Unity-How do I check if an object is seen by the Main Camera

user8048595 picture user8048595 · Sep 22, 2017 · Viewed 14k times · Source

I'm doing this thing where an object is moving on a plane, and the camera is in the center of it. I got it so the camera rotates along with the mouse, and when the main camera sees the game object, it stops. So I was using the onbecamevisible() and onbecameinvisible() functions, but that applies to any camera, including the scene view. How do I make it so the objects stops when seen only by the main game camera?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class cubeMove : MonoBehaviour,moveObject
{

Camera cam;
public Transform checkedObject;

void Start()
{
    cam = GetComponent<Camera>();
}



void Update()
{
    Vector3 viewPos = cam.WorldToViewportPoint(checkedObject.position);
    if ()
        move();
}

public void move()
{
    transform.Rotate(new Vector3(15, 30, 45) * Time.deltaTime);
}

}

Here's my Camera Script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Camera : MonoBehaviour {

public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityY = 15F;

public float minimumX = -360F;
public float maximumX = 360F;

public float minimumY = -60F;
public float maximumY = 60F;

float rotationX = 0F;
float rotationY = 0F;

private List<float> rotArrayX = new List<float>();
float rotAverageX = 0F;

private List<float> rotArrayY = new List<float>();
float rotAverageY = 0F;

public float frameCounter = 20;

Quaternion originalRotation;

void Update()
{
    if (axes == RotationAxes.MouseXAndY)
    {
        rotAverageY = 0f;
        rotAverageX = 0f;

        rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
        rotationX += Input.GetAxis("Mouse X") * sensitivityX;

        rotArrayY.Add(rotationY);
        rotArrayX.Add(rotationX);

        if (rotArrayY.Count >= frameCounter)
        {
            rotArrayY.RemoveAt(0);
        }
        if (rotArrayX.Count >= frameCounter)
        {
            rotArrayX.RemoveAt(0);
        }

        for (int j = 0; j < rotArrayY.Count; j++)
        {
            rotAverageY += rotArrayY[j];
        }
        for (int i = 0; i < rotArrayX.Count; i++)
        {
            rotAverageX += rotArrayX[i];
        }

        rotAverageY /= rotArrayY.Count;
        rotAverageX /= rotArrayX.Count;

        rotAverageY = ClampAngle(rotAverageY, minimumY, maximumY);
        rotAverageX = ClampAngle(rotAverageX, minimumX, maximumX);

        Quaternion yQuaternion = Quaternion.AngleAxis(rotAverageY, Vector3.left);
        Quaternion xQuaternion = Quaternion.AngleAxis(rotAverageX, Vector3.up);

        transform.localRotation = originalRotation * xQuaternion * yQuaternion;
    }
    else if (axes == RotationAxes.MouseX)
    {
        rotAverageX = 0f;

        rotationX += Input.GetAxis("Mouse X") * sensitivityX;

        rotArrayX.Add(rotationX);

        if (rotArrayX.Count >= frameCounter)
        {
            rotArrayX.RemoveAt(0);
        }
        for (int i = 0; i < rotArrayX.Count; i++)
        {
            rotAverageX += rotArrayX[i];
        }
        rotAverageX /= rotArrayX.Count;

        rotAverageX = ClampAngle(rotAverageX, minimumX, maximumX);

        Quaternion xQuaternion = Quaternion.AngleAxis(rotAverageX, Vector3.up);
        transform.localRotation = originalRotation * xQuaternion;
    }
    else
    {
        rotAverageY = 0f;

        rotationY += Input.GetAxis("Mouse Y") * sensitivityY;

        rotArrayY.Add(rotationY);

        if (rotArrayY.Count >= frameCounter)
        {
            rotArrayY.RemoveAt(0);
        }
        for (int j = 0; j < rotArrayY.Count; j++)
        {
            rotAverageY += rotArrayY[j];
        }
        rotAverageY /= rotArrayY.Count;

        rotAverageY = ClampAngle(rotAverageY, minimumY, maximumY);

        Quaternion yQuaternion = Quaternion.AngleAxis(rotAverageY, Vector3.left);
        transform.localRotation = originalRotation * yQuaternion;
    }
}

void Start()
{
    Rigidbody rb = GetComponent<Rigidbody>();
    if (rb)
        rb.freezeRotation = true;
    originalRotation = transform.localRotation;
}

public static float ClampAngle(float angle, float min, float max)
{
    angle = angle % 360;
    if ((angle >= -360F) && (angle <= 360F))
    {
        if (angle < -360F)
        {
            angle += 360F;
        }
        if (angle > 360F)
        {
            angle -= 360F;
        }
    }
    return Mathf.Clamp(angle, min, max);
}

}

SphereMove

public class sphereMove : MonoBehaviour,moveObject {

public float delta = 1.5f;  
public float speed = 2.0f;
private Vector3 startPos;

public UnityEngine.Camera cam;
public Transform checkedObject;
bool isMoving;

void Start()
{
    isMoving = true;
    cam = Camera.main;

}

void Update()
{

    Vector3 viewPos = cam.WorldToViewportPoint(checkedObject.position);
    if (viewPos.x > 0 && viewPos.x <= 1 && viewPos.y >= 0 && viewPos.y <= 1 && viewPos.z > 0)
        isMoving = false;
    else
        isMoving = true;

    if (isMoving)
        move();
}
public void move()
{
    Vector3 v = startPos;
    v.x += delta * Mathf.Sin(Time.time * speed);
    transform.position = v;
}

}

Answer

Isuka picture Isuka · Sep 22, 2017

You can use the Camera.WorldToViewport function, using your Main Camera to call it and giving in parameter the position of the object your are checking. If the x and y coordinates values of the result vector are between 0 and 1 and the z value is superior to 0, it means the center of your object is seen by your camera.

UnityEngine.Camera cam;
bool isMoving;

void Start()
{
    cam = UnityEngine.Camera.main;
    isMoving = true;
}

void Update()
{
    Vector3 viewPos = cam.WorldToViewportPoint(checkedObject.position);
    if (viewPos.x >= 0 && viewPos.x <= 1 && viewPos.y >= 0 && viewPos.y <= 1 && viewPos.z > 0)
    {
        // Your object is in the range of the camera, you can apply your behaviour
        isMoving = false;
    }
    else
        isMoving = true;

    if(isMoving)
        Move();
}