我有一台摄像机朝向地面,我想要向上看以远处看目标物体。
目前,我通过以下方式实现了这一目标:
Vector3 dir = targetPoint - transform.position;
Quaternion lookRotation = Quaternion.LookRotation(dir);
Quaternion newRotation = Quaternion.RotateTowards(transform.rotation, lookRotation, rotationDamping * Time.deltaTime);
transform.rotation = newRotation;
相机执行旋转并最终正确指向目标物体,但随着相机平移,它会向一侧倾斜,使我的游戏世界与观察者成一定角度,这非常迷惑:
如何以某种方式限制摄像机角度,使地平线始终与摄像机平齐?
谢谢!
更新
在下面添加@Isaac建议的线会产生相对于地平线的正确旋转,但是它会在开始时突然切换到z = 0,这仍然不是我正在寻找的。 p>
transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, 0);
答案 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 359f
而1f
越接近该跳越小。使它太小的危险是如果你超调,但它应该工作,即使它超过,但它将需要一点时间。
测试一下,让我知道你的想法,对不起,我现在找不到更优雅的东西。我还尝试添加一个单独的四元数来专门旋转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;