前言
这个一个2d游戏的跟踪导弹游戏,这个轨迹有两个要点:1.实现跟踪、2.轨迹成弧线。
效果
逻辑
1.实现跟踪:子弹一直朝着目标移动。
求得目标的方向:
dir = target - self.position;
利用unity 中的正切函数取得该方向在世界左边下的角度:
angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
得到角度旋转子弹方向:
self.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
2.实现轨迹弧线:在朝向目标后在加一个旋转,随着靠近目标这个旋转逐渐减小。
代码
using System;
using System.Timers;
using Unity.Mathematics;
using UnityEngine;
using Random = UnityEngine.Random;
/// <summary>
/// 追踪弹
/// </summary>
public class Track : MonoBehaviour
{
// 子弹
private Rocket _self;
[Header("移动速度")]
public float moveSpeed= 5; //移动速度
[Header("随机扭曲弹道")]
public float RandomRotateMin = -50; //随机旋转角度
public float RandomRatateMax = +50;
private float RandomRotate;
private Transform target; //跟踪目标
// 距离敌人距离
private float _targetDis;
private void Start()
{
// 初始化
_self = GetComponent<Rocket>();
target = _self.Target;
// 随机角度值
RandomRotate = Random.Range(RandomRotateMin, RandomRatateMax);
// 距离敌人距离
_targetDis = Vector3.Distance(transform.position, target.position);
}
private void Update()
{
TrackUnit();
}
private void TrackUnit()
{
if (target != null) //判断当前是否有跟踪目标 如果有的话 执行 以下跟踪逻辑
{
// 追踪
TrackUnit(transform,target.position);
// 扭曲
var rotateValue = RandomRotate;
// 距离比例
var disRatio = Vector3.Distance(transform.position, target.position) / _targetDis;
// 根据距离控制扭曲角度
if (disRatio > 1)
rotateValue = 0;
else if(disRatio < 1)
rotateValue = RandomRotate * disRatio;
// 限制扭曲角度范围
rotateValue = Mathf.Clamp(rotateValue, RandomRotateMin, RandomRatateMax);
// 扭曲弹道
transform.rotation *= Quaternion.Euler(new Vector3(0,0,rotateValue));
}
//向前移动
transform.position += transform.up * (moveSpeed * Time.deltaTime);
}
/// <summary>
/// 用某个轴去朝向物体 (这也是看向目标的方法可用于3d跟踪导弹)
/// </summary>
/// <param name="tr_self">朝向的本体</param>
/// <param name="lookPos">朝向的目标</param>
/// <param name="directionAxis">方向轴,取决于你用那个方向去朝向</param>
void AxisLookAt(Transform tr_self, Vector3 lookPos, Vector3 directionAxis)
{
var rotation = tr_self.rotation;
var targetDir = lookPos - tr_self.position;
//指定哪根轴朝向目标,自行修改Vector3的方向
var fromDir = tr_self.rotation * directionAxis;
//计算垂直于当前方向和目标方向的轴
var axis = Vector3.Cross(fromDir, targetDir).normalized;
//计算当前方向和目标方向的夹角
var angle = Vector3.Angle(fromDir, targetDir);
//将当前朝向向目标方向旋转一定角度,这个角度值可以做插值
tr_self.rotation = Quaternion.AngleAxis(angle, axis) * rotation;
}
// 扭转
void TrackUnit(Transform self,Vector3 target)
{
var dir = target - self.position;
// 世界坐标系下的角度
var angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
// 旋转z轴 这里 -90 是为了让 Y轴对齐目标
self.rotation = Quaternion.AngleAxis(angle - 90f, Vector3.forward);
}
}