Unity - 如何检查主摄像头是否看到某个对象

时间:2017-09-22 12:21:50

标签: c# unity3d camera gameobject

我正在做一件物体在飞机上移动的东西,而相机就在它的中心。我得到了它,所以相机随着鼠标一起旋转,当主相机看到游戏对象时,它就会停止。所以我使用的是onbecamevisible()和onbecameinvisible()函数,但这适用于任何相机,包括场景视图。如何仅在主游戏相机看到物体时才能制作它?

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);
}

}

这是我的相机脚本

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;
}

}

2 个答案:

答案 0 :(得分:2)

您可以使用Camera.WorldToViewport功能,使用主摄像头调用它并在参数中输入您正在检查的对象的位置。如果结果向量的x和y坐标值介于0和1之间且z值高于0,则表示相机可以看到对象的中心。

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();
}

答案 1 :(得分:2)

建议的方法在您的情况下不起作用,因为您创建了一个名为Camera的类,其名称与Unity的{​​{1}}组件完全相同。

我建议您使用community wiki中的方法。它非常简单易懂,可让您检查每个摄像头的可见度。

您可以为Camera组件创建扩展类:

Camera

你可以像这样分别从每个对象中调用它:

public static class CameraEx
{
    public static bool IsObjectVisible(this UnityEngine.Camera @this, Renderer renderer)
    {
        return GeometryUtility.TestPlanesAABB(GeometryUtility.CalculateFrustumPlanes(@this), renderer.bounds);
    }
}

在这里,您可以找到有关GeometryUtility

的完整文档