Unity使用DoTween實(shí)現(xiàn)拋物線效果
Unity使用DoTween實(shí)現(xiàn)拋物線效果,供大家參考,具體內(nèi)容如下
概要
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實(shí)現(xiàn)炮彈運(yùn)動(dòng)軌跡(拋物線)
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Parabol : MonoBehaviour { private Rigidbody rgb; /// <summary> /// 目標(biāo) /// </summary> public GameObject target; /// <summary> /// 子彈的發(fā)射點(diǎn) /// </summary> private Vector3 originPoint; private Vector3 aimPoint; /// <summary> /// 無(wú)彈道偏移的當(dāng)前位置 /// </summary> private Vector3 myVirtualPosition; /// <summary> /// 定位最后一幀 /// </summary> private Vector3 myPreviousPosition; /// <summary> /// 是否可以發(fā)射 /// </summary> private bool sw = false; private bool actived = false; /// <summary> /// 最大發(fā)射距離 /// </summary> public float maxLaunch = 1f; /// <summary> /// 加速度計(jì)算計(jì)數(shù)器 /// </summary> private float counter; /// <summary> /// 剛剛啟動(dòng)時(shí)的速度 /// </summary> public float speed = 0.5f; /// <summary> /// 恒定加速度 /// </summary> public float speedUpOverTime = 0.1f; /// <summary> /// 彈道偏移量(與目標(biāo)的距離) /// </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; //目標(biāo)之間的值 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; } //計(jì)算從發(fā)射點(diǎn)到目標(biāo)的距離 Vector3 originDistance = aimPoint - originPoint; //計(jì)算剩余距離 Vector3 distanceToAim = aimPoint - myVirtualPosition; //發(fā)射點(diǎn)和目標(biāo)之間的矢量距離 //移動(dòng)到目標(biāo) 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); //將子彈旋轉(zhuǎn)至彈道 //Debug.Log("最后一幀的位置:" + myPreviousPosition); LookAtDirection(transform.position - myPreviousPosition); myPreviousPosition = transform.position; } private Vector3 AddBallisticOffset(float originDistance, float distanceToAim) { if (ballisticOffset > 0f) { // 計(jì)算彎曲處偏移 float offset = Mathf.Sin(Mathf.PI * ((originDistance - distanceToAim) / originDistance)); offset *= originDistance; // 向軌跡添加偏移 return myVirtualPosition + (ballisticOffset * offset * Vector3.up); } else { return myVirtualPosition; } } /// <summary> /// 朝向目標(biāo) /// </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); } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#中利用斷點(diǎn)操作調(diào)試程序的步驟詳解
所謂斷點(diǎn)調(diào)試就是檢測(cè)執(zhí)行路徑和數(shù)據(jù)是否正確,中斷游戲運(yùn)行在線調(diào)試,下面這篇文章主要給大家介紹了關(guān)于C#中利用斷點(diǎn)操作調(diào)試程序的相關(guān)資料,需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12C# 無(wú)邊框窗體邊框陰影效果的簡(jiǎn)單實(shí)現(xiàn)
這篇文章介紹了C# 無(wú)邊框窗體邊框陰影效果的簡(jiǎn)單實(shí)現(xiàn),有需要的朋友可以參考一下2013-10-10Unity Shader實(shí)現(xiàn)徑向模糊效果
這篇文章主要為大家詳細(xì)介紹了Unity Shader實(shí)現(xiàn)徑向模糊效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08DevExpress實(shí)現(xiàn)自定義TreeListNode的Tooltip的方法
這篇文章主要介紹了DevExpress實(shí)現(xiàn)自定義TreeListNode的Tooltip的方法,需要的朋友可以參考下2014-08-08winfrom 打印表格 字符串的封裝實(shí)現(xiàn)代碼 附源碼下載
以前寫(xiě)打印都是根據(jù)打印機(jī)的型號(hào),找開(kāi)發(fā)類庫(kù)。然后在此基礎(chǔ)上開(kāi)發(fā)。寫(xiě)的多了自然就想到了封裝。這是還是想到了微軟,微軟封裝了PrintDocument的打印類。但這只是在低層對(duì)串口的封裝2013-02-02Winform利用分頁(yè)控件實(shí)現(xiàn)導(dǎo)出PDF文檔功能
當(dāng)前的Winform分頁(yè)控件中,當(dāng)前導(dǎo)出的數(shù)據(jù)一般使用Excel來(lái)處理,但是有框架的使用客戶希望分頁(yè)控件能夠直接導(dǎo)出PDF,所以本文整理了一下分頁(yè)控件導(dǎo)出PDF的處理過(guò)程,分享一下2023-03-03C# 16進(jìn)制與字符串、字節(jié)數(shù)組之間的轉(zhuǎn)換
在串口通訊過(guò)程中,經(jīng)常要用到 16進(jìn)制與字符串、字節(jié)數(shù)組之間的轉(zhuǎn)換2009-05-05Unity Shader實(shí)現(xiàn)序列幀動(dòng)畫(huà)效果
這篇文章主要為大家詳細(xì)介紹了Unity Shader實(shí)現(xiàn)序列幀動(dòng)畫(huà)效果 ,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02