飞机运行轨迹,适应于战争游戏,超灵活。。。。。。自己手写的。

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;
        }
    }

}
 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

W低小调W

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值