关于导弹的飞行算法,网上有很多教程。简单算法无非是获取目标点的当前位置,然后导弹朝目标方向移动。高深点的,就是通过计算获取碰撞点然后朝着目标移动。如果你能看懂这个高深算法的话,可以去看原帖:http://game.ceeger.com/forum/read.php?tid=3919

需要注意的是,原帖存在错误。而且一些方法使用的不合理。下面是我整合后的代码,欢迎大家提出不同见解。

想要实现导弹的“拦截”功能,首先需要根据目标物体的速度,位置,导弹的速度,位置,计算出两者相交的预计点。然后导弹朝碰撞点移动。

因为目标可能做不规则运动,所以需要公式计算物体的平均速度。即速度=距离/时间。物体的方向,则是当前位置-上一位置。下面是计算物体的速度和方向的具体代码:

  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class SpeedTest : MonoBehaviour {
  5. private float lastTime;
  6. private Vector3 lastPos;
  7. private float dtime;
  8. [HideInInspector]
  9. public Vector3 CurrentVector;
  10. [HideInInspector]
  11. public float Speed;
  12.  
  13. // Update is called once per frame
  14. void OnEnable() {
  15. lastTime = Time.time;
  16. lastPos = transform.position;
  17. }
  18. void Update () {
  19. dtime = Time.time - lastTime;
  20. if (dtime > 0) {
  21. lastTime = Time.time;
  22.  
  23. Speed = PhycisMath.GetSpeed(lastPos, transform.position, dtime);
  24. CurrentVector = PhycisMath.GetDir(lastPos, transform.position);
  25. if (Mathf.Abs(Speed)<0.001f)
  26. {
  27. CurrentVector = transform.TransformDirection(Vector3.forward);
  28. }
  29. lastPos = transform.position;
  30. }
  31. }
  32. }

上面是通过位移来算的速度和方向,与物理效果无关,所以拥有更好的适用性,可以用来不规则的平滑运动计算。为了代码的直观,将一些常用的方法封装于一个静态方法类中。

  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class PhycisMath
  5. {
  6. public static float GetSpeed(Vector3 lastPos,Vector3 newPs,float time) {
  7. if (time == 0) return 0;
  8. return Vector3.Distance(lastPos, newPs) / time;
  9. }
  10. public static Vector3 GetDir(Vector3 lastPos, Vector3 newPs)
  11. {
  12. return (newPs - lastPos).normalized;
  13. }
  14. public static float GetDelta(float a,float b,float c) {
  15. return b * b - 4 * a * c;
  16. }
  17. public static float GetRad(float dis, float angle)
  18. {
  19. return -(2 * dis * Mathf.Cos(angle * Mathf.Deg2Rad));
  20. }
  21. public static float GetPom(float a, float b)
  22. {
  23. return 1-Mathf.Pow(a,b);
  24. }
  25. public static float GetSqrtOfMath(float a,float b, float d) {
  26. float a1 = (-b + Mathf.Sqrt(d)) / (2 * a);
  27. float a2 = (-b - Mathf.Sqrt(d)) / (2 * a);
  28.  
  29. return a1>a2?a1:a2;
  30. }
  31. public Vector3 GetHitPoint() {
  32. return Vector3.zero;
  33. }
  34. }

接下来是写一个雷达,通过一系列“复杂”的运算获取碰撞点位置。

  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class RadarOfRocket : MonoBehaviour {
  5. //我们的导弹的轨道计算是基于Transform的,
  6. //纯数学的计算,这样更精确,适用性更好
  7. public Transform target;//目标
  8. private SpeedTest rocketSpeed;//
  9. private SpeedTest targetSpeed;
  10.  
  11. private Vector3 targetDir;
  12. private float angle;
  13. private float distence;
  14.  
  15. private bool isAim = false;
  16.  
  17. public bool IsAim
  18. {
  19. get { return isAim; }
  20. set { isAim = value; }
  21. }
  22. private Vector3 aimPos;
  23.  
  24. public Vector3 AimPos
  25. {
  26. get { return aimPos; }
  27. set { aimPos = value; }
  28. }
  29. void checkTarget() {
  30. if (!(rocketSpeed=GetComponent<SpeedTest>()))
  31. {
  32. gameObject.AddComponent<SpeedTest>();
  33. rocketSpeed = GetComponent<SpeedTest>();
  34. }
  35. if (target&&!(targetSpeed = target.GetComponent<SpeedTest>()))
  36. {
  37. target.gameObject.AddComponent<SpeedTest>();
  38. targetSpeed = target.GetComponent<SpeedTest>();
  39. }
  40. }
  41. void OnEnable() {
  42.  
  43. checkTarget();
  44. }
  45. void Update() {
  46. if (target)
  47. TestAim();
  48. }
  49. public void TestAim() {
  50.  
  51. if (Mathf.Abs(targetSpeed.Speed) < 0.01f)
  52. { //物体的速度过小,则默认物体是静止的。
  53.  
  54. isAim = true;
  55. aimPos = target.position;
  56. }
  57. else {
  58. targetDir = transform.position - target.position;
  59. angle = Vector3.Angle(targetDir, targetSpeed.CurrentVector);
  60.  
  61. distence = targetDir.magnitude;
  62.  
  63. float a = PhycisMath.GetPom((rocketSpeed.Speed / targetSpeed.Speed), 2);
  64. float b = PhycisMath.GetRad(distence, angle);
  65. float c = distence * distence;
  66. float d = PhycisMath.GetDelta(a, b, c);
  67. isAim = d >= 0 && !float.IsNaN(d) && !float.IsInfinity(d);
  68.  
  69. if (isAim)
  70. {
  71. float r = PhycisMath.GetSqrtOfMath(a, b, d);
  72. if (r < 0) isAim = false;//如果得出的是负值,则代表交点有误
  73. aimPos = target.transform.position + targetSpeed.CurrentVector * r;
  74. }
  75.  
  76. }
  77.  
  78. }
  79. }

原博客中的解是获取较小的那个。但是据我测试,只有正解时目标点才正确。大家也可以进行测试。值得注意的是,导弹的速度必须要大于目标的速度,不然导弹无法靠近目标。

好,获取目标点的代码已经完成了。接着是导弹的飞行代码。关于这部分,一般的做法是通过移动+转向实现导弹的轨迹。代码很简单。距离和角度的过滤我就省略了,基本上新手都能写出来。

  1. using UnityEngine;
  2. using System.Collections;
  3. [RequireComponent(typeof(RadarOfRocket))]
  4. public class Missile : MonoBehaviour {
  5. private RadarOfRocket radar;
  6. public float Speed = 100;
  7. public float RoteSpeed = 3;
  8. public float Noise = 0;
  9. void OnEnable() {
  10. radar = GetComponent<RadarOfRocket>();
  11. }
  12. void Update() {
  13. Fly();
  14. if (radar.IsAim) {
  15. FlyToTarget(radar.AimPos-transform.position);
  16. }
  17. }
  18. private void FlyToTarget(Vector3 point) {
  19. if (point != Vector3.zero) {
  20. Quaternion missileRotation = Quaternion.LookRotation(point, Vector3.up);
  21.  
  22. transform.rotation = Quaternion.Slerp(transform.rotation, missileRotation, Time.deltaTime * RoteSpeed);
  23. }
  24.  
  25. }
  26. private void Fly() {
  27. Move(transform.forward.normalized+transform.right*Mathf.PingPong(Time.time,0.5f)*Noise, Speed*Time.deltaTime);
  28. }
  29. public void Move(Vector3 dir,float speed){
  30. transform.Translate(dir*speed,Space.World);
  31. }
  32. void OnTriggerEnter(Collider other)
  33. {
  34. print("hit");
  35. }
  36.  
  37. }

好,上面就是导弹的所有代码了。谢谢观看。

考虑到可能有小白拿到代码可能完全不知道怎么弄,故增加以下注释。

将Radar.cs脚本和Missile.cs脚本托给你做好的导弹。然后将目标Transform赋值给Radar的target即可完成拦截导弹的演示。

关于目标怎样的移动,你可以自己定义,像直线移动或者圆周移动,不规则平滑移动等等都可以进行拦截。具体的效果由参数控制,但是一定要注意导弹的速度一定要大于目标的

速度,拦截导弹才能发挥作用!

本文的链接是:http://www.cnblogs.com/jqg-aliang/p/4768101.html 转载请申明出处谢谢!

unity导弹算法 预计目标点的更多相关文章

  1. [UE4]记录瞬移目标点

    1.判定射线是否击中一个物体:LineTraceByChannel的Return Value返回值 2.击中的目标点:LineTraceByChannel.Out Hit.Location,如图提示文 ...

  2. Unity三消算法

    消除算法图文详解 三消算法首要实现的就是找到所有三个或三个以上的可消除对象,但直接找到这些对象是不太现实的,所以我们要将需求拆分.可不可以先获取所有图案相连的对象,进而在获取三消对象,这个算法也是众多 ...

  3. [Unity A*算法]A*算法的简单实现

    写在前面:之前看过一点,然后看不懂,也没用过. 最近正好重构项目看到寻路这块,想起来就去查查资料,总算稍微理解一点了,下面记录一下自己的成果(哈哈哈 :> ) 下面分享几篇我觉得挺不错的文章 A ...

  4. ros机器人导航设置原点,目标点

    之前利用movebase导航定位都是通过rviz用鼠标指来指去,实验时非常方便,但实际应用总不能也人工指来指去吧,这怎么体现智能呢 启动导航后,用以前使用的rviz设设置目标点来获取map坐标系下的位 ...

  5. 基于Unity的A星寻路算法(绝对简单完整版本)

    前言 在上一篇文章,介绍了网格地图的实现方式,基于该文章,我们来实现一个A星寻路的算法,最终实现的效果为: 项目源码已上传Github:AStarNavigate 在阅读本篇文章,如果你对于里面提到的 ...

  6. Unity实现A*寻路算法学习1.0

    一.A*寻路算法的原理 如果现在地图上存在两点A.B,这里设A为起点,B为目标点(终点) 这里为每一个地图节点定义了三个值 gCost:距离起点的Cost(距离) hCost:距离目标点的Cost(距 ...

  7. Unity实现A*寻路算法学习2.0

    二叉树存储路径节点 1.0中虽然实现了寻路的算法,但是使用List<>来保存节点性能并不够强 寻路算法学习1.0在这里:https://www.cnblogs.com/AlphaIcaru ...

  8. unity A*寻路 (三)A*算法

    这里我就不解释A*算法 如果你还不知道A*算法 网上有很多简单易懂的例子 我发几个我看过的链接 http://www.cnblogs.com/lipan/archive/2010/07/01/1769 ...

  9. Unity Lighting - The Precompute Process 预计算过程(二)

      The Precompute Process 预计算过程 In Unity, precomputed lighting is calculated in the background - eith ...

随机推荐

  1. android源码如何起步与阅读方法

    显然Eclipse不是阅读Android源码的好工具,不流畅,搜索低效,继承性关系/调用关系都无法有效查看.推荐Source Insight,在这个工具帮助下,你才可以驾驭巨大数量的Android 源 ...

  2. 解决tomcat启动慢

    1.在Tomcat环境中解决 可以通过配置JRE使用非阻塞的Entropy Source. 在catalina.sh中加入这么一行:-Djava.security.egd=file:/dev/./ur ...

  3. WebService注解

    package cn.itcast.service; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.W ...

  4. 让 sphinx 支持中文、日文和韩文

    在国内搜索 sphinx 的话找到的资源好像都是挺久远的,无奈之下只好跑到国外去找了.听起来有点不可思议,但是最近整 sphinx 的时候突然想到 mediawiki 官方有 sphinx 的安装介绍 ...

  5. ajax处理select下拉表单

    $('#gameid').change(function() { var gameid = $(this).val(); if (this.value != '') { $.ajax({ url: ' ...

  6. vim-程序员的利器

    个人觉得vi使用熟练后就离不开了,用了它效率会提升不少,但是没了它可能还赶不上以前的速度,给惯坏了. 以下是本人无耻的复制和粘贴的:(附图一张方便学习) Vim目前已经有各主流系统的版本,尽管vim较 ...

  7. html增加锚点定位

    第一种方法,也是最简单的方法是锚点用<a>标签,在href属性中写入DIV的id.如下: <!DOCTYPE html><html><head>< ...

  8. Xamarin for VS 4.0.1.145 Stable版免费完整破解补丁

    Xamarin for VS 4.0.1.145 Stable版免费完整破解补丁 支持Priority最高权限(超企业版)开发, 支持Android, IOS调试.  支持Android打包为Bund ...

  9. 缓存server设计与实现(五)

    上次讲到lru与缓存重建,这次主要讲一下关于过期处理的一些主要问题. 在讨论这个问题之前,有个相关的问题须要大家有所了解. 就是对于一个缓存如期仅仅来说,什么东西应该缓存,什么不应该缓存.这是一个比較 ...

  10. ORACLE用户角色与授权

    --创建一个用户CREATE USER test_user IDENTIFIED BY test_user; --创建一个角色 CREATE ROLE connect2 ; --为角色授权 GRANT ...