Unity 简单的飞机控制器脚本

前言

前几天突发奇想的想做一个3d飞机游戏,于是先自己写了一下简单的控制器,发现效果不是很好。之后浏览了一下网上的资源发现免费的不全,别的要钱。只好自己设计了。下面是我设计完后的脚本。

代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerController : MonoBehaviour
{[Tooltip("限飞速度,限制飞机能否起飞")]/// <summary>/// 限飞速度/// </summary>public float GroundMaxSpeed = 5;[Tooltip("水平的最大速度")]/// <summary>/// 水平的最大速度/// </summary>public float HorizotalMaxSpeed = 5;[Tooltip("垂直最大速度")]/// <summary>/// 垂直最大速度/// </summary>public float VerticalMaxSpeed = 5;[Tooltip("最大飞行高度")]/// <summary>/// 最大飞行高度/// </summary>public float MaxFlyHeight = 100;[Tooltip("每次旋转的角度分量")]/// <summary>/// 每次旋转的角度增量/// </summary>public float EveryRotateValue = 5;[Tooltip("水平移动加速度")]/// <summary>/// 水平移动加速度/// </summary>public float AccSpeed = 10;[Tooltip("垂直上升加速度")]/// <summary>/// 上升加速度/// </summary>public float UpAccSpeed = 10;[Tooltip("平衡轴的名称:'x+y','x+z','y+z'")]/// <summary>/// 平衡轴的名称 x,y,z/// </summary>public string BalancedAxis = null;[Tooltip("平衡回调速度,值越大速度越慢,越小速度越快")]/// <summary>/// 平衡回调速度,值越大速度越慢,越小速度越快/// </summary>public float ReBalanceSpeed = 10;/// <summary>/// z轴旋转总值,自身/// </summary>float zLocalRotateValue = 0;/// <summary>/// x轴旋转总值,自身/// </summary>float xLocalRotateValue = 0;/// <summary>/// y轴旋转总值,自身/// </summary>float yLocalRotateValue = 0;/// <summary>/// 是否能够发动上升引擎/// </summary>bool CanFly = false;/// <summary>/// 实时更新的平衡轴的值/// </summary>Vector3 UpdateBalancedValue = new Vector3(0, 0, 0);/// <summary>/// 飞机水平两个平衡轴的值,本例用模型为x轴/// </summary>Vector3 BalanceAxisValue;/// <summary>/// 是否处于平衡调整状态/// </summary>bool IsBalancing = false;/// <summary>/// 自身的刚体/// </summary>Rigidbody rigidbody;// Start is called before the first frame updatevoid Start(){//获取初始坐标作为水平位置直接关系轴的值,本例为x,z轴BalanceAxisValue = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y,transform.localEulerAngles.z);//初始化三个旋转总值的初始值Update3LocalRotateValue();//获取当前的刚体组件rigidbody = GetComponent<Rigidbody>();if (!rigidbody)Debug.LogError("刚体未添加!");}// Update is called once per framevoid Update(){if (!IsBalancing) {//限制速度LimitSpeed();//实时检测是否可以起飞SpeedCheck();//行为检测MainController();}}/// <summary>/// 检查平衡轴字符串输入是否正确/// </summary>bool CheckBlanceAxisString() {switch (BalancedAxis) {//输入正确case "x+y":return true;//输入正确case "x+z":return true;case "y+z":return true;case "y+x":BalancedAxis = "x+y";return true;case "z+x":BalancedAxis = "x+z";return true;case "z+y":BalancedAxis = "y+z";return true;//除开以上的所有结果视为错误default:return false;}}/// <summary>/// 飞机行为控制函数/// </summary>void MainController() {//前进if (Input.GetKeyDown(KeyCode.W) || Input.GetKey(KeyCode.W)){//调用GoFarward前进GoFarward();}//后退if (Input.GetKeyDown(KeyCode.S) || Input.GetKey(KeyCode.S)){//调用GoBack后退GoBack();}//左移if (Input.GetKeyDown(KeyCode.A) || Input.GetKey(KeyCode.A)){//调用GoLeft左侧飞GoLeft();}//右移if (Input.GetKeyDown(KeyCode.D) || Input.GetKey(KeyCode.D)){//调用GoRight右侧飞GoRight();}//飞机上升if (CanFly && Input.GetKey(KeyCode.Space))//等价于CanFly==true{//调用上升引擎让飞机上升UpPlane();}//左旋if (Input.GetKeyDown(KeyCode.Q) || Input.GetKey(KeyCode.Q)){//调用TurnLeft飞机左旋TurnLeft();}//右旋if (Input.GetKeyDown(KeyCode.E) || Input.GetKey(KeyCode.E)){//调用TurnRight飞机右旋TurnRight();}//上挑if (Input.GetKeyDown(KeyCode.Alpha1) || Input.GetKey(KeyCode.Alpha1)){//调用TurnUp飞机上挑TurnUp();}//下挑if (Input.GetKeyDown(KeyCode.Alpha2) || Input.GetKey(KeyCode.Alpha2)){//调用TurnDown飞机下挑TurnDown();}//开启平衡调整,平衡调整状态下,不能对飞机进行操作if (Input.GetKeyDown(KeyCode.B)){//开启自动平衡模式IsBalancing = true;StartCoroutine(Balanced());}}/// <summary>/// 起飞速度检测/// </summary>void SpeedCheck() {if (rigidbody.velocity.magnitude >= GroundMaxSpeed) {CanFly = true;}}/// <summary>/// 上升引擎函数/// </summary>void UpPlane() {if (rigidbody){rigidbody.AddForce(transform.up * UpAccSpeed*Time.deltaTime);}}/// <summary>/// 给飞机一个向前的力/// </summary>void GoFarward() {if (rigidbody) {rigidbody.AddForce(-transform.forward*AccSpeed*Time.deltaTime);}}/// <summary>/// 控制飞机向后飞/// </summary>void GoBack() {if (rigidbody) {rigidbody.AddForce(transform.forward * AccSpeed * Time.deltaTime);}}/// <summary>/// 控制飞机向左飞/// </summary>void GoLeft() {if (rigidbody){//添加力rigidbody.AddForce(transform.right * AccSpeed * Time.deltaTime);}}/// <summary>/// 控制飞机向右飞/// </summary>void GoRight() {if (rigidbody){//添加力rigidbody.AddForce(-transform.right * AccSpeed * Time.deltaTime);}}/// <summary>/// 限制飞机速度/// </summary>void LimitSpeed() {//限制水平方向上的最大速度if (rigidbody.velocity.x <= -HorizotalMaxSpeed){rigidbody.velocity = new Vector3(-HorizotalMaxSpeed, rigidbody.velocity.y, rigidbody.velocity.z);}else if (rigidbody.velocity.x >= HorizotalMaxSpeed) {rigidbody.velocity = new Vector3(HorizotalMaxSpeed, rigidbody.velocity.y, rigidbody.velocity.z);}if (rigidbody.velocity.y <= -HorizotalMaxSpeed){rigidbody.velocity = new Vector3(rigidbody.velocity.x,-HorizotalMaxSpeed, rigidbody.velocity.z);}else if (rigidbody.velocity.y >= HorizotalMaxSpeed){rigidbody.velocity = new Vector3(rigidbody.velocity.x, HorizotalMaxSpeed, rigidbody.velocity.z);}//限制垂直方向上的最大速度if (rigidbody.velocity.z <= -VerticalMaxSpeed){rigidbody.velocity = new Vector3(rigidbody.velocity.x, rigidbody.velocity.y, -VerticalMaxSpeed);}else if (rigidbody.velocity.y >= VerticalMaxSpeed){rigidbody.velocity = new Vector3(rigidbody.velocity.x, rigidbody.velocity.y, VerticalMaxSpeed);}//限制飞机能飞到的最大高度if (transform.position.y >= MaxFlyHeight) {transform.position = new Vector3(transform.position.x,MaxFlyHeight, transform.position.z);}}/// <summary>/// 保持飞机平衡/// </summary>IEnumerator Balanced() {//首先判断BalancedAxis的字符串是否有问题if (!CheckBlanceAxisString()) {//退出自动平衡IsBalancing = false;Debug.LogError("Banlanced Axis字符串有错误,\n请认真检查修改后再使用自动平衡功能。");//返回空yield return null;}//更新实时平衡轴的位置,并从0-360制转化为-180到180制UpdateBalancedValueF();Vector2 UpBalanceValue;//实时平衡轴位置的二维值Vector2 BalanceValue;//平衡轴位置的二维值Vector2 DeltaValue1;//差值1,不对数据优化时的差值Vector2 DeltaValue2;//差值2,将角度限制在-180,180后的差值Vector3 AddValue;//每次的增值//因为不修改水平旋转的角度,所以需要判断if (BalancedAxis == "x+y"){//将对应平衡轴值临时保存为2维向量UpBalanceValue = new Vector2(UpdateBalancedValue.x, UpdateBalancedValue.y);BalanceValue = new Vector2(BalanceAxisValue.x, BalanceAxisValue.y);//选取代价最小的调整方向,由于系统内部是0-360制//对比转化为-180到180制来得到最小偏转角度DeltaValue1 = BalanceValue - UpBalanceValue;DeltaValue2 = new Vector2(LimitAngle(BalanceAxisValue.x, 180)- LimitAngle(UpBalanceValue.x, 180), LimitAngle(BalanceAxisValue.y, 180) - LimitAngle(UpBalanceValue.y, 180));if (DeltaValue1.magnitude <= DeltaValue2.magnitude){AddValue = new Vector3(DeltaValue1.x, DeltaValue1.y, 0);}else {AddValue = new Vector3(DeltaValue2.x, DeltaValue2.y, 0);}}else if (BalancedAxis == "x+z"){//同上UpBalanceValue = new Vector2(UpdateBalancedValue.x, UpdateBalancedValue.z);BalanceValue = new Vector2(BalanceAxisValue.x, BalanceAxisValue.z);DeltaValue1 = BalanceValue - UpBalanceValue;DeltaValue2 = new Vector2(LimitAngle(BalanceAxisValue.x, 180) - LimitAngle(UpBalanceValue.x, 180), LimitAngle(BalanceAxisValue.y, 180) - LimitAngle(UpBalanceValue.y, 180));if (DeltaValue1.magnitude <= DeltaValue2.magnitude){AddValue = new Vector3(DeltaValue1.x, 0, DeltaValue1.y);}else{AddValue = new Vector3(DeltaValue2.x, 0, DeltaValue2.y);}}else if (BalancedAxis == "y+z"){//同上UpBalanceValue = new Vector2(UpdateBalancedValue.y, UpdateBalancedValue.z);BalanceValue = new Vector2(BalanceAxisValue.x, BalanceAxisValue.y);DeltaValue1 = BalanceValue - UpBalanceValue;DeltaValue2 = new Vector2(LimitAngle(BalanceAxisValue.x, 180) - LimitAngle(UpBalanceValue.x, 180), LimitAngle(BalanceAxisValue.y, 180) - LimitAngle(UpBalanceValue.y, 180));if (DeltaValue1.magnitude <= DeltaValue2.magnitude){AddValue = new Vector3(0, DeltaValue1.x, DeltaValue1.y);}else{AddValue = new Vector3(0, DeltaValue2.x, DeltaValue2.y);}}else {AddValue = new Vector3(0, 0, 0);}while (true) {//当当前平衡轴与目标平衡位置时的差值大于1还需要调整平衡if ((BalanceAxisValue-UpdateBalancedValue).magnitude>=1){//每次运行到这里都加上差值除以一定数的量UpdateBalancedValue += AddValue / ReBalanceSpeed;}else{//更新3个旋转轴的总值Update3LocalRotateValue();//退出平衡调整状态IsBalancing = false;break;}//每帧一次yield return new WaitForEndOfFrame();//平衡调整transform.localEulerAngles = UpdateBalancedValue;}}/// <summary>/// 将Angle限制在-limitangle和limitangle之间/// </summary>/// <param name="Angle"></param>/// <param name="limitangle"></param>/// <returns></returns>float LimitAngle(float Angle, float limitangle) {if (Angle > limitangle){Angle = Angle - 360;}else if (Angle < -limitangle) {Angle = Angle + 360;}return Angle;}/// <summary>/// 飞机向右旋转/// </summary>void TurnRight() {//本例的左右旋转是绕y轴旋转的,因此这里计算的是y轴旋转总值yLocalRotateValue += EveryRotateValue;//对y值做个限制不能超过360if (yLocalRotateValue >= 360)yLocalRotateValue -= 360;//给飞机赋值旋转量来实现旋转transform.localEulerAngles = new Vector3(xLocalRotateValue, yLocalRotateValue, zLocalRotateValue);//更新其它旋转轴的总值zLocalRotateValue = transform.localEulerAngles.z;xLocalRotateValue = transform.localEulerAngles.x;}/// <summary>/// 飞机向左旋转/// </summary>void TurnLeft() {//同上yLocalRotateValue -= EveryRotateValue;if (yLocalRotateValue <= -360)yLocalRotateValue += 360;transform.localEulerAngles = new Vector3(xLocalRotateValue, yLocalRotateValue, zLocalRotateValue);zLocalRotateValue = transform.localEulerAngles.z;xLocalRotateValue = transform.localEulerAngles.x;}/// <summary>/// 飞机上挑/// </summary>void TurnUp() {//类比TurnRight旋转函数xLocalRotateValue += EveryRotateValue;if (xLocalRotateValue >= 360)xLocalRotateValue = xLocalRotateValue - 360;transform.localEulerAngles = new Vector3(xLocalRotateValue, yLocalRotateValue, zLocalRotateValue);yLocalRotateValue = transform.localEulerAngles.y;zLocalRotateValue = transform.localEulerAngles.z;}/// <summary>/// 飞机下挑/// </summary>void TurnDown(){//类比TurnRight旋转函数xLocalRotateValue -= EveryRotateValue;if (xLocalRotateValue <= -360)xLocalRotateValue += 360;transform.localEulerAngles = new Vector3(xLocalRotateValue, yLocalRotateValue, zLocalRotateValue);yLocalRotateValue = transform.localEulerAngles.y;zLocalRotateValue = transform.localEulerAngles.z;}/// <summary>/// 更新平衡轴的实时坐标值/// </summary>void UpdateBalancedValueF(){//将360度制的旋转量获取并更新到UpdateBalanceValueUpdateBalancedValue = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y, transform.localEulerAngles.z);BalanceAxisValue.y = transform.localEulerAngles.y;//转-180,180制UpdateBalancedValue = new Vector3(LimitAngle(UpdateBalancedValue.x, 180),LimitAngle(UpdateBalancedValue.y, 180),LimitAngle(UpdateBalancedValue.z, 180));BalanceAxisValue = new Vector3(LimitAngle(BalanceAxisValue.x, 180),LimitAngle(BalanceAxisValue.y, 180),LimitAngle(BalanceAxisValue.z, 180));}/// <summary>/// 三个LocalRotate值对接物体实际旋转值/// </summary>void Update3LocalRotateValue() {//更新三个旋转总值的值zLocalRotateValue = transform.localEulerAngles.z;xLocalRotateValue = transform.localEulerAngles.x;yLocalRotateValue = transform.localEulerAngles.y;}
}

主要实现功能

__这个控制器实现了简单的左飞(A),右飞(D),前进(W),后退(S),上升(Space),左旋(Q),右旋(E),上挑(1),下挑(2),自动水平平衡(B),限速,限高,这些功能。
游戏体结构如下图:

游戏体的结构图片


一些设计想法

__接下来说一下旋转和平衡功能,其它功能的实现看注释就ok了。旋转我是设置了三个轴的旋转总值,根据需求固定增``加某总值,在将三个总值赋值给飞机自身的旋转量,在开头初始化对接了自身的旋转量。每次旋转完后也会更新三个旋转量,还有一次就是在退出自动平衡状态时调用了。
__之后是自动平衡。自动平衡就是两个三维向量的运算。一个标准的平衡位置向量和一个当前三个旋转轴值的向量。求出两个向量的差值,并运用协程每一帧增加一个差值/n的量,当两者之间的差值模小于1时,认为达到平衡状态。
__这里需要注意的时标准平衡位置有两个个轴的值是固定的,剩下的一个轴的值要在进行自动平衡时更新,即保留它的水平旋转。而当前三个旋转轴值的向量需要在自动平衡时更新对接一下游戏体实际的旋转值量。
即一个是(0,nowRotatey,0),一个是(nowRotatex,nowRotatey,
nowRotatez)

结尾

接触unity脚本没有多深,可能会觉得代码有些地方写的不好,请见谅。

Unity 3d飞机游戏制作1相关推荐

  1. Unity 3D飞机大战制作心得

     1.摄像机的设置需要注意:选择摄像机的投影方式为Orthographic(正交投影). 2.控制飞船的移动,其实就是控制一个3D的Vector3(x,y,z)的变换,首先需要得到 在x轴方向和z ...

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

    Unity学习笔记:Unity 3D 飞机大战 1.打开unity软件后,首先新建Quad作为背景,导入飞机模型,并为其添加刚体 然后创建C#脚本,挂载到飞机上. 2.给飞机创建子弹,让子弹成为预制体 ...

  3. Unity 3D 创建简单的几何模型 || Unity 3D Assets 游戏资源目录管理

    Unity 3D 创建简单的几何模型 Unity 3D 是一个强大的游戏开发引擎.在游戏开发中使用的模型常常是从外部导入的,Unity 3D 为了方便游戏开发者快速创建模型,提供了一些简单的几何模型, ...

  4. Unity 3D设定游戏背景色

    Unity 3D设定游戏背景色 1,方法1,通过窗口设定. 2,方法2,通过c#设定. void Start(){Color newColor = new Color(1f, 1f, 1f, 1f); ...

  5. 3D/VR游戏制作软件GameStudio简介

    3D/VR游戏制作软件GameStudio简介 2004-4-30 作者:虚怀若谷 转载自:5D多媒 网友评论 2 条 点击进入论坛 前言:GameStudio是一个可以制作3D/VR游戏的软件,通过 ...

  6. 使用 Unity 3D 开发游戏的几个架构设计难点

     Unity 3D 引擎对于开发者来说,入手非常快,因为它采用的是 C# 作为开发语言,这也大大降低了开发者的门槛.但凡只要懂一门编程语言的人都能使用 Unity 3D 引擎开发,另外 Unity 3 ...

  7. 使用 Unity 3D 开发游戏的架构设计难点

    作者:姜雪伟,网名:海阳,CSDN 博客专家,资深 3D 游戏引擎,IT 高级讲师,畅销书作者,从事 IT 行业 15 年,主导或参与了 18 款大型游戏的研发:国家专利发明人:已出版书籍:<手 ...

  8. GG修改Unity 3D加密游戏

    首先是提取Assembly-CSharp.dll文件,参见简单Unity 3D游戏加密dll文件提取 然后使用dnSpy找到要修改代码的特征码: 在set上鼠标右键"在十六进制编辑器中显示方 ...

  9. unity打飞机游戏简单制作

    欢迎来到unity学习.unity培训.unity企业培训教育专区,这里有很多U3D资源.U3D培训视频.U3D

最新文章

  1. float向u8和s8的转换
  2. Java 8 类型转换及改进
  3. c语言流程图图裂代表的意义,程序流程图的意义
  4. [大话数据结构-读书笔记] 栈
  5. UWP 文件读写API
  6. ECMAScript6入门教程(二)
  7. 内存墙,多核CPU的终结者?
  8. 【OpenCV 例程200篇】38. 图像的反色变换(图像反转)
  9. java定义数组_java中数组的三种定义方式_java中数组的定义及使用方法(推荐)...
  10. Linux笔记-Centos7将python2升级为python3(及修改yum配置防报错)
  11. 【华为云技术分享】物体检测yolo3算法 学习笔记(1)
  12. IEEE 迎来首位华人主席,马里兰大学终身教授刘国瑞当选
  13. Apache Phoenix学习记录(SQL on HBase)
  14. 如何提取HTML代码中img的src地址?
  15. Android之基于百度云推送IM
  16. java编程:对两个分数进行简单的算术运算
  17. 对图片进行剪切,保留原始比例
  18. 兵棋---棋盘绘制算法(六边形阵列算法)
  19. win10 右键新建卡顿
  20. Springboot 实现将文件压缩,然后下载

热门文章

  1. 职中选什么专业好_职高毕业,迷茫中,选什么专业和学校好
  2. CSDN【精品专栏】第三期
  3. 已知抛物线与直线相交两点和抛物线顶点,求抛物线和直线所围成的面积?
  4. 论文阅读笔记《USAC: A Universal Framework for Random Sample Consensus》
  5. ssh免密登录和阿里云epel安装
  6. java狗具有特别的接飞盘的方法_java第七章 多态 课堂笔记/作业
  7. python做值班表预测_Django model一张表中两个字段设置外键参考另一张表两个字段...
  8. 【对未来机器人的畅想】
  9. 使用Tomcat插件实现WEB项目热部署
  10. i510400和i512400差距