勇敢的树袋熊1 发表于 2020-12-21 10:53

Unity中设置forward/up/right旋转异常问题

本文首发于洪流学堂微信公众号。洪流学堂公众号回复forward,获取本文的测试工程。
小新:“智哥,我在设置人物持枪IK时,想要将枪的方向设置为光标的方向。但是出现了枪旋转混乱的问题,这个该怎么解决啊?”
大智:“具体说说看你是怎么实现的?”
小新:“我先计算了枪的朝向的向量,代码是这样的”
想深入了解大智和小新这对好基友,可以在洪流学堂公众号回复小新了解他们。var pos = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width / 2, Screen.height / 2, 10));
var direction = (pos - _currentGun.transform.position).normalized;小新:“这不计算出来方向了嘛,我觉得最简单的方法就是设置枪的transform里面的forward向量。但是我先设置场景为pivot模式(显示物体的自身坐标轴),然后看了枪的轴以后,发现枪口方向的轴不是forward,而是红色的轴,也就是right。”



红色的轴为枪口方向的反方向
大智:“没错,这点很好,就是不要想当然的用forward/up/right这些轴,一定要根据实际情况。forward是蓝色的轴,up是绿色的轴,right是红色的轴。记不清楚的时候可以看下Scene窗口右上角的小工具的颜色。”



Scene窗口右上角的小工具
小新:“然后我就设置枪的transform的right为-direction,就像这样”
_currentGun.transform.right = -direction;小新:“结果运行起来是这个样子,上下旋转没啥问题,但是左右旋转枪会发生翻转”



枪会发生翻转.gif
大智:“好,我大概了解了。你使用了transform的right属性,但是你知不知道设置right的具体内部代码是什么?”
小新:“这个我还真不知道”
大智:“Unity已经公布了C#端的所有源码,这个你可以去 https://github.com/Unity-Technologies/UnityCsReference 里面查看。你去看看Transform类中的forward/up/right是怎么定义的”
小新赶忙打开这个链接,去找相关的内容。
小新:“在Github网站上找好麻烦,我还是把它下载下来”
大智:“非常明智,下载下来以后通过VS打开可以快速找到想要的内容”
小新:“找到了!在Transform.bindings.cs文件的第41行”
// The red axis of the transform in world space.
public Vector3 right { get { return rotation * Vector3.right; } set { rotation = Quaternion.FromToRotation(Vector3.right, value); } }

// The green axis of the transform in world space.
public Vector3 up { get { return rotation * Vector3.up; } set { rotation = Quaternion.FromToRotation(Vector3.up, value); } }

// The blue axis of the transform in world space.
public Vector3 forward { get { return rotation * Vector3.forward; } set { rotation = Quaternion.LookRotation(value); } }大智:“你仔细看看这三个属性在set的时候内部具体是如何实现的”
小新:“对于right和up,他用了Quaternion.FromToRotation来创建了一个四元数,但是起始位置用的是世界坐标轴的right和up”



枪的默认朝向
大智:“没错,起始位置用的是世界坐标轴的right和up,而枪的初始姿态不正常,因为是平躺在地上的而不是竖着的状态,需要将枪的朝向调整为拿在手中时的朝向,比如将枪调成竖着的状态。对于这个枪Quaternion.FromToRotation在计算旋转的时候就会出现不正常的情况。这时候有两种解决方式:”
通过给枪加一个空的父物体,调整好枪的朝向,使用这个父节点进行旋转,这样枪就不会沿着x轴旋转了,旋转也就正确了。



调整过朝向的枪
不使用transform的right进行设置,而是自己计算旋转。代码也很简单,如下:
var rot = Quaternion.FromToRotation(-_currentGun.transform.right, direction);
_currentGun.transform.rotation = rot * _currentGun.transform.rotation;大智:“这种方式在物体原来旋转的基础上进行旋转叠加,不会出现旋转乱掉的问题。”
总结

小新:“以后再遇到问题我要探究问题的深层次原因,不能仅限于将问题解决这个表象。”
大智:“这么想就对了,这样才能进步的更快!”
今日思考题

下载测试工程,深入了解下这个问题的原因和解决办法吧!
洪流学堂公众号回复forward,获取本文的测试工程。
欢迎在留言区分享你的收获,和大家一起讨论。
别忘了分享给你学Unity的朋友,也许能够帮到他。
页: [1]
查看完整版本: Unity中设置forward/up/right旋转异常问题