利用Unity实现导弹飞行的算法网上案例很多,本篇博客主要给读者介绍如何将所学算法运用到项目开发的实战教程。
我们将使用运动学原理实现仿真,这意味着我们将只在计算中使用速度,而不考虑物体上的质量和其他作用的物理力,这些力会影响物体的运动,比如阻力。为了能够模拟导弹击中目标,我们将考虑以下变量:
发射速度,发射角度,导弹距离目标的距离。
很多程序员学过算法,学过数据结构,但是在项目开发过程中就不会灵活运用了,所以有些人觉得以前学的知识没用,其实这是完全错误的,大学读书的过程也是一种培养能力的过程,大学所学的都是一些基础知识,他也是为我们以后能够自学打下基础。而且大学学习的算法在游戏开发中用的非常多,我们也借助本篇博客告诉读者如何将所学知识应用到项目开发中。
下面我们就围绕算法讲解实现过程:
我们将从运动的运动学方程开始,其实也就是我们说的抛物线方程,它描述了基于初始速度和加速度所获取到的位置:

P1是最后的位置,P0是初始位置,v0初始速度,a加速度,t是运动持续时间。我们在纸上推导一下数学公式,看能到什么结果?

a是发射角度,V0是初始速度,V0x,V0y是初始速度V0的两个分量,H是沿着y轴位置距离差,R是沿x轴的位置距离差,t就是抛物线运动的时间。
通过我们的推演可以知道以下几个条件:一是,在x轴的运动距离是R,初始速度是V0x,运行时间是t;二是,在y轴运动距离是H,初始速度是V0y,重力G以及运行轨迹的时间t;三是,沿着y轴的距离H, x轴R, G重力,发射角α和初速度V0x也就是V0的分量。利用我们的这些已经计算好的公式,最终推导出上图的公式如下所示:

在解答方程之前,我们还要解决一个问题就是导弹朝向目标问题,在Unity中提供了LookAt函数,再思考目标物体和导弹的高度不同的情况,虽然我们希望在下面的gif中使用左边的效果,但是如果使用LookAt()函数,我们将获得右边的效果。

如果我们像这样放弃目标的Y分量和抛射体的位置,我们可以达到预期的“转向”效果,代码如下所示:

void Launch()
{// think of it as top-down view of vectors: //   we don't care about the y-component(height) of the initial and target position.Vector3 projectileXZPos = new Vector3(transform.position.x, 0.0f, transform.position.z);Vector3 targetXZPos = new Vector3(TargetObjectTF.position.x, 0.0f, TargetObjectTF.position.z);// rotate the object to face the targettransform.LookAt(targetXZPos);// ...
}

接下来我们开始解方程,解方程首先要确定上述公式中每个变量所能标识的含义,先看G,在Unity中,它表示的是重力的y值,G=Physics.gravity.y;
tan(α)=Mathf.Tan(LaunchAngle * Mathf.Deg2Rad);
R = Vector3.Distance(projectileXZPos, targetXZPos);
H=TargetObjectTF.position.y - transform.position.y;
在Unity中的表示如下所示:
公式计算出来后,我们要将公式用编程语言表达出来,这个也就是所谓的理论联系实际,对应代码如下所示:

void Launch()
{// ...// shorthands for the formulafloat R = Vector3.Distance(projectileXZPos, targetXZPos);float G = Physics.gravity.y;float tanAlpha = Mathf.Tan(LaunchAngle * Mathf.Deg2Rad);float H = (TargetObjectTF.position.y + GetPlatformOffset()) - transform.position.y;// calculate initial speed required to land the projectile on the target object float Vz = Mathf.Sqrt(G * R * R / (2.0f * (H - R * tanAlpha)) );float Vy = tanAlpha * Vz;// create the velocity vector in local space and get it in global spaceVector3 localVelocity = new Vector3(0f, Vy, Vz);// ...
}

以上我们的计算数值是在局部空间中计算得到的,我们的导弹发射是在世界空间中,所以还需要一个矩阵转换,Unity已经为我们想到了,使用函数:Transform.TransformDirection()
这样我们的导弹飞行函数就完善了,完整的导弹发射函数如下所示:

void Launch()
{// think of it as top-down view of vectors: //   we don't care about the y-component(height) of the initial and target position.Vector3 projectileXZPos = new Vector3(transform.position.x, 0.0f, transform.position.z);Vector3 targetXZPos = new Vector3(TargetObjectTF.position.x, 0.0f, TargetObjectTF.position.z);// rotate the object to face the targettransform.LookAt(targetXZPos);// shorthands for the formulafloat R = Vector3.Distance(projectileXZPos, targetXZPos);float G = Physics.gravity.y;float tanAlpha = Mathf.Tan(LaunchAngle * Mathf.Deg2Rad);float H = TargetObjectTF.position.y - transform.position.y;// calculate the local space components of the velocity // required to land the projectile on the target object float Vz = Mathf.Sqrt(G * R * R / (2.0f * (H - R * tanAlpha)) );float Vy = tanAlpha * Vz;// create the velocity vector in local space and get it in global spaceVector3 localVelocity = new Vector3(0f, Vy, Vz);Vector3 globalVelocity = transform.TransformDirection(localVelocity);// launch the object by setting its initial velocity and flipping its staterigid.velocity = globalVelocity;bTargetReady = false;
}

上述代码,对应的实现效果如下所示:

这里还需要解决的问题就是导弹的飞行方向,我们的导弹不仅要命中目标还要方向时时朝向目标,就比如下图所示的:

关于朝向问题,使用Unity提供的函数lookat()改变导弹的方向,使其局部向前矢量对准目标方向,我们可以利用碰撞器组件来检测导弹是否触地,并根据速度矢量更新其旋转,从而解决这个问题。更新导弹旋转使用的函数是:Quaternion.LookRotation(),对应的代码实现如下所示:

public class Trajectory : MonoBehaviour
{//...// stateprivate bool bTargetReady;private bool bTouchingGround;//...// Update is called once per framevoid Update (){// ...if (!bTouchingGround && !bTargetReady){// update the rotation of the projectile during trajectory motiontransform.rotation = Quaternion.LookRotation(rigid.velocity);}}void OnCollisionEnter(){bTouchingGround = true;}void OnCollisionExit(){bTouchingGround = false;}
}

对应的Unity实现如下所示:

显然上图并不是我们想要的结果,我们希望我们的正向向量指向圆柱体顶端的默认方向,如下面的全局空间向量所示:

四元数的一个优点是可以通过使用乘法运算符Quaternion.operator*()来组合它们。我们可以将从quaternion . lookrotation()函数中获得的旋转与初始旋转initialRotation 结合起来,从而为导弹对象实现正确的轨迹方向。我们把从右到左的旋转组合起来,如下所示:

transform.rotation = Quaternion.LookRotation(rigid.velocity) * initialRotation;

还要注意,组合旋转不是交换操作,所以乘法的顺序很重要(a B != B a)。我们实现“组合旋转”的方法和它的数学细节可以参考网址:
https://math.stackexchange.com/questions/331539/combining-rotation-quaternions/331548#331548
如下所示:

这意味着四元数.LookRotation(rigid.velocity) * initialRotation将首先对对象应用initialRotation来实现“我们想要的默认方向”,然后应用LookRotation(rigid.velocity)来沿弹道轨迹旋转导弹,导弹会指向速度方向,如下图所示。

demo下载地址:链接:https://pan.baidu.com/s/1-3R9HN045xVJlAejTjl7gQ
提取码:ct11

参考网址:
https://gamedev.stackexchange.com/questions/114759/how-do-i-set-angular-velocity-torque-so-that-its-pointing-to-velocity-direction
https://en.wikipedia.org/wiki/Projectile_motion
https://en.wikipedia.org/wiki/Trajectory
https://en.wikipedia.org/wiki/Kinematics
https://en.wikipedia.org/wiki/Trigonometry
https://en.wikipedia.org/wiki/Quaternion
https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
https://docs.unity3d.com/ScriptReference/Quaternion.html
https://docs.unity3d.com/Manual/QuaternionAndEulerRotationsInUnity.html

利用运动学实现导弹仿真飞行相关推荐

  1. 【导弹仿真】基于matlab导弹轨迹和撞击位置仿真【含Matlab源码 2067期】

    ⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[导弹仿真]基于matlab导弹轨迹和撞击位置仿真[含Matlab源码 2067期] 点击上面蓝色字体,直接付费下载,即可. 获取代码方式 ...

  2. 【AeroSim 六自由度仿真飞行模块】一、安装与demo运行问题

    AeroSim  Blockset 的模块是与MATLAB中simulink结合使用,模拟飞行器六自由度飞行模块. 需要的安装包: AeroSim (可以在PUDN中找到,免费下载https://do ...

  3. 模拟仿真最终利用计算机,基于计算机仿真模拟实验的应用分析

    计算机技术应用 t h e A p p l i c a t i o n o f C o mp u t e r T e c h n o l o g y 基于计算机仿真模拟实验的应用分析 文/吴婷 Mi ...

  4. 利用IT++搭建通信仿真平台

    IT++ is a C++ library of mathematical, signal processing and communication classes and functions.也就是 ...

  5. 利用FPGA仿真软件modelsim仿真波形显示图片

    之前参考过几篇博文介绍如何使用仿真软件(比如modelsim)产生字符效果波形的,但是发现在进行具体修改时还是挺麻烦的,且无法产生图片这种更加直观的效果. 所以本次打算重新设计代码,升级为显示效果更好 ...

  6. 利用eNSP进行VPLS仿真实验

    While a VLL or VPWS Layer 2 VPN only allows point-to-point interconnection, VPLS is a technology tha ...

  7. Pixhawk软件仿真飞行测试

    环境 Ubuntu 14.04 ROS - indigo (注意非ros-indogo-desktop-full安装) Gazebo6 (版本也要对应) Pixhawk_firmwork 版本 Qgr ...

  8. 六自由度机器人(机械臂)运动学建模及运动规划系列(三)——机器人建模及运动学分析的Matlab仿真

    在完成机器人的建模以及运动学分析之后,可以利用Matlab中的Robotics工具箱进行仿真. 本篇目录 一.工具箱下载 二.机器人建模仿真 三.机器人运动学计算仿真 四.小结 一.工具箱下载 要在M ...

  9. 六自由度方程组 matlab,采用Matlab的六自由度机器人三维运动学仿真_李庆.pdf

    采用Matlab的六自由度机器人三维运动学仿真_李庆 第 ( ) 3 卷 第 期 华侨大学学报 自然科学版 7 3 Vol.37 No.3 年 月 ( ) 2016 5 JournalofHua ia ...

  10. 在Simulink中利用simmechanics对三自由度的串联机械臂进行仿真

    在写本科的毕业论文的时候,需要对三自由度的机械臂进行一个仿真实验.在网上查阅相关资料,得知可以利用simmechanics 来进行仿真实验.关于simmechanics 这个的介绍就百度一下就可以,这 ...

最新文章

  1. 大一就会这么多,还在问有没有前途? | 每日趣闻
  2. 如何利用python3创建数据表_python3创建表及表数据;
  3. LOL手游超燃测试好评如潮,没拿到资格不用急,期待一手不删档
  4. html5软件下载页面源码
  5. 对 5G “迟钝”的苹果,该如何后来居上?| 极客头条
  6. Zabbix 系统监控(三)VMware 虚拟平台监控、邮件告警、企业微信告警配置
  7. 单机多实例数据库搭建过程
  8. toad 连接mysql8.0_toad for mysql免费版
  9. Android控件-TabLayout使用介绍
  10. 异常:贴dependency报错
  11. 单片机at89c51数字钟c语言,基于AT89C51单片机的数字钟设计
  12. [Qt]使用QSS的扁平化风格的小作业—— 附源码
  13. SublimeText 3.2.3207 汉化破解免安装版(3264位)
  14. 易基因|3文聚焦:宏病毒组测序在肠病中的应用研究
  15. 电子产品安全认证有哪些?
  16. js 监听浏览器窗口大小变化
  17. 如何把gif做成html,gif怎么倒放
  18. 酒店直播服务器系统,用ffmpeg+nginx服务器实现类似酒店视频直播系统
  19. (附源码)springboot球鞋调货管理系统 毕业设计 160942
  20. 在Windows中安装OpenCV-Python | 四

热门文章

  1. 案例|高稳定紫外LED光源助力流体力学PSP技术
  2. 【基础】创建react脚手架
  3. Python 操作pdf文件-合并操作 (三)
  4. tpadmin隐藏index.php,百度云服务器tp5框架布署,隐藏路径中的index.php
  5. FrameMaker 2019中文版
  6. Leetcode 75. 颜色分类
  7. 【华为HCIE考试卷在哪买?】
  8. 第3章-线性概率模型(1)-logistics/probit模型
  9. 自抗扰控制器七-二阶 LADRC-PLL 结构设计
  10. 基于Android的防疫信息管理系统源码【包调试运行】