赞
踩
最近做个雷达地屏的项目,需要在平面内(地面是图)踩地面场景,踩到动物(上层是动物模型)后有个伪3D的场景交互的效果,涉及到动物朝向目标(cube代替的目标点)跑的问题,最初想到最简单的transform.LookAt方法,但是实际测试之后,他会x、y、z都会相对朝向目标,这样就导致可能某次朝向目标点时,动物朝着目标点时会翻身背朝下,这样就导致了我必须要寻找一种方式去只使某一个轴旋转朝向目标即可,所以就自己参考一些资料后,写出自己的一些想法来。
配图:实现点击到小白兔后朝向随机cube的方向跑
有人和我推荐过在LookAt之后,再将其他两个轴向重置,但这样的做法不是聪明的做法,其次,在使用了lookAt之后,是没有办法控制那个轴来实现朝向,如果他旋转朝向,旋转用的轴是你重置的轴,那么被你重置后,就又会导致朝向不对,还有人给我建议过用AI(NavMeshAgent)组件来做,我想我都做了这些功夫了,翻新做那是不可能的了。
配图:因为各种朝向计算导致兔子没有站立在地面上
配图有点类似于这个API的味道:public static Quaternion RotateTowards (Quaternion from, Quaternion to, float maxDegreesDelta);//描述:将旋转 from 向 to 旋转
所以我猜测他的底层应该有个最优计算旋转朝向的算法,当然我们是要去解决问题的,所以我理清了思路,参照底下的代码,大致如下:
1.首先我们要定义是那个轴去朝向目标
2.要去计算轴的向量和目标位置到自身的向量之间的夹角
3.用计算 Vector3.Cross垂直于当前方向和目标方向的轴
4.使用Quaternion.AngleAxis将当前朝向向目标方向旋转
配图:做到以上几点也差不多实现了一个LookAt功能了
↑↑↑由于这个算法和LookAt最大的区别就是他是能控制某个轴,可以在定义的轴上实现朝向,因为我们只需要让Y轴上旋转朝向目标方位,所以我又重置了X、Z的轴向不变↓↓↓
5.tr_self.localEulerAngles = new Vector3(0, tr_self.localEulerAngles.y, 90);//后来调试增加的,因为我想让x,z轴向不会有任何变化,只使用Y轴实现了动物的转向功能
/// <summary> /// 用某个轴去朝向物体 /// </summary> /// <param name="tr_self">朝向的本体</param> /// <param name="lookPos">朝向的目标</param> /// <param name="directionAxis">方向轴,取决于你用那个方向去朝向</param> void AxisLookAt(Transform tr_self, Vector3 lookPos, Vector3 directionAxis) { var rotation = tr_self.rotation; var targetDir = lookPos - tr_self.position; //指定哪根轴朝向目标,自行修改Vector3的方向 var fromDir = tr_self.rotation * directionAxis; //计算垂直于当前方向和目标方向的轴 var axis = Vector3.Cross(fromDir, targetDir).normalized; //计算当前方向和目标方向的夹角 var angle = Vector3.Angle(fromDir, targetDir); //将当前朝向向目标方向旋转一定角度,这个角度值可以做插值 tr_self.rotation = Quaternion.AngleAxis(angle, axis) * rotation; tr_self.localEulerAngles = new Vector3(0, tr_self.localEulerAngles.y, 90);//后来调试增加的,因为我想让x,z轴向不会有任何变化 }
void Update()
{
AxisLookAt(this.transform, m_tr_Random[0].position, Vector3.up);//朝向目标体
}
朝向的问题之前老是弄不好,网上也试过很多代码,都会或多或少有些许问题,今天刚实现后,下班后就马上更新了文章,代码简单做过测试可行,参照最上面的gif图,如果有什么不足之处多多包涵,我会认真听取您的意见。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。