本篇博客对直升机的飞行状态和攻击进行了简单的模拟,但是如果对仿真度没有太高的要求,这已经完全够用了。

对于旋转方式有困惑的可以参考https://blog.csdn.net/xdedzl/article/details/81488894

1.简易状态机基类

using UnityEngine;
using System.Collections;public class FSM : MonoBehaviour
{protected virtual void Initialize() {}protected virtual void FSMUpdate() {}protected virtual void FSMFixedUpdate() {}//Use this for initializationvoid Start(){Initialize();}// Update is called once per framevoid Update () {FSMUpdate();    }void FixedUpdate(){FSMFixedUpdate();}
}

2.直升机状态类

这个类里设置了三个外部调用接口,分别是StartAttack,SetTargetPos,SetEnemy,大家可以根据需要自行控制

​
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;/// <summary>
/// 直升机状态
/// </summary>
public enum HState
{Flying,  // 飞行Up,      // 上升Down,    // 下降Halt,    // 停止Hover,   // 悬停Aim,     // 瞄准
}public class Helicopter : FSM
{/// <summary>/// 攻击目标/// </summary>public Transform enemy;/// <summary>/// 移动目标点/// </summary>protected Vector3 targetPos;/// <summary>/// 攻击时间间隔/// </summary>protected float shootRate;/// <summary>/// 主旋翼/// </summary>public Transform mainRotor;/// <summary>/// 尾旋翼/// </summary>public Transform tailRotor;/// <summary>/// 发射器组/// </summary>public Transform[] launchs;/// <summary>/// 导弹/// </summary>public GameObject missile;/// <summary>/// 火箭弹/// </summary>public GameObject rocketSheel;/// <summary>/// 主旋翼旋转速度/// </summary>private float mainRatorSpeed;/// <summary>/// 尾翼旋转速度/// </summary>private float tailRatorSpeed;/// <summary>/// 最大俯仰角/// </summary>private float maxPitchAngle = 10;/// <summary>/// 最大横滚角/// </summary>private float maxRollAngle = 30;/// <summary>/// 最大升降速度/// </summary>private float maxLiftSpeed = 15;/// <summary>/// 最大移动速度/// </summary>private float maxMoveSpeed;/// <summary>/// 当前移动速度/// </summary>private float currentMoveSpeed;/// <summary>/// 旋转速度/// </summary>private float rotateSpeed = 1;/// <summary>/// 旋翼声音/// </summary>private AudioSource ratorSound;/// <summary>/// 移动后是否着陆/// </summary>private bool isLanding = false;/// <summary>///  是否已瞄准/// </summary>private bool isAim = false;public bool IsAim { get { return isAim; } }/// <summary>/// 武器种类/// </summary>private bool isMissile = false;/// <summary>/// 携弹量/// </summary>[SerializeField]private float weaponNumber = 8;/// <summary>/// 直升机当前状态/// </summary>private HState currentFlyState = HState.Halt;protected override void Initialize(){targetPos = transform.position + transform.forward * 0.1f;ratorSound = gameObject.GetComponent<AudioSource>();}protected override void FSMFixedUpdate(){RotateRotor();SwitchMove();}/// <summary>/// 旋翼旋转/// </summary>private void RotateRotor(){if (currentFlyState != HState.Halt){mainRatorSpeed = Mathf.Lerp(mainRatorSpeed, 15, Time.deltaTime);tailRatorSpeed = Mathf.Lerp(tailRatorSpeed, 20, Time.deltaTime);}else{mainRatorSpeed = Mathf.Lerp(mainRatorSpeed, 0, Time.deltaTime);tailRatorSpeed = Mathf.Lerp(tailRatorSpeed, 0, Time.deltaTime);}mainRotor.Rotate(0, mainRatorSpeed, 0);tailRotor.Rotate(tailRatorSpeed, 0, 0);}/// <summary>/// 选择飞行状态/// </summary>private void SwitchMove(){switch (currentFlyState){case HState.Flying:FlyingState();break;case HState.Up:UpState();break;case HState.Down:DownState();break;case HState.Hover:HoverState();break;case HState.Halt:break;case HState.Aim:AimState();break;default:break;}}/// <summary>/// 飞行状态的移动/// </summary>private void FlyingState(){YawRotate(targetPos, maxRollAngle); // 偏航float y = (targetPos - transform.position).normalized.y; // 获取y轴移动方向currentMoveSpeed = Mathf.Lerp(currentMoveSpeed, maxMoveSpeed, Time.deltaTime);transform.Translate(new Vector3(transform.forward.x, y, transform.forward.z) * currentMoveSpeed * Time.deltaTime, Space.World); // x,z轴方向用直升机自身方向PitchRotate(maxPitchAngle);   // 俯仰 飞行状态必俯仰// 抵达目标点后更改状态if (Vector3.Distance(transform.position, targetPos) < 5){currentMoveSpeed = 0;if (isLanding){currentFlyState = HState.Down;}else{currentFlyState = HState.Hover;}}}/// <summary>/// 悬停状态/// </summary>private void HoverState(){PitchRotate(0);RollRotate(0);}/// <summary>/// 降落状态/// </summary>private void DownState(){PitchRotate(0);  // 俯仰修正RollRotate(0);   // 横滚修正float height = transform.position.y - Terrain.activeTerrain.SampleHeight(transform.position);if (height < 0.1){ratorSound.Stop();currentFlyState = HState.Halt;return;}transform.Translate(Vector3.down * Time.deltaTime * Mathf.Lerp(Mathf.Min(height, maxLiftSpeed), maxLiftSpeed, Time.deltaTime));// 起飞速度以离地高度与飞行速度做插值// 控制旋翼声音ratorSound.volume = height / 10;}/// <summary>/// 起飞状态/// </summary>private void UpState(){float height = transform.position.y - Terrain.activeTerrain.SampleHeight(transform.position);if (height > 10){currentFlyState = HState.Flying;return;}YawRotate(targetPos, maxRollAngle);transform.Translate(Vector3.up * Time.deltaTime * Mathf.Lerp(height, maxLiftSpeed, Time.deltaTime));// 起飞速度以离地高度与飞行速度做插值if (!ratorSound.isPlaying){ratorSound.Play();}// 控制旋翼声音ratorSound.volume = height / 10;}/// <summary>/// 攻击状态/// </summary>private void AimState(){// 俯仰和偏航到指定角度Vector3 dir = enemy.position - (launchs[0].position + launchs[1].position) / 2;Quaternion rotation = Quaternion.LookRotation(dir);transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime);if (Vector3.Angle(dir, transform.forward) < 0.2){isAim = true;}else{isAim = false;}}/// <summary>/// 偏航 机身旋转/// </summary>private void YawRotate(Vector3 _targetPos, float rollAngle){float height = transform.position.y - Terrain.activeTerrain.SampleHeight(transform.position); // 获取当前物体相对地面高度if (height < 5){return;}Vector3 dir = _targetPos - transform.position;Quaternion targetRotation = Quaternion.LookRotation(dir);float angle = transform.eulerAngles.y - targetRotation.eulerAngles.y;if (angle < 0) angle += 360;if (angle > rotateSpeed && angle < 180){transform.Rotate(0f, -rotateSpeed, 0f, Space.World);RollRotate(rollAngle);}else if (angle < 360 - rotateSpeed && angle > 180){transform.Rotate(0f, rotateSpeed, 0f, Space.World);RollRotate(-rollAngle);}else{// 偏航完成if (currentFlyState == HState.Flying){RollRotate(0);}}}/// <summary>/// 横滚 左倾右倾/// </summary>/// <param name="target_z">横滚目标角度</param>private void RollRotate(float target_z){Vector3 currentEuler = transform.eulerAngles;Quaternion from = Quaternion.Euler(transform.eulerAngles);Quaternion to = Quaternion.Euler(new Vector3(currentEuler.x, currentEuler.y, target_z));transform.rotation = Quaternion.Lerp(from, to, Time.deltaTime);}/// <summary>/// 俯仰 前倾/// </summary>/// <param name="target_x">俯仰目标角度</param>private void PitchRotate(float target_x){Vector3 currentEuler = transform.eulerAngles;Quaternion from = Quaternion.Euler(transform.eulerAngles);Quaternion to = Quaternion.Euler(new Vector3(target_x, currentEuler.y, currentEuler.z));transform.rotation = Quaternion.Lerp(from, to, Time.deltaTime);}/// <summary>/// 初始化火力/// </summary>/// <param name="_launch">发射架</param>/// <param name="_target">打击目标</param>/// <param name="_Missile">导弹预制</param>/// <param name="_velocity">导弹速度</param>private void InitFirePower(Transform _launch, float _velocity = 400f){int index;if (isMissile){//实例化导弹实体,项目中要用对象池改写index = Random.Range(3, 4);GameObject _missile = Instantiate(missile, launchs[index].position, _launch.rotation);//实例化出来的导弹上挂导弹飞行的代码}else{//实例化火箭弹,项目中要用对象池改写index = Random.Range(0, 2);GameObject _rocketSheel = Instantiate(rocketSheel, launchs[index].position, _launch.rotation);//实例化出来的火箭弹挂火箭弹飞行的代码}launchs[index].Find("FireEffect").GetComponent<ParticleSystem>().Play();launchs[index].GetComponent<AudioSource>().Play();}/// <summary>/// 攻击 startAttack为外部调用接口/// </summary>private IEnumerator Attack(float delay = 0.1f){yield return new WaitForSeconds(delay);if (launchs.Length > 0){for (int i = 0; i < weaponNumber; i++){InitFirePower(launchs[0]);yield return new WaitForSeconds(0.2f);}}}public void StartAttack(){StartCoroutine(Attack());}/// <summary>/// 设置目标点/// </summary>/// <param name="_pos"></param>/// <param name="_speed"></param>/// <param name="_isLanding"></param>public void SetTargetPos(Vector3 _pos, float _speed, bool _isLanding){targetPos = _pos;maxMoveSpeed = _speed;isLanding = _isLanding;isAim = false;switch (currentFlyState){case HState.Down:case HState.Halt:currentFlyState = HState.Up;break;case HState.Hover:case HState.Aim:currentFlyState = HState.Flying;break;default:break;}}/// <summary>/// 设置攻击目标/// </summary>/// <param name="_enemy"></param>/// <param name="isMissile">武器是否是导弹</param>public void SetEnemy(Transform _enemy, bool _isMissile = true){if (launchs.Length <= 0){return;}enemy = _enemy;isMissile = _isMissile;if (currentFlyState == HState.Hover || currentFlyState == HState.Flying){currentFlyState = HState.Aim;}}
}

unity直升机飞行模拟相关推荐

  1. 基于unity的飞行模拟设计

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

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

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

  3. unity飞行模拟游戏源码,支持安卓+IOS双端 unity2019 C#语言开发

    unity飞行模拟游戏源码,支持安卓+IOS双端 unity2019 C#语言开发.完整的源码可直接运营.拿来学习研究和二次开发都很不错. 源码下载 unity2019飞行模拟游戏源码C#语言开发-U ...

  4. 基于知识图谱的直升机飞行指挥模型研究

    基于知识图谱的直升机飞行指挥模型研究 人工智能技术与咨询 昨天 本文来自<无线电工程>,作者齐小谦 关注微信公众号:人工智能技术与咨询.了解更多咨询! 摘 要: 针对当前直升机飞行指挥效率 ...

  5. 开发Unity3D空战类插件 战机飞行模拟模板

    Fighter Flight Template是本人开发的一款飞行模拟游戏模板,使用此模板可以帮助您轻松创建您自己的战机游戏 游戏控制 模板特点 战机的飞行系统是根据现代战机的空气动力学所设计的. 战 ...

  6. 开发Unity3D空战类插件 战机飞行模拟模板Pro版本

    Fighter Flight Template Pro是本人开发的一款飞行模拟游戏模板,使用此模板可以帮助您轻松创建您自己的战机游戏 游戏控制 模板特点 战机的飞行系统是根据现代战机的空气动力学所设计 ...

  7. 倾转旋翼飞行模拟(基于X-planeXV-15)

    前言:       和传统一样,受限于固定翼的起降需求和直升机的航程与速度限制,诞生了接触一下倾转旋翼的想法.但是我一没有科研需求,二没有项目支撑,于是决定从X-plane当中做出一些尝试,体验一下. ...

  8. 介绍简易制作飞行模拟游戏的方法(转)

    介绍简易制作飞行模拟游戏的方法(转)[@more@] 对许多网友而言,玩游戏是件令人愉快的事情,但是能因此而想到要去亲手制作一个游戏-----甚至是大型游戏的朋友可能就不是很多了,其中原因,说来也简单 ...

  9. 《微软飞行模拟》用AI还原全球15亿建筑,玩家发现bug:白金汉宫变成写字楼

    晓查 发自 凹非寺  量子位 报道 | 公众号 QbitAI 全球最大的仿真游戏<微软模拟飞行2020>本周正式上线.这款游戏还原了全球200万个城镇.15亿座建筑物和3.7万个机场,让玩 ...

最新文章

  1. 计算机视觉已超越人类眼睛?腾讯优图与《科学》杂志全面解读
  2. Oracle XTTS跨平台数据库迁移(从Unix迁移数据库到Linux)_Oracle数据库迁移项
  3. Sharepoint java sdk_java – 使用JAX-WS将文件保存到Sharepoint服务器
  4. 【结论】只不过是长的领带(luogu 6877)
  5. C++ 11 深度学习(七)位运算常见操作
  6. 各個瀏覽器CSS樣式控制
  7. corn表达式的简单使用
  8. [转]Maintain Control State in ASP.NET 2.0
  9. STM32F0xx_TIM基本延时配置详细过程
  10. JAVA程序设计基础(第六版)第六章习题 6.13
  11. ArcGIS中裁剪(clip)出现000117错误的解决办法
  12. matlab局部放大找交点,11.matlab找两条离散曲线的交点
  13. MACHINE LEARNING ----BY HUNGYILEE (love u)
  14. matlab中inf是什么意思,simulink中inf什么意思
  15. tyvj P1517 飘飘乎居士的乌龟(最大流)
  16. git:info: detecting host provider for ‘https://gitee.com/‘...
  17. 【学习笔记15】JavaScript的函数
  18. Typora自动上传图床配置
  19. 关于hi3516ev100调试zbar二维码和链接wifi问题
  20. 华为rstp配置实例

热门文章

  1. 增长天王排位赛,等你来战!
  2. Android Studio中移动.gradle文件夹的方法
  3. favicon.ico使用方式
  4. 人工智能的最后一公里
  5. COUPLE3.0计算过程出现缺少qtintf70.dll文件而无法计算问题解决方法
  6. 上课不听讲下课来补习系列之-玩转单片机STM8(一)
  7. CentOS7下安装chrome浏览器
  8. div中的p标签于img设置同一水平_P标签和img标签的问题
  9. 常用DOS命令(转)
  10. centos7 安装压测软件webbench