坦克瞄准系统的开发记录——Unity随手记(2020.11.16)

无论网上找到的方法怎么样,我都得尝试去做一下坦克炮塔的瞄准系统
好吧,我直接承认到最后我还没有完全做出来,炮管依旧不按照我的想法跑,但是确实也初具效果了
炮塔会跟着转了,但是炮管依然有自己的想法
炮塔会跟着转了,但是炮管依然有自己的想法

直接上代码,大概什么原理我想注释以及说的差不多了,这里就放炮塔的吧

            // 用于存储瞄准的方向
            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就好了。

猜你喜欢

转载自blog.csdn.net/qq_37856544/article/details/109730863