无论网上找到的方法怎么样,我都得尝试去做一下坦克炮塔的瞄准系统
好吧,我直接承认到最后我还没有完全做出来,炮管依旧不按照我的想法跑,但是确实也初具效果了
炮塔会跟着转了,但是炮管依然有自己的想法
直接上代码,大概什么原理我想注释以及说的差不多了,这里就放炮塔的吧
// 用于存储瞄准的方向
Vector3 aimPosition = Vector3.zero;
// 用于确定射线的落点
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float distance;
Plane plane = new Plane(Vector3.up, raycastTarget.position);
if (plane.Raycast(ray, out distance))
{
aimPosition = ray.origin + ray.direction * distance;
}
// 炮塔的实际旋转
Vector3 turretPos = aimPosition;
turretPos.y = turret.position.y; //过滤掉y轴的信息,防止炮塔出现绕x,z轴旋转的问题
Quaternion aimRotTurret = Quaternion.RotateTowards(turret.rotation,
Quaternion.LookRotation(turretPos - turret.position, Vector3.up), Time.deltaTime * rotateSpeed);
turret.rotation = aimRotTurret;
最核心的部分就是用Quaternion.RotateTowards这个方法来实现那种炮塔慢慢转过去的效果,这个方法简直就是量身定制的。需要的参数是:初始的rotation(炮塔的位置),目标rotation,还有就是旋转速度是多少。然后我们拿着他的返回值每一帧赋值给炮塔的rotation就行了。看网上说这个方法应该类似于lerp,我反正有点不求甚解了(能用就行)。
然后还有一个关键问题就是我们要确定目标rotation是多少,首先通过一条沿摄像机正前方发出的射线,打在一个永远在摄像机前方,并且位置保证永远在炮塔的前面(相对摄像机来看在炮塔前面)的Plane,来获得一个Vector3 aimPosition,这个aimPosition就是我们要把炮管对准的位置,接下来,对于炮塔而言,要过滤掉aimPosition来自Y轴的影响,否则炮塔会变成摇摆炮塔
炮塔刚刚说了,我觉得目前来看相当成功,但是炮管就没有那么顺利了,我的想法就是,炮管依然是aimPosition,但是过滤掉x,z轴的影响就行了。但是情况很不如愿,炮管是炮塔的一部分,炮塔旋转炮管理应跟着旋转,如果忽视,炮塔跑了炮管还在原地杵着,如果不忽略,炮管会比炮塔抢先一步归位,而当前情况是一种我也无法形容的状态。。。也许是因为0不对。现在以及有点晚了,明天再做吧。
// 炮管的实际旋转(有问题)
Vector3 gunPos = aimPosition;
gunPos.x = 0;
gunPos.z = 0; //类似的过滤操作
Quaternion aimRotGun = Quaternion.RotateTowards(gun.rotation,
Quaternion.LookRotation(gunPos - gun.position, Vector3.up), Time.deltaTime * rotateSpeed);
gun.rotation = aimRotGun;
炮管旋转问题已于当天晚上解决。方法如下:
// 炮管的实际旋转(BUG已经修好)
Vector3 gunPos = aimPosition;
Quaternion aimRotGun = Quaternion.RotateTowards(gun.rotation,
Quaternion.LookRotation(gunPos - gun.position), Time.deltaTime * rotateSpeed);
// 让localRotation的y,z轴不要转
gun.localRotation = Quaternion.Euler(aimRotGun.eulerAngles.x, 0f, 0f);
方法就是,在最后要给gun.localRotation赋值时再做点事情,aimRotGun.eulerAngles.x是我们要用到的旋转轴,y,z轴直接设置为0就好了。