Unity使用DoTween实现抛物线效果

 更新时间:2021年05月27日 09:00:35   作者:轻风点语  
这篇文章主要为大家详细介绍了Unity使用DoTween实现抛物线效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

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

相关文章

  • C#中隐式运行CMD命令行窗口的方法

    C#中隐式运行CMD命令行窗口的方法

    下面介绍一种常用的在C#程序中调用CMD.exe程序,并且不显示命令行窗口界面,来完成CMD中各种功能的简单方法。
    2011-04-04
  • C# 利用VS编写一个简单的网游客户端

    C# 利用VS编写一个简单的网游客户端

    本文主要介绍了在visual studio中利用C#编写一个简单的网游客户端,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • C# Socket的TCP通讯的实例代码

    C# Socket的TCP通讯的实例代码

    本篇文章主要介绍了C# Socket的TCP通讯,socket通讯方式有两种:同步和异步,详细的介绍了这两种方法,有兴趣的可以了解一下。
    2016-12-12
  • C#对称加密(AES加密)每次生成的结果都不同的实现思路和代码实例

    C#对称加密(AES加密)每次生成的结果都不同的实现思路和代码实例

    这篇文章主要介绍了C#对称加密(AES加密)每次生成的结果都不同的实现思路和代码实例,每次解密时从密文中截取前16位,这就是实现随机的奥秘,本文同时给出了实现代码,需要的朋友可以参考下
    2015-07-07
  • 探秘C# 6.0 的新特性

    探秘C# 6.0 的新特性

    本文的内容包括引入C#6.0中的新的语言特性有哪些. 还有已经被引入的代码名称为 “Roslyn”新编译器. 编译器是开放源码的,并且可以从 codeplex 网站的这个地址下载到源代码:https://roslyn.codeplex.com/.
    2015-03-03
  • C#确保只有一个实例在运行的方法

    C#确保只有一个实例在运行的方法

    这篇文章主要介绍了C#确保只有一个实例在运行的方法,涉及C#进程操作的相关技巧,需要的朋友可以参考下
    2015-05-05
  • 使用C#实现读取PDF中所有文本内容

    使用C#实现读取PDF中所有文本内容

    这篇文章主要为大家详细介绍了如何使用C#实现读取PDF中所有文本内容,文中的示例代码简洁易懂,具有一定的学习价值,有需要的小伙伴可以了解下
    2024-02-02
  • C#实现批量Word转换Html的示例代码

    C#实现批量Word转换Html的示例代码

    这篇文章主要为大家详细介绍了如何利用C#批量Word转换Html的功能,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • C#实现修改系统时间的方法

    C#实现修改系统时间的方法

    这篇文章主要介绍了C#实现修改系统时间的方法,是一个非常实用的功能,需要的朋友可以参考下
    2014-07-07
  • C#嵌套类的访问方法

    C#嵌套类的访问方法

    这篇文章主要介绍了C#嵌套类的访问方法,本文给出了嵌套类代码和访问方法代码,不会的同学照搬对照中的方法即可,需要的朋友可以参考下
    2015-04-04

最新评论