Unity Camera Quaternion.RotateTowards没有滚动/银行业务

时间:2017-08-20 19:46:17

标签: c# unity3d camera rotation quaternions

我有一台摄像机朝向地面,我想要向上看以远处看目标物体。

目前,我通过以下方式实现了这一目标:

Vector3 dir = targetPoint - transform.position;
Quaternion lookRotation = Quaternion.LookRotation(dir);
Quaternion newRotation = Quaternion.RotateTowards(transform.rotation, lookRotation, rotationDamping * Time.deltaTime);
transform.rotation = newRotation;

相机执行旋转并最终正确指向目标物体,但随着相机平移,它会向一侧倾斜,使我的游戏世界与观察者成一定角度,这非常迷惑:

Camera rotation example 1

如何以某种方式限制摄像机角度,使地平线始终与摄像机平齐?

谢谢!

更新

在下面添加@Isaac建议的线会产生相对于地平线的正确旋转,但是它会在开始时突然切换到z = 0,这仍然不是我正在寻找的。

transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, 0);

Camera rotation example 2

3 个答案:

答案 0 :(得分:1)

经过实验,我根据你的需要找到了两种可能的解决方案。

如果您只是想跟随目标,我建议使用LookAt,它会自动与世界对齐。在您的代码中(在更新中)transform.LookAt(dir);

如果您需要/想要平移效果,请在更新旋转后设置localEulerAngles。这就是我所做的工作:

//this is your code
    Vector3 dir = targetPoint - transform.position;
    Quaternion lookRotation = Quaternion.LookRotation(dir);
    Quaternion newRotation = Quaternion.RotateTowards(transform.rotation, lookRotation, rotationDamping * Time.deltaTime);
    transform.rotation = newRotation;

//this is what I added
    transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, 0);

使用四元数更新旋转后,添加简单地采用相机所面向的方式,并将z旋转设置为零。

如果您有任何疑问,请告诉我们。)

/////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////

新信息/编辑:

我相信我找到了一个解决方案,但它很难看,我会很感激它是否口吃等反馈。

此代码与以前基本相同,但现在它检查以查看z角度并使用名为zDamping的变量手动编辑它,这会影响相机围绕z访问旋转的速度

我在更新之外添加了:

public float zDamping; //public only for testing, it's convenient for finding an optimal value
private bool rotationCheck = false;

然后在update()内:

//This is your code (unchanged)
        Vector3 targetPoint = target.transform.position;
        Vector3 dir = targetPoint - transform.position;
        Quaternion lookRotation = Quaternion.LookRotation (dir);
        Quaternion newRotation = Quaternion.RotateTowards (transform.rotation, lookRotation, rotationDamping * Time.deltaTime);

//This is what is new (remove my addition from before edits or it won't work)
        if (transform.localEulerAngles.z >= 180f && transform.localEulerAngles.z <= 359f && !rotationCheck) {
            transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, transform.localEulerAngles.z + (rotationDamping * zDamping));
            transform.rotation = newRotation;
        } 
        else if (transform.localEulerAngles.z <= -180f && transform.localEulerAngles.z >= 1f && !rotationCheck) {
            transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, transform.localEulerAngles.z - (rotationDamping * zDamping));
            transform.rotation = newRotation;
        }
        else {
            transform.rotation = newRotation;
            transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, 0);
            rotationCheck = true;
        }

正如我所说,这个解决方案非常难看,但可能会有效。你必须看看zDamping值对你的速度看起来是否有效(我建议从.01开始)。一旦接近该值,也会有一个小的“跳跃”,但是你越接近360 359f1f越接近该跳越小。使它太小的危险是如果你超调,但它应该工作,即使它超过,但它将需要一点时间。

测试一下,让我知道你的想法,对不起,我现在找不到更优雅的东西。我还尝试添加一个单独的四元数来专门旋转z轴,但它不起作用;随便尝试一下,如果你想,我可以提供更多关于我所做的事情的细节。

祝你好运,再次,对于草率的解决方案感到抱歉。

答案 1 :(得分:1)

在这个问题上有一个很好的Q/A on gamedev.stackexchange。您应该尝试那里建议的俯仰/偏航系统。
另一个建议是在旋转过程中纠正相机的滚动。

public float rollCorrectionSpeed; 
public void Update()
{
    float roll = Vector3.Dot(transform.right, Vector3.up);
    transform.Rotate(0, 0, -roll * rollCorrectionSpeed);

    Vector3 dir = targetPoint.position - transform.position;
    Quaternion lookRotation = Quaternion.LookRotation(dir);
    Quaternion newRotation = Quaternion.RotateTowards(transform.rotation, lookRotation, rotationDamping * Time.deltaTime);
    transform.rotation = newRotation;
} 

编辑:
有一个更简单的解决方案:只需将正在旋转的四元数的z旋转保持为0。

public void Update()
{
    Vector3 angles = transform.rotation.eulerAngles;
    Quaternion from = Quaternion.Euler(angles.x, angles.y, 0);

    Vector3 dir = targetPoint.position - transform.position;        
    Quaternion to = Quaternion.LookRotation(dir);

    transform.rotation = Quaternion.RotateTowards(from, to, rotationDamping * Time.deltaTime);
}

答案 2 :(得分:0)

在您的行中添加了一个代码,希望它能解决问题。

Vector3 dir = targetPoint - transform.position;
Quaternion lookRotation = Quaternion.LookRotation(dir);
Quaternion newRotation = Quaternion.RotateTowards(transform.rotation, lookRotation, rotationDamping * Time.deltaTime);
newRotation.eulerAngles = new Vector3(newRotation.eulerAngles.x,newRotation.eulerAngles.y,transform.rotation.eulerAngles.z);
transform.rotation = newRotation;