Unity使用DoTween實現(xiàn)拋物線效果
更新時間:2021年05月27日 09:00:35 作者:輕風(fēng)點語
這篇文章主要為大家詳細(xì)介紹了Unity使用DoTween實現(xiàn)拋物線效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
Unity使用DoTween實現(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實現(xiàn)炮彈運動軌跡(拋物線)
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ā)射點
/// </summary>
private Vector3 originPoint;
private Vector3 aimPoint;
/// <summary>
/// 無彈道偏移的當(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>
/// 加速度計算計數(shù)器
/// </summary>
private float counter;
/// <summary>
/// 剛剛啟動時的速度
/// </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;
}
//計算從發(fā)射點到目標(biāo)的距離
Vector3 originDistance = aimPoint - originPoint;
//計算剩余距離
Vector3 distanceToAim = aimPoint - myVirtualPosition; //發(fā)射點和目標(biāo)之間的矢量距離
//移動到目標(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)
{
// 計算彎曲處偏移
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);
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
DevExpress實現(xiàn)自定義TreeListNode的Tooltip的方法
這篇文章主要介紹了DevExpress實現(xiàn)自定義TreeListNode的Tooltip的方法,需要的朋友可以參考下2014-08-08
winfrom 打印表格 字符串的封裝實現(xiàn)代碼 附源碼下載
以前寫打印都是根據(jù)打印機(jī)的型號,找開發(fā)類庫。然后在此基礎(chǔ)上開發(fā)。寫的多了自然就想到了封裝。這是還是想到了微軟,微軟封裝了PrintDocument的打印類。但這只是在低層對串口的封裝2013-02-02
Winform利用分頁控件實現(xiàn)導(dǎo)出PDF文檔功能
當(dāng)前的Winform分頁控件中,當(dāng)前導(dǎo)出的數(shù)據(jù)一般使用Excel來處理,但是有框架的使用客戶希望分頁控件能夠直接導(dǎo)出PDF,所以本文整理了一下分頁控件導(dǎo)出PDF的處理過程,分享一下2023-03-03
C# 16進(jìn)制與字符串、字節(jié)數(shù)組之間的轉(zhuǎn)換
在串口通訊過程中,經(jīng)常要用到 16進(jìn)制與字符串、字節(jié)數(shù)組之間的轉(zhuǎn)換2009-05-05

