//速度和角度 if ((IsSing) || IsOnGround CurrentSpeed aircaft.MoveFBSpeed / 3.6f) return; if (CurrentSpeed aircaft.MoveFBSpeed / 3.6f speed 0) return; IsFBB = false; Balance(Quaternion.Euler(aircaft.AxisFB * speed, body.eulerAngles.y, body.eulerAngles.z), aircaft.RoteFBSpeed * Time.deltaTime * CurrentSpeed / aircaft.MoveFBSpeed); //print("RoteUD" + speed); public override void Balance()//飞机的平衡方法,当无输入事件时,飞机自动平衡 if (IsSing) return; if (IsLRB)//z轴平衡(左右) Balance(Quaternion.Euler(body.eulerAngles.x, body.eulerAngles.y, 0), aircaft.RoteLRSpeed * Time.deltaTime/1.2f ); if (IsFBB)//x轴平衡(上下) Balance(Quaternion.Euler(0, body.eulerAngles.y, body.eulerAngles.z), aircaft.RoteFBSpeed * Time.deltaTime /1.3f); IsLRB = true;//自动平衡打开 IsFBB = true;//自动平衡打开 }
都是非常简单的代码,关键是如何使用,以及逻辑的处理。
为了增加飞机飞行的效果,我还设计了飞机的特技飞行:90度转角的左右飞行,以及180度翻转飞行。当然也是使用了基础的公式完成的。左右90度特技飞行:飞机侧身90度,并大角度的转角转向飞机的左或右方。获取相对于飞机在世界坐标的左/右方向V,然后通过判断当前方向与V的角度,来判定是否完成特技飞行。180度转角飞行:飞机绕自身x轴180度旋转,然后恢复平衡。
因为特技飞行的完成需要一段时间,而这段时间是玩家不需要控制,系统完成后进入正常状态的,所以用到需要协程。
IEnumerator SLR(float speed) { //90度转角飞行 speed = (speed 0 ? 1 : -1); Vector3 aim = body.right * (speed); aim.y = 0; while(Vector3.Dot(aim.normalized,body.forward.normalized) 0.99f){ Rote(speed * Vector3.up * aircaft.RoteLRSpeed * Time.deltaTime); Balance(Quaternion.Euler(body.eulerAngles.x, body.eulerAngles.y, -85 * (speed )), aircaft.RoteLRSpeed * Time.deltaTime*3.8f); Balance(Quaternion.Euler(0, body.eulerAngles.y, body.eulerAngles.z), aircaft.RoteFBSpeed * Time.deltaTime *1.8f); yield return new WaitForFixedUpdate(); while ((body.eulerAngles.z 15) (body.eulerAngles.z 180) || (body.eulerAngles.z 345) (body.eulerAngles.z 270)) Balance(Quaternion.Euler(0, body.eulerAngles.y, body.eulerAngles.z), aircaft.RoteFBSpeed * Time.deltaTime); Balance(Quaternion.Euler(body.eulerAngles.x, body.eulerAngles.y, 0), aircaft.RoteLRSpeed * Time.deltaTime * 3); yield return new WaitForFixedUpdate(); IsSing = false; public override void StuntUD(float axis) if ((IsSing) || IsOnGround CurrentSpeed aircaft.MoveFBSpeed / 3.6f) return; if (!IsSing) IsSing = true; StartCoroutine(SUD(axis)); IEnumerator SUD(float speed) //180度翻转 speed = (speed 0 ? 1 : -1); Vector3 aim = -body.forward ; aim.y = 0; while (Vector3.Dot(aim.normalized, body.forward.normalized) 0.8f)//飞机翻转 Vector3 v = body.right; v.y= 0; Rote(body.right * Time.deltaTime * -90 * speed); Move(-Vector3.up * speed * Time.deltaTime * 10 * (CurrentSpeed / (aircaft.OffSpeed))); //body.Rotate(Vector3.right * Time.deltaTime * -90,Space.Self); //Balance(Quaternion.Euler(body.eulerAngles.x, body.eulerAngles.y, 0), aircaft.RoteLRSpeed * Time.deltaTime*5); yield return new WaitForFixedUpdate(); while ((body.eulerAngles.z 15) (body.eulerAngles.z 180) || (body.eulerAngles.z 345) (body.eulerAngles.z 270))//翻转后飞机完成平衡 Balance(Quaternion.Euler(0, body.eulerAngles.y, body.eulerAngles.z), aircaft.RoteFBSpeed * Time.deltaTime ); Balance(Quaternion.Euler(body.eulerAngles.x, body.eulerAngles.y, 0), aircaft.RoteLRSpeed * Time.deltaTime*3); yield return new WaitForFixedUpdate(); IsSing = false; }
以上是飞机的飞行模拟思路以及基本算法实现。玩家操作的代码就是输入检测之类的,然后再调用一下飞行接口就行了,我就不提供了。
接下来的问题就是AI飞行了,由电脑逻辑控制的AI飞行。如上图,是由计算机控制的飞行。这个AI就一个核心方法,就是飞到目标点。要实现这个功能也很简单,就是计算一下目标点的距离,角度等。然后根据距离以及当前状态控制加减速度,通过角度控制转向。主要使用到Vector.Dot(v1,v2);,然后就是各种情况下的判断和飞行方法的调用。例如当目标在飞机的后方时,可以调用180度翻转,来锁定目标。
好,我们简单的分析一下如何去写这个AI,获取目标Point,计算距离差,高度差,角度差。通过高度差,控制飞机的升降,距离差控制速度,角度差控制转向。
嗯,下面就是实现的代码。
public void MoveToPoint(Vector3 point, float stopDistance) { Vector3 hPoint = point; hPoint.y = flight.body.position.y; hDistence = Vector3.Distance(hPoint, flight.body.position);//水平距离 distence = Vector3.Distance(point, flight.body.position);//距离 dHeight = point.y - flight.body.position.y;//高度差 vector = (point - flight.body.position).normalized; dUDAgle = Vector3.Dot(vector, flight.body.TransformDirection(Vector3.up).normalized); //获取目标点与当前位置的距离,高度差,判断目标相对于当前位置的前/后,左/右 dFBAgle = Vector3.Dot(vector, (flight.body.TransformDirection(Vector3.forward)).normalized);//判断目标点相对于当前位置的前后 //print(forward); dLRAgle = Vector3.Dot(vector, (flight.body.TransformDirection(Vector3.right)).normalized);//判断目标点相对于当前位置的左右