Unity使用DoTween实现抛物线效果
短信预约 -IT技能 免费直播动态提醒
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);
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341