Unity使用DoTween实现抛物线效果

编辑: admin 分类: c#语言 发布时间: 2021-11-25 来源:互联网

Unity使用DoTween实现抛物线效果,供大家参考,具体内容如下

概要

public partial class EMath
{
    public static Vector3 Parabola(Vector3 start, Vector3 end, float height, float t)
    {
        float Func(float x) => 4 * (-height * x * x + height * x);

        var mid = Vector3.Lerp(start, end, t);

        return new Vector3(mid.x, Func(t) + Mathf.Lerp(start.y, end.y, t), mid.z);
    }

    public static Vector2 Parabola(Vector2 start, Vector2 end, float height, float t)
    {
        float Func(float x) => 4 * (-height * x * x + height * x);

        var mid = Vector2.Lerp(start, end, t);

        return new Vector2(mid.x, Func(t) + Mathf.Lerp(start.y, end.y, t));
    }
}

使用方法

public class Test : MonoBehaviour
{
    public Transform start;
    public Transform target;
    public Transform ball;

    private float t;

    private void Start()
    {
        DOTween.To(setter: value =>
            {
                Debug.Log(value);
                ball.position = Parabola(start.position, target.position, 10, value);
            }, startValue: 0, endValue: 1, duration: 5)
            .SetEase(Ease.Linear);
    }
}

效果演示

之前小编收藏了一段抛物线代码,分享给大家:unity实现炮弹运动轨迹(抛物线)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Parabol : MonoBehaviour
{
    private Rigidbody rgb;
    /// <summary>
    /// 目标
    /// </summary>
    public GameObject target;
    /// <summary>
    /// 子弹的发射点
    /// </summary>
    private Vector3 originPoint;

    private Vector3 aimPoint;
    /// <summary>
    /// 无弹道偏移的当前位置
    /// </summary>
    private Vector3 myVirtualPosition;
    /// <summary>
    /// 定位最后一帧
    /// </summary>
    private Vector3 myPreviousPosition;
    /// <summary>
    /// 是否可以发射
    /// </summary>
    private bool sw = false;
    private bool actived = false;
    /// <summary>
    /// 最大发射距离
    /// </summary>
    public float maxLaunch = 1f;
    /// <summary>
    /// 加速度计算计数器
    /// </summary>
    private float counter;
    /// <summary>
    /// 刚刚启动时的速度
    /// </summary>
    public float speed = 0.5f;
    /// <summary>
    /// 恒定加速度
    /// </summary>
    public float speedUpOverTime = 0.1f;
    /// <summary>
    /// 弹道偏移量(与目标的距离)
    /// </summary>
    public float ballisticOffset = 0.5f;

    void Start()
    {
        rgb = GetComponent<Rigidbody>();
        sw = true;
        if (target == null)
        {
            Destroy(gameObject);
        }
        else
        {
            aimPoint = target.transform.position;
        }
        originPoint = myVirtualPosition = myPreviousPosition = transform.position;
        
    }
    
    void Update()
    {
        if (target != null)
        {
            if (actived == false)
            {
                actived = true;
                PreLaunch();
            }
            else
            {
                if (sw == true)
                {
                    if (rgb.isKinematic == false)
                    {
                        Move();
                    }
                }
            }
        }
    }
    private void PreLaunch()
    {
        float xTarget = target.transform.position.x;
        float yTarget = target.transform.position.y;
        float zTarget = target.transform.position.z;
【本文出处:国外高防服务器 复制请保留原URL】        float xCurrent = transform.position.x;
        float yCurrent = transform.position.y;
        float zCurrent = transform.position.z;
        //目标之间的值
        float xDistance = Mathf.Abs(xTarget - xCurrent);
        float yDistance = yTarget - yCurrent;
        float zDistance = Mathf.Abs(zTarget - zCurrent);
        float fireAngle = 1.57075f - (Mathf.Atan((Mathf.Pow(maxLaunch, 2f) + Mathf.Sqrt(Mathf.Pow(maxLaunch, 4f) - 9.8f * (9.8f * Mathf.Pow(xDistance, 2f) + 2f * yDistance * Mathf.Pow(maxLaunch, 2f)+ 2f * zDistance * Mathf.Pow(maxLaunch, 2f)))) / (9.8f * xDistance)));
        float xSpeed = Mathf.Sin(fireAngle) * maxLaunch;
        float ySpeed = Mathf.Cos(fireAngle) * maxLaunch;
        float zSpeed = Mathf.Tan(fireAngle) * maxLaunch;
        //判断在左边还是右边
        if ((xTarget - xCurrent) < 0f) { xSpeed = -xSpeed; }    
        if ((zTarget - zCurrent) < 0f) { zSpeed = -zSpeed; }
        Calculation(ySpeed);                                                
        sw = true;
    }
    private void Calculation(float speedy)
    {
        NextPosition(Time.time % ((speedy / 9.81f) * 2));
    }
    private void NextPosition(float airtime)
    {
        float xTarget = target.transform.position.x;
        float yTarget = target.transform.position.y;
        float zTarget = target.transform.position.z;
        float speedy = target.GetComponent<Rigidbody>().velocity.y;
        float speedx = target.GetComponent<Rigidbody>().velocity.x;
        float speedz = target.GetComponent<Rigidbody>().velocity.z;
        Launch(xTarget + (speedx * airtime), yTarget + (speedy * airtime),zTarget+ (speedz * airtime));
    }
    private void Launch(float xTarget, float yTarget, float zTarget)
    {
        rgb.isKinematic = false;
        float xCurrent = transform.position.x;
        float yCurrent = transform.position.y;
        float zCurrent = transform.position.z;
        float xDistance = Mathf.Abs(xTarget - xCurrent);
        float yDistance = yTarget - yCurrent;
        float zDistance = Mathf.Abs(zTarget - zCurrent); 
        float fireAngle = 1.57075f - (Mathf.Atan((Mathf.Pow(maxLaunch, 2f) + Mathf.Sqrt(Mathf.Pow(maxLaunch, 4f) - 9.8f * (9.8f * Mathf.Pow(xDistance, 2f) + 2f * yDistance * Mathf.Pow(maxLaunch, 2f) + 2f * zDistance * Mathf.Pow(maxLaunch, 2f)))) / (9.8f * xDistance)));
        float xSpeed = Mathf.Sin(fireAngle) * maxLaunch;
        float ySpeed = Mathf.Cos(fireAngle) * maxLaunch;
        float zSpeed = Mathf.Tan(fireAngle) * maxLaunch;
        //判断在左边还是右边
        if ((xTarget - xCurrent) < 0f) { xSpeed = -xSpeed; } 
        if (!float.IsNaN(xSpeed) && !float.IsNaN(ySpeed))
        {
            rgb.velocity = new Vector3(xSpeed, ySpeed, zSpeed);
        }
        else
        {
            maxLaunch = maxLaunch + 0.3f;
            PreLaunch();
        }
    }

    private void Move()
    {
        counter += Time.fixedDeltaTime;
        //加速度提升
        speed += Time.fixedDeltaTime * speedUpOverTime;
        if (target != null)
        {
            aimPoint = target.transform.position;
        }
        //计算从发射点到目标的距离
        Vector3 originDistance = aimPoint - originPoint;
        //计算剩余距离
        Vector3 distanceToAim = aimPoint - myVirtualPosition; //发射点和目标之间的矢量距离
        //移动到目标
        myVirtualPosition = Vector3.Lerp(originPoint, aimPoint, counter * speed / originDistance.magnitude);// vector nội suy giữa vị trí ban đầu và mục tiêu
        //向轨迹添加弹道偏移
        transform.position = AddBallisticOffset(originDistance.magnitude, distanceToAim.magnitude);
        //将子弹旋转至弹道
        //Debug.Log("最后一帧的位置:" + myPreviousPosition);
        LookAtDirection(transform.position - myPreviousPosition);
        myPreviousPosition = transform.position;
    }
    private Vector3 AddBallisticOffset(float originDistance, float distanceToAim)
    {
        if (ballisticOffset > 0f)
        {
            // 计算弯曲处偏移
            float offset = Mathf.Sin(Mathf.PI * ((originDistance - distanceToAim) / originDistance));
            offset *= originDistance;
            // 向轨迹添加偏移
            return myVirtualPosition + (ballisticOffset * offset * Vector3.up);
        }
        else
        {
            return myVirtualPosition;
        }
    }

    /// <summary>
    /// 朝向目标
    /// </summary>
    /// <param name="direction"></param>
    private void LookAtDirection(Vector3 direction)
    {
        Quaternion netPointQ = Quaternion.FromToRotation(direction, direction-transform.position);
        transform.rotation = Quaternion.Lerp(transform.rotation, netPointQ, 30f);
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持海外IDC网。

【本文由http://www.1234xp.com/xgzq.html首发,转载请保留出处,谢谢】