unity3d 飞机 飞行

2019-03-01 16:50:57 beiluo77 阅读数 1260

Unity学习笔记:Unity 3D 飞机大战

1、打开unity软件后,首先新建Quad作为背景,导入飞机模型,并为其添加刚体
然后创建C#脚本,挂载到飞机上。
2、给飞机创建子弹,让子弹成为预制体,同样创建C#脚本
3、创建陨石和敌机作为敌方,飞机发射子弹使其销毁,如果飞机与敌方相撞,则飞机爆炸消失。

放上完成后的图:
在这里插入图片描述
给飞机设置的组件:
alt
子弹的组件:
在这里插入图片描述
陨石的组件:
在这里插入图片描述
敌机和其子弹的组件与飞机类似,就不放图了~

接下来是代码:
1、飞机脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/** 玩家飞机飞行的脚本 */
public class PlayerMovement : MonoBehaviour
{
    /** 飞机可以飞行的区域 */
    public float xMax;
    public float xMin;
    public float zMax;
    public float zMin;

    /** 飞机自身的刚体 以及 飞机发射子弹的位置 */
    Rigidbody _plane_rig;           
    Transform _plane_fire_point;

    /** 子弹的预制体 */
    GameObject _bullet;

    private void Awake()
    {
        //获取刚体
        _plane_rig = this.GetComponent<Rigidbody>();
        //获取开火位置
        _plane_fire_point = transform.GetChild(1);
        //获取子弹的预制体
        //通过资源加载的方式获取预制体
        _bullet = Resources.Load("Prefabs/Bullet") as GameObject;
    }

    private void FixedUpdate()
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        //飞机移动
        Move(h, v);
        //飞机开火
        Shoot();
    }

    /** 飞机的飞行速度 以及飞机的倾斜度 */
    public float plane_speed = 3f;
    public float plane_Tilt = 2f;
    void Move(float h,float v)
    {
        //1.获取飞机移动的方向
        Vector3 plane_fly_dir = new Vector3(h, 0, v);
        //2.设定飞机的飞行速度
        _plane_rig.velocity = plane_fly_dir * plane_speed;
        //3.移动
        _plane_rig.position = new Vector3
            (
                //Mathf.Clamp(x,y,z)的作用是将x限定在y和z之间
                Mathf.Clamp(_plane_rig.position.x,xMin,xMax),
                5f,
                Mathf.Clamp(_plane_rig.position.z,zMin,zMax)
            );
        //4.设置飞机倾斜度
        _plane_rig.rotation = Quaternion.Euler(0f, 0f, _plane_rig.velocity.x * -plane_Tilt);
    }


    float _shoot_rate = 0.5f;
    float _timer = 0f;
    void Shoot()
    {
        //计时
        _timer += Time.deltaTime;
        //按下鼠标左键
        if (Input.GetMouseButton(0) && _timer >= _shoot_rate)
        {
            //在_plane_fire_point.position的位置生成_bullet实例,保持_plane_fire_point.rotation的旋转
            Instantiate(_bullet, _plane_fire_point.position, _plane_fire_point.rotation);
            //重置定时器
            _timer = 0f;
        }
    }
}

2、子弹的脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BulletMovement : MonoBehaviour
{
    /** 子弹的飞行速度 */
    public float bullet_speed = 20f;

    private void FixedUpdate()
    {
        this.GetComponent<Rigidbody>().velocity = bullet_speed * transform.forward;
    }
}

3、陨石的脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AsteroidMove : MonoBehaviour
{
    //陨石的移动速度集合
    float[] _asteroid_speeds = { 8, 10, 13, 16 };

    private void Awake()
    {
        //左闭右开 [0,4)
        int index = Random.Range(0, _asteroid_speeds.Length);

        this.GetComponent<Rigidbody>().velocity = Vector3.back * _asteroid_speeds[index];
    }

}

陨石旋转

 //陨石旋转的速率集合
    float[] rotRations = { 4f, 6f, 8f };

    private void Awake()
    {
        int index = Random.Range(0, rotRations.Length);

        //Random.insideUnitSphere 随机返回球体(半径为1的球体)内部的任意一点
        this.GetComponent<Rigidbody>().angularVelocity = Random.insideUnitSphere * rotRations[index];
    }

陨石爆炸

/** 爆炸效果预制体 */
    public GameObject asteroidExp;
    public GameObject playerExp;

    private void OnTriggerEnter(Collider other)
    {
        //碰到陨石或者是敌方飞机 不处理直接返回
        if (other.gameObject.tag == "Asteroid" || other.gameObject.tag == "Enemy" || other.gameObject.tag == "EBullet")
            return;

        //碰到了子弹
        if(other.gameObject.tag == "Bullet")
        {
            //生成爆炸体
            GameObject exp = Instantiate(asteroidExp, transform.position, transform.rotation);
            //销毁
            Destroy(exp, 0.3f);
        }

        //碰到了玩家
        if(other.gameObject.tag == "Player")
        {
            //生成爆炸体
            GameObject exp = Instantiate(playerExp, transform.position, transform.rotation);
            //销毁
            Destroy(exp, 0.3f);
        }

        //销毁碰到的物体
        Destroy(other.gameObject);
        //销毁自身
        Destroy(transform.gameObject);

    }

以及陨石的管理

 /** 三个陨石预制体 */
    GameObject _Asteroid_01;
    GameObject _Asteroid_02;
    GameObject _Asteroid_03;

    /** 存放所有的陨石 */
    List<GameObject> _Asteroids;

    private void Awake()
    {
        //初始化陨石集合
        _Asteroids = new List<GameObject>();

        //通过资源加载的方式先获取到三个陨石
        _Asteroid_01 = Resources.Load("Prefabs/Asteroid_01") as GameObject;
        _Asteroid_02 = Resources.Load("Prefabs/Asteroid_02") as GameObject;
        _Asteroid_03 = Resources.Load("Prefabs/Asteroid_03") as GameObject;

        //将三个陨石加入到集合中
        _Asteroids.Add(_Asteroid_01);
        _Asteroids.Add(_Asteroid_02);
        _Asteroids.Add(_Asteroid_03);
    }

    private void Start()
    {
        //重复调用某一个方法
        InvokeRepeating("CreateAsteroid", 0f, 3f);
    }

    void CreateAsteroid()
    {
        //1.随机从集合中取出陨石
        GameObject asteroid = _Asteroids[Random.Range(0, _Asteroids.Count)];
        //2.创建随机位置
        Vector3 asteroidPos = 
            new Vector3(Random.Range(transform.position.x, -transform.position.x), 5f, 17.52f);
        //3.创建陨石
        Instantiate(asteroid, asteroidPos, Quaternion.identity);
    }

    private void OnApplicationQuit()
    {
        //当程序结束的时候取消invoke的重复调用
        CancelInvoke("CreateAsteroid");
    }

4、最后是敌机和其子弹

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyShip : MonoBehaviour {

    //敌机的移动速度集合
    float _enemy_speeds = 3f;
    Transform _eplane_fire;

    /** 敌机子弹的预制体 */
    GameObject _ebullet;

    private void Awake()
    {
        //左闭右开 [0,4)
        this.GetComponent<Rigidbody>().velocity = Vector3.back * _enemy_speeds;
        transform.eulerAngles = new Vector3(transform.eulerAngles.x, 180, transform.eulerAngles.z);

        //获取开火位置
        _eplane_fire = transform.GetChild(1);
        //获取子弹的预制体
        //通过资源加载的方式获取预制体
        _ebullet = Resources.Load("Prefabs/EBullet") as GameObject;

    }

    private void FixedUpdate()
    {
        //敌机开火
        Shoot();
    }

    float _shoot_rate = 2f;
    float _timer = 0f;
    void Shoot()
    {
        //计时
        _timer += Time.deltaTime;
        if (_timer >= _shoot_rate)
        {
            //在_plane_fire_point.position的位置生成_bullet实例,保持_plane_fire_point.rotation的旋转
            Instantiate(_ebullet, _eplane_fire.position, Quaternion.identity);
            //重置定时器
            _timer = 0f;
        }
    }
}

(敌机的爆炸及其子弹的爆炸和陨石爆炸代码类似,下面就不放了)


5、最后的最后(终于要完成了~)给敌机设置管理

/** 敌机 */
    GameObject _enemys;

    private void Awake()
    {
        //通过资源加载的方式先获取到敌机
        _enemys = Resources.Load("Prefabs/EnemyShip") as GameObject;
    }

    private void Start()
    {
        //重复调用某一个方法
        InvokeRepeating("CreateEnemy", 0f, 3f);
    }

    void CreateEnemy()
    {
        
        //1.创建随机位置
        Vector3 enemyPos =
            new Vector3(Random.Range(transform.position.x, -transform.position.x), 5f, 17.52f);
        //2.创建陨石
        Instantiate(_enemys, enemyPos, Quaternion.identity);
    }

    private void OnApplicationQuit()
    {
        //当程序结束的时候取消invoke的重复调用
        CancelInvoke("CreateEnemy");
    }

撒花!!!一个飞机大战小游戏就完成了,用 unity 做这款小游戏有些大材小用,却也的确比用 h5 简单很多!

2014-09-05 21:11:34 yangyisen0713 阅读数 6727

以下是个人对unity3dAircraftSimulator飞行模拟器包的使用方法的总结,以便自己和大家日后查看。

一、AircraftSimulator飞行模拟器(.unitypackage)资源效果图:

二、使用方法:

将AircraftSimulator的package导入u3d后,在AssetsUnityFS目录有一个名为Getting Started的PDF说明文档,里面说的还算比较详细。大家英语不好没关系,接着往下看!


在Assets\UnityFS\Prefabs文件下找到Example.prefab文件,拖入场景中,如图:


打开Window\UnityFS\Configure Input,点击OVERWRITE-Done,如图:




打开Edit\Project Settings\Input,如图:


可以看到右边的Inspector里面设置好了,直接打开Scenes下的Example是没有设置的,而且会提示报错,虽然不影响运行,但是飞机是不能操控的,如图:

最后删掉后来拖进去的飞机即可,原来的飞机就可以运行了。

飞机操控说明:前后左右:“wsad”;

起落架抬起和放下:“G”;

加大油门:长按“2”;

减小油门:长按“1”;

飞机起飞:“S”,拉起拉杆即可;‘

切换视角:“C”;

点火:“I”;

顺便说一句,这个飞机模拟器还是比较强大的,里面的仪表盘会根据高度转向等信息转动,而且比较逼真,有从飞机加油-抬升-起飞-收齐起落架等一些列动作,声音等平衡系统相当完善。不过还是要学习别人的技术,不能总是看别人的东西很NB,要拿来转换成自己的东西才是最终目的!

2012-10-06 23:15:14 tinya0913 阅读数 8360

本视频主要讲述Unity3d中实现飞行模拟的方法,通过本次课程我们将学会在空间中实现自由飞行的控制,效果类似二战空骑兵、鹰击长空等飞行模拟类游戏。课程中我也将会给大家介绍相关的飞行原理,介绍飞机的基本构成、飞机的常用布局、飞行姿态控制等航空方面的基础知识。

更多内容请关注新浪微博@筑梦天下文化科技 http://weibo.com/mongtx


请同时关注团队新微博@筑梦创想 http://weibo.com/mongcc

此外,本人是广州在校大三学生(软件工程专业),现在诚求各单位提供实习岗位,我希望能通过实习进一步提高个人专业技能和充实职业工作经验,欢迎对我感兴趣的单位随时与我联系,此外我们团队将会继续推出更多精品的课程为大家服务,希望大家能继续支持,持续关注,谢谢大家!

联系方式
E-mail:gsh0913@qq.com
QQ:264965161

教学视频地址:http://www.tudou.com/programs/view/rBreIRfIsVE/?resourceId=0_06_02_99


公开课片头_1280_800.png

2012-4-4 20:12:51 上传
下载附件 (499.31 KB)


内容提要_1280_800.png

2012-4-4 20:13:07 上传
下载附件 (273.07 KB)


飞行截图.jpg

2012-4-4 20:13:14 上传
下载附件 (34.92 KB)


飞行截图2.jpg

2012-4-4 20:13:19 上传
下载附件 (35.07 KB)


截图01.jpg

2012-4-4 20:17:28 上传
下载附件 (31.57 KB)


截图02.jpg

2012-4-4 20:17:41 上传
下载附件 (33.55 KB)


截图03.jpg

截图04.jpg

PS:由于有部分网友反映本工作室发布的视频教程内容过于简单,我们希望在此声明一下,我们发布教学视频的目的并不是为了炫耀些什么,教程大部分都为基础知识,面向的主要为入门级的网友。我们希望有更多的网友能通过我们的视频进入游戏开发的殿堂,并且我们希望通过本系列教程结交到更多热爱游戏的朋友,我们的教程会遵循渐进的原则,步步为营由浅及深,希望大家多多包含,继续鼎力支持!

2016-10-12 16:03:35 qq_28221881 阅读数 8263

值得注意的是,模型要于代码的方向和轴向一致,多多改几次就能调整合适的了。

制作空物体,放在飞机模型合适的位置

using UnityEngine;
using System.Collections;

public class FlyTest : MonoBehaviour {
    public GameObject box;

    private Transform Head;
    private Transform LeftAirfoil;
    private Transform RightArifoil;
    private Transform LeftTailAirfoil;
    private Transform RightTailAirfoil;


    private float speed = 250.0f;

    private Rigidbody rb;

    void Start()
    {
        box = GameObject.Find("Plane");

        Head = transform.Find("Head");
        LeftAirfoil = transform.Find("LeftAirfoil");
        RightArifoil = transform.Find("RightAirfoil");
        LeftTailAirfoil = transform.Find("LeftTailAirfoil");
        RightTailAirfoil = transform.Find("RightTailAirfoil");

        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
       
        transform.Translate(Vector3.right * Time.deltaTime);
        //俯冲
        if(Input .GetKey (KeyCode.W ))
        {
            rb.AddForceAtPosition(transform.up * 5.0f, LeftTailAirfoil.position);

            rb.AddForceAtPosition(transform.up * 5.0f, RightTailAirfoil.position);
        }
         //爬升
        else if(Input .GetKey (KeyCode .S ))
        {
            rb.AddForceAtPosition(transform.up * -5.0f, LeftTailAirfoil.position);

            rb.AddForceAtPosition(transform.up * -5.0f, RightTailAirfoil.position);
        }
        //左翻滚
        else if(Input .GetKey (KeyCode .A ))
        {
            rb.AddForceAtPosition(transform.up * -5.0f, LeftTailAirfoil.position);

            rb.AddForceAtPosition(transform.up * 5.0f, RightTailAirfoil.position);
        }
        //右翻滚
        else if(Input .GetKey (KeyCode .D ))
        {
            rb.AddForceAtPosition(transform.up * 5.0f, LeftTailAirfoil.position);

            rb.AddForceAtPosition(transform.up * -5.0f, RightTailAirfoil.position);
        }
    }
}


2016-04-29 10:47:44 hyf2713 阅读数 4314

使用unity开发游戏真是非常方便。研究飞行模拟也有一段时日,尝试过物理和数学模拟。从效果上来看,物理模拟较为真实一点。但是操作不好。数学模拟的话,虽然牺牲了飞行效果,操控是非常方便的。

  所谓的数学模拟,就是位移模拟,通过定义起飞速度,加速度等,模拟飞机的飞行过程,包括转向,飞行坠落等。

  来看一下飞机的飞行状态:在地面上,飞机达到起飞速度时,可以拉起飞机,否则,一直在地面上;在空中:当飞机低于起飞速度,下降。大于起飞速度则能保持在空中。飞机不可能倒着飞行的,所以,飞机的速度状态就有:起飞速度,正常速度,最大速度。通过输入改变当前速度,然后通过判断速度所对应的状态处理。

  飞机的转向:飞机的转向,有y轴的转向,控制飞机的左右飞行。x的转向,控制飞机的升降。左右飞行时,飞机自身需要以z轴旋转,来模拟飞机转弯的效果。

  飞机的失速:当飞机在空中的速度低于起飞速度时,飞机下落。当着地时,下落的速度为0.

  整理一下思路:可以通过射线检测的方式获取距离地面的高度,判断飞机是在空中还是地面。通过输入值来调整currentSpeed,通过与飞机的offSpeed,normalSpeed,maxSpeed比较,来判断飞机所处的状态。通过四元数方法,调整飞机的角度,保持飞机的平衡和转向时的偏转效果。

  主要使用到的方法:

 

  移动:transform.Translate(vector, Space.World);

  旋转:transform.Rotate(vector, Space.World);

  转角:transform.rotation = Quaternion.RotateTowards(transform.rotation,rotation, speed);

     高度:Physics.Raycast(ray, out hit,1<<0);height = hit.distance;

 

  

  飞机的抽象控制方法:

复制代码
    public abstract void MoveLR(float speed);//左右移动
    public abstract void RoteUD(float speed);//上下旋转
    public abstract void MoveFB(float speed);//速度控制
    public abstract void RoteLR(float speed);//左右旋转
  public abstract Balance(Quaternion r, float speed);//转角

  public abstract void Operational();//飞行状态
 
复制代码

  接下来就是飞行方法的实现:

  

复制代码
public override void MoveFB(float speed)//速度控制
    {
        IsRun = true;//主动控制打开
        CurrentSpeed += speed*aircaft.Acc*Time.deltaTime;//加/减速
        CurrentSpeed = Mathf.Clamp(CurrentSpeed, 0, aircaft.MaxSpeed);//控制速度在最大值范围内
    }
    public override void MoveLR(float speed)//水平移动飞机,飞机的侧飞
    {
        //左右移动
        if ((IsSing) || IsOnGround) return;//如果在地面或者飞机处于特技状态
        //IsLRB = false;
        Vector3 vector = body.right;
        vector.y = 0;

        Move(speed * vector * aircaft.MoveLRSpeed * Time.deltaTime * CurrentSpeed/aircaft.MoveFBSpeed);//侧飞
Balance(Quaternion.Euler(body.eulerAngles.x, body.eulerAngles.y, -aircaft.AxisLR * speed), aircaft.RoteLRSpeed * Time.deltaTime);/旋转机身,实现侧飞的效果 //print("MoveLR" + speed); } public override void Operational()//飞机的状态控制 { Altigraph();//测量高度 if (CurrentSpeed < aircaft.OffSpeed)//小于起飞速度 { //落下 if (!IsOnGround)//在空中 { Move(-Vector3.up * Time.deltaTime * 10 * (1 - CurrentSpeed / (aircaft.OffSpeed)));//失重下落 downSpeed = Mathf.Lerp(downSpeed, 0.1f, Time.deltaTime); //print("downSpeed" + downSpeed); RoteUD(downSpeed);//机身前倾实现下落效果
}
if (!rigidbody) rigidbody = GetComponent<Rigidbody>(); rigidbody.useGravity = IsOnGround;//如果飞机在地面,启用重力,否则不使用重力 } else { downSpeed = 0; } Balance();//保持飞机的平衡 if (!IsRun) {//保持飞机以正常速度飞行 if (CurrentSpeed > aircaft.MoveFBSpeed) CurrentSpeed = Mathf.Lerp(CurrentSpeed, aircaft.MoveFBSpeed,Time.deltaTime); else if (CurrentSpeed > aircaft.OffSpeed && !IsOnGround) CurrentSpeed =Random.Range(aircaft.OffSpeed,aircaft.MoveFBSpeed); else if (IsOnGround && CurrentSpeed < aircaft.OffSpeed) { CurrentSpeed = Mathf.Lerp(CurrentSpeed,0,Time.deltaTime); } } Move(body.forward * CurrentSpeed * Time.deltaTime);//调用飞行方法 } public override void RoteLR(float speed)//飞机的转向 { //左右旋转 if ((IsSing) || IsOnGround) return; IsLRB = false; Rote(speed * Vector3.up * aircaft.RoteLRSpeed * Time.deltaTime * CurrentSpeed / aircaft.MoveFBSpeed); Balance(Quaternion.Euler(body.eulerAngles.x, body.eulerAngles.y,-aircaft.AxisLR * speed), aircaft.RoteLRSpeed * Time.deltaTime); //print("RoteLR" + speed); } public override void RoteUD(float speed)//飞机的转向 { //上下旋转 //速度和角度 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);//判断目标点相对于当前位置的左右
        
        
        //获取这个信息后,接下来就是移动到目标点
        //先判断什么?正前方到目标点的角度,如果这个角度在一定范围内,则可以进行移动
        //
        float axisFB = 0;
        if (dFBAgle > objectAI.Precision)
        {
            //方向偏移在正常范围内
            //根据距离判断是否加/减速度
            //

            if (distence > objectAI.RunDistance * stopDistance || (flight.CurrentSpeed < flight.aircaft.OffSpeed && !IsLand))
            {
                axisFB = Random.Range(0f, 1f);
            }
            else if (distence > objectAI.FreeDistance * stopDistance && !IsLand)
            {
                axisFB = Random.Range(-0.5f, 0.5f);
            }
            else if (distence < objectAI.SlowDistance * stopDistance && IsLand)
            {
                axisFB = Random.Range(-1f, 0f);
            }
            
        }
        else { 
        //方向偏移不在正常范围
            //判断距离是否达到停止距离
            //判断高度是否在误差之内
            //调整左右和前后,来
            if (distence < stopDistance)
            {
                //到达目标点附近,但是角度偏差过大,判断目标的左右,进行旋转
                axisFB = Random.Range(0.5f, 1f);
                flight.RoteLR(dLRAgle);
            }
            else {
                
                //if (Mathf.Abs(dLRAgle) < 0.05f) dLRAgle = 0;
                if (dFBAgle < -0.75f)
                {
                    flight.StuntUD(flight.Height>100?-1:1);
                }
                else if (dFBAgle < -0.25f) {
                    flight.StuntLR(dLRAgle);
                }
                
                flight.RoteLR(dLRAgle);
                if (!IsLand) {
                    if (Mathf.Abs(dHeight) > 5) {

                        flight.RoteUD(-dUDAgle);
                    }
                    if(flight.IsOnGround){
                        flight.RoteUD(-1);
                    }
                }
                    
                if(flight.CurrentSpeed<flight.aircaft.MoveFBSpeed)
                    axisFB = Random.Range(0.5f, 1f);
            }
        }
        //flight.RoteLR(dLRAgle);
        if (Mathf.Abs(axisFB) > 0.01f)
            flight.MoveFB(axisFB);
    }
复制代码

  好了,今天的飞行模拟就介绍到这了。预告一下,下一篇文章阿亮将探讨导弹算法的实现(预计目标点位置,而非通过获取目标的当前位置)

  导弹算法已经完成,博客地址:http://www.cnblogs.com/jqg-aliang/p/4768101.html谢谢观看!

本文转载自:http://www.cnblogs.com/jqg-aliang/p/4598515.html。转载请申明出处,谢谢!