• Unity3D之飞机游戏追踪导弹制作


    最近开发完成一款打飞机的游戏,记录一下制作追踪导弹的方法,最开始在网上找到的资料制作出来的追踪导弹都不够真实,主要的问题是没有对导弹进行一个阀值处理,导弹每帧都始终会面向目标,而不是按照一定的角度进行旋转,导致无法躲避跟踪导弹,下面我来说一下更加真实的跟踪导弹的制作方法。

    拖拽

    首先,我的Demo里有两个小飞机,一个是主角,一个是敌机,有一个需求就是这两个飞机可以通过鼠标进行拖拽,所以先给出拖拽的脚本,直接绑定即可,当然记得给GameObject添加一个BoxCollder。

     1 using UnityEngine;
     2 using System.Collections;
     3 
     4 /// <summary>
     5 /// 拖拽脚本.
     6 /// </summary>
     7 public class DragAndDrop : MonoBehaviour
     8 {
     9     bool isCatched = false;
    10 
    11     void Update()
    12     {
    13         if(Input.GetMouseButtonDown(0))
    14         {
    15             //根据鼠标位置创建一条垂直于屏幕的射线
    16             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    17             //保存射线信息的结构体
    18             RaycastHit hit;
    19             //对射线进行碰撞, 如果存在碰撞
    20             if(Physics.Raycast(ray, out hit))
    21             {
    22                 //碰撞到当前对象时
    23                 if(hit.collider.gameObject == this.gameObject)
    24                 {
    25                     //标记为抓取状态
    26                     isCatched = true;
    27                 }
    28             }
    29         }
    30 
    31         if(Input.GetMouseButtonUp(0))
    32         {
    33             //取消抓取状态
    34             isCatched = false;
    35         }
    36 
    37         if(isCatched)
    38         {
    39             //获取鼠标点在场景中的位置
    40             Vector3 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    41             pos.z = 0;
    42             //设置位置
    43             this.transform.position = pos;
    44         }
    45     }
    46 }

    管理类

    我使用UGUI添加了一个发射导弹的按钮,需要一个管理类来管理这部分的逻辑:

     1 using UnityEngine;
     2 using System.Collections;
     3 
     4 /// <summary>
     5 /// 控制脚本.
     6 /// </summary>
     7 public class TrackDemoScript : MonoBehaviour
     8 {
     9     public GameObject player;
    10 
    11     public GameObject enemy;
    12 
    13     /// <summary>
    14     /// 开火.
    15     /// </summary>
    16     public void Fire()
    17     {
    18         GameObject go = Resources.Load<GameObject>("Prefab/Bullet");
    19         GameObject bullet = Instantiate(go, player.transform.position, Quaternion.identity) as GameObject;
    20         bullet.GetComponent<BulletScript>().target = enemy;
    21     }
    22 }

    导弹被我制作为了一个预制件。

    导弹逻辑

    最重要的就是阀值了,我规定了每帧允许旋转的一个最大值,保证模拟出现实世界的效果,导弹要转弯肯定是画出一个弧线而不是马上掉头的。

     1 using UnityEngine;
     2 using System.Collections;
     3 
     4 /// <summary>
     5 /// 跟踪导弹脚本.
     6 /// </summary>
     7 public class BulletScript : MonoBehaviour
     8 {
     9     /// <summary>
    10     /// 每秒最大可旋转的角度.
    11     /// </summary>
    12     private const float MAX_ROTATION = 90;
    13     
    14     /// <summary>
    15     /// 每帧最大可旋转的角度.
    16     /// </summary>
    17     private static float MAX_ROTATION_FRAME = MAX_ROTATION / ((float) (Application.targetFrameRate == -1 ? 60 : Application.targetFrameRate));
    18 
    19     /// <summary>
    20     /// 攻击目标.
    21     /// </summary>
    22     public GameObject target;
    23 
    24     void Start()
    25     {
    26     }
    27     
    28     void Update()
    29     {
    30         //转向目标
    31         float dx = target.transform.position.x - this.transform.position.x;
    32         float dy = target.transform.position.y - this.transform.position.y;
    33         float rotationZ = Mathf.Atan2(dy, dx) * 180 / Mathf.PI;
    34         //得到最终的角度并且确保在 [0, 360) 这个区间内
    35         rotationZ -= 90;
    36         rotationZ = MakeSureRightRotation(rotationZ);
    37         //获取增加的角度
    38         float originRotationZ = MakeSureRightRotation(this.transform.eulerAngles.z);
    39         float addRotationZ = rotationZ - originRotationZ;
    40         //超过 180 度需要修改为负方向的角度
    41         if(addRotationZ > 180)
    42         {
    43             addRotationZ -= 360;
    44         }
    45         //不超过每帧最大可旋转的阀值
    46         addRotationZ = Mathf.Max(-MAX_ROTATION_FRAME, Mathf.Min(MAX_ROTATION_FRAME, addRotationZ));
    47         //应用旋转
    48         this.transform.eulerAngles = new Vector3(0, 0, this.transform.eulerAngles.z + addRotationZ);
    49         //移动
    50         this.transform.Translate(new Vector3(0, 2.0f * Time.deltaTime, 0));
    51     }
    52 
    53     /// <summary>
    54     /// 确保角度在 [0, 360) 这个区间内.
    55     /// </summary>
    56     /// <param name="rotation">任意数值的角度.</param>
    57     /// <returns>对应的在 [0, 360) 这个区间内的角度.</returns>
    58     private float MakeSureRightRotation(float rotation)
    59     {
    60         rotation += 360;
    61         rotation %= 360;
    62         return rotation;
    63     }
    64 }

    运行即可查看效果。

    源码下载

    http://pan.baidu.com/s/1qWBsvSg

  • 相关阅读:
    Redis 集群
    应用系统日志采集解决方案
    Flume学习应用:Java写日志数据到MongoDB
    一次开发逻辑规范的总结
    JSP2 自定义标签
    mysql的left join、 right join和inner join
    静态网页、动态网页、apache和tomcat之间区别和联系
    spring与shiro配置详解
    maven项目在eclipse启动报错:java.lang.ClassNotFoundException
    如何修改maven的默认jdk版本
  • 原文地址:https://www.cnblogs.com/hammerc/p/4860743.html
Copyright © 2020-2023  润新知