使用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。转载请申明出处,谢谢!

基于unity的飞行模拟设计相关推荐

  1. 基于unity的直升机模拟设计

    上一篇文章介绍了使用unity3D进行战斗机飞行模拟的设计http://www.cnblogs.com/jqg-aliang/p/4598515.html,其实只要稍微修改一下,就变成了直升机的飞行模 ...

  2. unity直升机飞行模拟

    本篇博客对直升机的飞行状态和攻击进行了简单的模拟,但是如果对仿真度没有太高的要求,这已经完全够用了. 对于旋转方式有困惑的可以参考https://blog.csdn.net/xdedzl/articl ...

  3. Unity游戏开发文档(1):飞行模拟

    前言     本篇的代码是基于Unity3D 系列课程 "Create with Code" 第一章 "Player Control" 改进而来 目录 背景 设 ...

  4. unity 陶瓷质感_一种基于Unity3D的虚拟陶瓷设计方法与流程

    本发明涉及虚拟现实领域,特别涉及一种基于Unity3D的虚拟陶瓷设计方法. 背景技术: 陶艺工艺制作环境要求严格:不仅在拉坯成型需要利用旋转机器,在烧制过程则需要窑炉锻造,如何将陶瓷制作工艺与虚拟现实 ...

  5. 基于unity的愤怒的小鸟设计

    基于unity的愤怒的小鸟设计 演示视频 目录 2 一.游戏设计 3 1.1 前期设计思路 3 1.1.1 设计透镜 3 1.1.2 游戏主题 3 1.1.2 创意 3 1.2 设计目的 4 1.3 ...

  6. 《游戏开发基础》课程论文丨基于Unity与Bolt的抗美援朝主题3D游戏设计

    文章目录 摘要 关键词 一.导言 二.角色操控 2.1 隐藏鼠标 2.2 通过移动鼠标更新玩家视角 2.3 使角色跳跃 2.4 使角色移动 2.5 使角色冲刺 2.6 使角色卧倒 2.7 设置准星及切 ...

  7. 基于wincc的虚拟电梯设计_基于WINCC的模拟电梯设计

    : 151********@163.com 基于 WINCC 的电梯模拟运行控制系统设计 冯鹏辉 谭兮 郭少校 刘国营 ( 湖南工业大学,湖南 株洲 412008) 摘要: 电梯的运行是电梯与大楼及各 ...

  8. 游戏设计、原型与开发:基于Unity与C#从构思到实现pdf

    下载地址:网盘下载 这是一本将游戏设计理论.原型开发方法以及编程技术巧妙结合在一起的书籍,目的是填补游戏设计与编程开发之间的缺口,将两者联系起来.随着 Unity游戏开发技术趋于成熟,游戏设计师把自己 ...

  9. 在Unity中实现基于粒子的水模拟(二:开始着色)

    在Unity中实现基于粒子的水模拟(二:开始着色) 文章目录 在Unity中实现基于粒子的水模拟(二:开始着色) 前言 一.生成顶点 二.偏移模拟 1.接收细分着色器输出的顶点 2.根据数据调用对应的 ...

最新文章

  1. 阿里暴跌近6%,蒸发2400亿!拼多多火了,股价暴涨近15%!这个幕后的程序员开挂了,马云,刘强东都怕!...
  2. mysql安装 linux 5.6,Linux安装MySql5.6版详细教程
  3. python 虚拟环境 virtualenv virtualenvwrapper的使用方法、命令
  4. Node入门之创建第一个HelloNode
  5. work hard, think harder
  6. matlab 柏林噪声,游戏AI怎么写(一)——高级随机技术
  7. [XJTUSE编译原理] 第三章 上下文无关文法
  8. FFMPEG AvFilter使用实例(实现视频缩放,裁剪,水印等)
  9. Android-PickerView的简单封装与使用
  10. Au入门系列之十:母带处理
  11. mysql的strict_MySQL Strict SQL MODE
  12. Error: Transaction check error: package managesoft-13.1.1-1.x86_64 does not verify: no digest
  13. 计算机的可持续发展问题,可持续发展视角下的计算机教育优化
  14. php建模,如何建模和跟踪PHP中的目标需求
  15. Linux 是洗衣粉 关于Linux 的10个趣事
  16. 日本IT派遣状况(东京)2现场
  17. Linux cooked capture v1 层的处理
  18. MySql Povit_MySQL pivot row成动态列数
  19. C语言常用算法源代码
  20. python 类中的变量、方法

热门文章

  1. C++读取 TOML 格式文件的方法
  2. pytorch 神经网络套路 实现一维输入特征的二分类
  3. 使用jQuery获取form表单数据并且打印在控制台
  4. 一个三流院校毕业的程序员奋斗历程
  5. oracle mysql is null_MySql,Postgres,Oracle和SQLServer忽略IS NOT NULL过滤...
  6. Java学习之类(三):构造方法和创建对象
  7. 夕食の後のレギュラーエクスプレスについての議論(1)
  8. 初中化学骨干教师培训需求调查分析--以贵州师范学院国培计划为例
  9. 四招教你无线电通讯工程现场天线驻波比测试
  10. wordpress建立php站点地图,WordPress修改源文件生成完整站点地图(sitemap.xml)的php代码实例...