unity笔记(脚本4)

/// <summary>
/// 贝塞尔曲线生成器
/// </summary>
public class BezierGenerate : MonoBehaviour
{
    public Transform beginTF;
    public Transform controlTF01;
    public Transform controlTF02;
    public Transform endTF;

    /// <summary>
    /// 创建贝塞尔曲线坐标点
    /// </summary>
    /// <param name="beginPos"></param>
    /// <param name="controlPos01"></param>
    /// <param name="controlPos02"></param>
    /// <param name="endPos"></param>
    /// <param name="t"></param>
    /// <returns></returns>
    public static Vector3 CreateBezierCurvePoint(Vector3 beginPos, Vector3 controlPos01, Vector3 controlPos02, Vector3 endPos,float t)
    {
        return beginPos * Mathf.Pow(1 - t, 3) + 3 * controlPos01 * t * Mathf.Pow(1 - t, 2) + 3 * controlPos02 * Mathf.Pow(t, 2) * (1 - t) + endPos * Mathf.Pow(t, 3);
    }

    /// <summary>
    /// 节点
    /// </summary>
    public int nodeCount = 20;

    public List<Vector3> pointList;

    private void Start()
    {
        pointList = new List<Vector3>(nodeCount);

        GeneratePoints();
        DrawCurve();
        CalculateNodeIntervals();
    }

    public void GeneratePoints()
    {
        //计算比例的间隔
        float interval = 1.0f / (nodeCount - 1);
        float t =0;
        for (int i = 0; i < nodeCount; i++)
        {
            Vector3 pos = CreateBezierCurvePoint(beginTF.position, controlTF01.position, controlTF02.position, endTF.position, t);
            pointList.Add(pos);
            t += interval;
        }
    }

    public void DrawCurve()
    {
        var renderer = GetComponent<LineRenderer>();
        renderer.SetVertexCount(pointList.Count);
        renderer.SetPositions(pointList.ToArray());
    }

    //节点间距
    private float[] nodeIntervals;
    private void CalculateNodeIntervals()
    {
        nodeIntervals = new float[nodeCount - 1];
        for (int i = 0; i < nodeIntervals.Length; i++)
        {
            nodeIntervals[i] = Vector3.Distance(pointList[i], pointList[i + 1]);
        } 
    }

    private void CalculateIndexAndRatioByDistance(float distance, out int index, out float ratio)
    {
        float sum = 0;
        for (int i = 0; i < nodeIntervals.Length; i++)
        {
            sum += nodeIntervals[i];
            if (sum >= distance)
            {
                ratio = 1 - (sum - distance) / nodeIntervals[i];
                index = i;
                return;
            }
        }
        //移动距离超过曲线长度
        ratio = -1;
        index = -1;
    }

    public Vector3 GetPoint(float distance)
    {
        int index;
        float ratio;

        CalculateIndexAndRatioByDistance(distance, out index, out ratio);

        if (index == -1) return pointList[pointList.Count - 1];

        return Vector3.Lerp(pointList[index], pointList[index + 1], ratio); 
    }
}
public class DoMovement : MonoBehaviour
{
    public float distance = 0;
    public float speed = 10;

    private void Update()
    {
        distance += speed * Time.deltaTime;

        transform.position 
            = FindObjectOfType<BezierGenerate>().GetPoint(distance);
    } 
}
/// <summary>
/// 椭圆生成器
/// </summary>
public class EllipseGenerate : MonoBehaviour
{ 
  /// <summary>
  /// 创建椭圆坐标
  /// </summary>
  /// <param name="a">长轴长度</param>
  /// <param name="b">短轴长度</param>
  /// <param name="rad">弧度</param>
  /// <returns>坐标</returns>
    public static Vector3 CreatePoint(float a, float b, float rad)
    {
        return new Vector3(a * Mathf.Cos(rad), 0, b * Mathf.Sin(rad));
    }

    /// <summary>
    /// 曲线的节点数量
    /// </summary>
    public int nodeCount = 10;

    /// <summary>
    /// 椭圆角度
    /// </summary>
    public float angle = 360;

    /// <summary>
    /// 长轴
    /// </summary>
    public float a;
    /// <summary>
    /// 短轴
    /// </summary>
    public float b;

    public List<Vector3> pointList;

    /// <summary>
    /// 曲线所有节点总和
    /// </summary>
    public float length;

    private void Start()
    {
        pointList = new List<Vector3>(nodeCount);
        GeneratePoint();
        CalculateNodeInterval();
        CalculateLength();
        DrawCurve();
    }

    /// <summary>
    /// 生成贝塞尔曲线
    /// </summary>
    public void GeneratePoint()
    {
        pointList.Clear();
        //将最大角度转换为最大弧度
        float radMax = angle * Mathf.Deg2Rad;
        //每段占比
        float ratio = radMax / (nodeCount - 1);
        float t = 0;
        for (int i = 0; i < nodeCount; i++)
        {
            Vector3 point = CreatePoint(a, b, t);
            Vector3 worldPoint = this.transform.TransformPoint(point);
            pointList.Add(worldPoint);
            t += ratio;
        }
    }

    //绘制曲线  建议创建单独脚本
    private void DrawCurve()
    {
        LineRenderer line = GetComponent<LineRenderer>();
        line.SetVertexCount(pointList.Count);
        line.SetPositions(pointList.ToArray());
    }

    /// <summary>
    /// 获取曲线中坐标
    /// </summary>
    /// <param name="distance">距离</param>
    /// <returns>坐标</returns>
    public Vector3 GetPoint(float distance)
    {
        //1.计算distance在哪段节点(索引) ,以及比例
        //2.计算比例
        int index;
        float ratio;
        CalculateIndexAndRatio(distance, out index, out ratio);

        if (index == -1) return pointList[pointList.Count - 1];

        //3.通过Vector3.Lerp根据比例计算坐标
        return Vector3.Lerp(pointList[index], pointList[index + 1], ratio);
    }

    /// <summary>
    /// 根据比例获取曲线坐标
    /// </summary>
    /// <param name="ratio">比例</param>
    /// <returns></returns>
    public Vector3 GetPoint01(float ratio)
    {
        return GetPoint(ratio * length);
    }

    private float[] nodeIntervals;
    //计算各节点间距
    private void CalculateNodeInterval()
    {
        nodeIntervals = new float[nodeCount - 1];
        for (int i = 0; i < nodeIntervals.Length; i++)
        {
            nodeIntervals[i] = Vector3.Distance(pointList[i], pointList[i + 1]);
        }
    }

    //计算曲线总长度
    private void CalculateLength()
    {
        float sum = 0;
        for (int i = 0; i < nodeIntervals.Length; i++)
        {
            sum += nodeIntervals[i];
        }
        this.length = sum;
    }

    //根据曲线距离,计算节点索引以及比例
    private void CalculateIndexAndRatio(float distance, out int index, out float ratio)//8
    {
        float sum = 0;
        for (int i = 0; i < nodeIntervals.Length; i++)
        {
            sum += nodeIntervals[i];
            if (sum >= distance)
            {
                ratio = 1 - (sum - distance) / nodeIntervals[i];
                index = i;
                return;//退出方法
            }
        }
        //如果移动距离超过所有节点总和
        index = -1;
        ratio = -1;
    }
}
public class EulerDemo : MonoBehaviour
{
    public Vector3 euler;
    private void OnGUI()
    {
        euler = transform.eulerAngles;

        if (GUILayout.RepeatButton("沿X轴旋转"))
        {
            //Vector3 euler = transform.eulerAngles;
            //欧拉角 没有 方向 和 大小的概念。
            //x  y   z  沿某个轴的旋转角度 
            transform.eulerAngles += new Vector3(1, 0, 0);
        }
        if (GUILayout.RepeatButton("沿Y轴旋转"))
        {
            transform.eulerAngles += Vector3.up;
        }
        if (GUILayout.RepeatButton("沿Z轴旋转"))
        {
            transform.eulerAngles += Vector3.forward;
        }
    }
 
}
public class QuaternionDemo : MonoBehaviour
{
    private void Start()
    {
        //物体沿Y轴旋转50度
        Vector3 axis = Vector3.up;
        float rad = 50 * Mathf.Deg2Rad;
        Quaternion qt = new Quaternion();
        qt.x = Mathf.Sin(rad / 2) * axis.x;
        qt.y = Mathf.Sin(rad / 2) * axis.y;
        qt.z = Mathf.Sin(rad / 2) * axis.z;
        qt.w = Mathf.Cos(rad / 2);

        //transform.rotation = qt;
        transform.rotation = Quaternion.Euler(0, 50, 0);

        Debug.Log(transform.eulerAngles);
    }

    //计算
    private void OnGUI()
    { 
        if (GUILayout.RepeatButton("沿X轴旋转"))
        {  
            transform.rotation *= Quaternion.Euler(1, 0, 0);
            //transform.Rotate(1, 0, 0); //Rotate通过四元数实现
        }
        if (GUILayout.RepeatButton("沿Y轴旋转"))
        {
            transform.rotation *= Quaternion.Euler(0, 1, 0);
        }
        if (GUILayout.RepeatButton("沿Z轴旋转"))
        {
            transform.rotation *= Quaternion.Euler(0, 0, 1);
        }
    }

    private void Update()
    {
        Demo01();
    }

    private void Demo01()
    {  
        //计算物体右前方30度10m处坐标
        Vector3 worldPos =
            transform.position + Quaternion.Euler(0, 30, 0) * transform.rotation * new Vector3(0, 0, 10);

        Debug.DrawLine(transform.position, worldPos);
    }
}
/// <summary>
/// 切点探测器
/// </summary>
public class TangentDetector : MonoBehaviour
{
    private Vector3 leftTangent;
    private Vector3 rightTangent;

    private Transform playerTF;
    private float radius;
    private void Start()
    {
        GameObject playerGO  = GameObject.FindWithTag("Player");
        if (playerGO != null)
        {
            playerTF = playerGO.transform;
            radius = playerGO.GetComponent<CapsuleCollider>().radius;
        }
        else
        {
            this.enabled = false;
        }
    }

    public void CalaculateTangent()
    {
        Vector3 playerToExplosion = transform.position - playerTF.position;
        Vector3 playerToExplosionRadius = playerToExplosion.normalized * radius;
        float angle = Mathf.Acos(radius / playerToExplosion.magnitude) * Mathf.Rad2Deg;
        rightTangent =playerTF .position + Quaternion.Euler(0, angle, 0) * playerToExplosionRadius;
        leftTangent = playerTF.position + Quaternion.Euler(0, -angle, 0) * playerToExplosionRadius;
    }

    //**************测试**************
    private void Update()
    {
        CalaculateTangent();

        Debug.DrawLine(transform.position, leftTangent);
        Debug.DrawLine(transform.position, rightTangent);
    }
}

 

posted @ 2022-03-10 21:15  xms_667  阅读(40)  评论(0)    收藏  举报