1

我如何设置合适的截锥体大小,以便移动相机需要始终将对象(例如 3D 模型)完全保持在场景中,而不能靠得太近以至于该对象的一部分被切断.

模型不动。

4

1 回答 1

0

如果相机始终指向您的对象并且对象位于屏幕中心,您可以在此处轻松解决此问题https://docs.unity3d.com/Manual/FrustumSizeAtDistance.html 。但一般来说,这个类可以完成任务. 首先,您需要考虑一个围绕您的对象的虚拟球体,它完全包含您的对象,并且此代码可避免对象离开屏幕。

public class PutObjectAlwaysInScreen : MonoBehaviour {

//Object Transform that should be in the screen
public Transform Target;
//Considering a sphere around your object according to its size
public float Radius;

void check()
{
    //Finding a frustum plate that include object position point
    //the vector from camera to frustum plate
    Vector3 Vcenter = Camera.main.transform.forward;
    //Vector between camera and object
    Vector3 VcameraToObject = Target.position - Camera.main.transform.position;
    //The angle between center of frustum and object postion
    float CosTeta = Vector3.Dot(Vcenter,VcameraToObject)/(Vcenter.magnitude * VcameraToObject.magnitude);
    //distance between camera and frustum
    float distance = VcameraToObject.magnitude * CosTeta;
    //Center of frustum plate
    Vector3 Fcenter = Camera.main.transform.position + distance * (Vcenter/Vcenter.magnitude);
    //Vector between center of frustum and object
    Vector3 FrustumToObject = Target.position - Fcenter;
    //Width And Height of the distance between center of frustum and object in the screen
    float W = Vector3.Dot(FrustumToObject,Camera.main.transform.right);
    float H = Vector3.Dot(FrustumToObject,Camera.main.transform.up);
    //frustum Width and Height
    float frustumHeight = 2.0f * distance * Mathf.Tan(Camera.main.fieldOfView * 0.5f * Mathf.Deg2Rad);
    float frustumWidth = frustumHeight * Camera.main.aspect;
    //Check if the object is out of the screen
    if( ((Mathf.Abs(W)+Radius)>frustumWidth) || ((Mathf.Abs(H)+Radius)>frustumHeight) )
    {
        // Do Something
        // You Can Avoid Camera from getting closer to the Object

        //or With the below formulae adjust the fieldOfView
        if((Mathf.Abs(W)+Radius)>frustumHeight)
            Camera.main.fieldOfView = 2.0f * Mathf.Atan((Mathf.Abs(H)+Radius) * 0.5f / distance) * Mathf.Rad2Deg;
        if((Mathf.Abs(W)+Radius)>frustumWidth)
            Camera.main.fieldOfView = 2.0f * Mathf.Atan(((Mathf.Abs(W)+Radius)/Camera.main.aspect) * 0.5f / distance) * Mathf.Rad2Deg;
    }


}

    void Update() {
    check();
    }
}
于 2020-03-25T00:05:36.570 回答