飞机运行轨迹,适应于战争游戏,超灵活。。。。。。自己手写的。
using UnityEngine;
using System;
/// <summary>
/// 左右旋转枚举
/// </summary>
public enum RotType
{
Left = 1,
Right = -1
}
/// <summary>
/// 飞机运行状态
/// </summary>
public enum PlaneState
{
Idle,
AutoFly,
BeginAttacked
}
public class AirPlanePath : MonoBehaviour
{
//左旋转与右旋转
public RotType rotType = RotType.Right;
//飞机状态
public PlaneState planeState = PlaneState.Idle;
//Dir旋转速度
public float rotDirSpeed = 1;
//SideWay旋转速度
public float rotSideWaySpeed = 1;
//飞行速度
public float speed = 1;
//出发点
public Transform bornPos;
//目标点
public Transform targetPos;
//初始的角度值
public float startSidewayAngle;
//目标角度值
public float targetSidewayAngle;
//飞行高度
public float heigh = 3;
//上升速度
public float upSpeed = 1;
//上升速度
public float downSpeed = 1;
//开始打击的距离
public float disAttack = 16;
//返回基地开始降落点
public float disLand = 16;
//降落时前行速度减值
public float minusSpeed = 1;
//距离基地点的距离目标值
public float dis_Born = 1.5f;
//计数器
private float times = 0;
//基地制高点
private Vector3 bornTop;
//基地点为0,目标点为180,正为右,负为左,依次排列为圆周状
public float circleAngle = 0;
//初始位置差值调节
float offect = 0;
//百分比
private float percent = 0.5f;
//平衡飞机降低x旋转
private float angle_x_Speed = 10f;
//获取直线距离最后x角
private float static_x;
// Use this for initialization
void Start()
{
transform.LookAt(targetPos);
bornTop = new Vector3(bornPos.position.x , bornPos.position.y + heigh, bornPos.position.z);
offect = 2 * GetAngle();//差值矫正
}
private float GetAngle()
{
return Vector3.Angle((targetPos.position - bornPos.position), GetCircleMax(bornPos.position, targetPos.position) - bornPos .position);
}
private Vector3 GetCircleMax(Vector3 born, Vector3 target ,float angle=0f)
{
Vector3 mid = GetBetweenPoint(born , target , percent);
float r = Vector3.Distance(born ,target) * percent;
float x1 =mid.x+ r * Mathf.Cos((angle + offect) * Mathf.Deg2Rad);
float y1 = heigh;
float z1 =mid.z+ r * Mathf.Sin((angle + offect) * Mathf.Deg2Rad);
return new Vector3(x1, y1, z1);
}
private Vector3 GetBetweenPoint(Vector3 start, Vector3 end, float percents)
{
Vector3 normal = (end - start).normalized;
float distance = Vector3.Distance(start, end);
Vector3 pos = normal * (distance * percents) + start;
return new Vector3(pos.x, pos.y + heigh, pos.z);
}
private void MainMathodRotation(float deltime)
{
Vector3 targetDir =( GetCircleMax(bornPos.position , targetPos .position , (int)rotType*circleAngle) - transform.position).normalized;
Quaternion dirRotation = Quaternion.LookRotation(targetDir, Vector3.up);
// float lerpSpeed = GetSpeed(transform.forward, targetDir,deltime);
float lerpSpeed = GetSpeed(transform.forward, targetDir, rotDirSpeed, deltime);
Quaternion dir = Quaternion.Slerp(transform.rotation, dirRotation, lerpSpeed);
//float rotSpeed = GetSpeed(startSidewayAngle, targetSidewayAngle * (-(int)rotType),deltime);
float rotSpeed = GetSpeed(startSidewayAngle, targetSidewayAngle * (int)rotType, rotSideWaySpeed, deltime);
float rotValue = Mathf.LerpAngle(startSidewayAngle, targetSidewayAngle * (int)rotType, rotSpeed);
Quaternion sideWay = Quaternion.AngleAxis(rotValue, Vector3.forward);
transform.rotation = dir * sideWay;
}
#region 暂时不用
//private float GetSpeed(Vector3 v1, Vector3 v2,float deltime)
//{
// float angle = Vector3.Angle(v1, v2);
// float needTime = angle / rotDirSpeed;
// return (deltime / needTime);
//}
//private float GetSpeed(float v1, float v2,float deltime)
//{
// float angle = Mathf.Abs(v1 - v2);
// float needTime = angle / rotSideWaySpeed;
// return (deltime / needTime);
//}
#endregion
private float GetSpeed<T>(T v1, T v2, float rotspeed, float deltime)
{
float angle = 0;
if (typeof(T) == typeof(System.Single))
{
float? a = v1 as float?;
float? b = v2 as float?;
if (a != null && b != null)
{
angle = Mathf.Abs(a.Value - b.Value);
}
}
else if (typeof(T) == typeof(Vector3))
{
Vector3? a = v1 as Vector3?;
Vector3? b = v2 as Vector3?;
if (a != null && b != null)
{
angle = Vector3.Angle(a.Value, b.Value);
}
}
float needTime = angle / rotspeed;
return (deltime / needTime);
}
/// <summary>
/// 爬升
/// </summary>
/// <param name="deltime"></param>
private void ClampHeigh(float deltime)
{
float y = Mathf.Lerp(transform.position.y, heigh, deltime / ((heigh - transform.position.y) / upSpeed));
transform.position = new Vector3(transform.position.x, y, transform.position.z);
}
/// <summary>
/// 降落
/// </summary>
/// <param name="deltime"></param>
private void LandBorn(float deltime)
{
times += deltime * downSpeed;
float y = Mathf.Lerp(transform.position.y, bornPos.position.y, times * deltime);
transform.position = new Vector3(transform.position.x, y, transform.position.z);
}
// Update is called once per frame
void Update()
{
switch (planeState)
{
case PlaneState.Idle:
break;
case PlaneState.AutoFly:
transform.position = Vector3.MoveTowards(transform.position, targetPos.position, Time.deltaTime * speed);
ClampHeigh(Time.deltaTime);
if (Vector3.Distance(transform.position, targetPos.position) < disAttack)
{
static_x = transform.eulerAngles.x;
planeState = PlaneState.BeginAttacked;
}
break;
case PlaneState.BeginAttacked:
if (Vector3.Distance(transform.position, bornTop) < disLand)
{
if (Vector3.Distance(transform.position, bornPos.position) < dis_Born)
{
planeState = PlaneState.Idle;
}
transform.position = Vector3.MoveTowards(transform.position, bornTop, Time.deltaTime * (speed = Mathf.Clamp((speed -= Time.deltaTime * minusSpeed), 0, speed)));
LandBorn(Time.deltaTime);
}
else
{
MainMathodRotation(Time.deltaTime);
transform.eulerAngles = new Vector3(Mathf.Clamp((static_x -= Time.deltaTime*angle_x_Speed), 360, static_x), transform.eulerAngles.y, transform.eulerAngles.z);
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
break;
default:
Debug.Log("plane have not planeState");
break;
}
}
}