标签:
最近开发完成一款打飞机的游戏,记录一下制作追踪导弹的方法,最开始在网上找到的资料制作出来的追踪导弹都不够真实,主要的问题是没有对导弹进行一个阀值处理,导弹每帧都始终会面向目标,而不是按照一定的角度进行旋转,导致无法躲避跟踪导弹,下面我来说一下更加真实的跟踪导弹的制作方法。
首先,我的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
标签:
原文地址:http://www.cnblogs.com/hammerc/p/4860743.html