思路
给定:起点、终点、“速度”、“高度”。
做法
- 根据“速度”算得运动总时长:运动总时长 = 起点到终点的距离 / 速度
- 让物体在运动总时长内,坐标从起点变到终点(Lerp的方式)
- 在上述过程中,要修改物体的PosY(加一个Offset):Offset = 高度 * y
根据指定函数算得:该函数的自变量取值范围为0~1,在0和1时因变量值(y,高度系数值)为0。如:y = 1 - 4 *(x-0.5)^2
也可以直接使用AnimationCurve画出期望的y在该过程中变化的曲线,同样要求在0和1时因变量值为0。
实现
效果
模拟抛物运动.gif
配置
image.png
示意代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 物体沿弧线移动测试
public class Fan_ThrowTest : MonoBehaviour
{
[SerializeField]
private GameObject _go;
[SerializeField]
private Transform _beginPosTrans;
private Vector3 BeginPos{ get { return _beginPosTrans.position; } }
[SerializeField]
private Transform _endPosTrans;
private Vector3 EndPos{ get { return _endPosTrans.position; } }
[SerializeField]
private float _moveSpeed;
[SerializeField]
private AnimationCurve _posYCurve;
[SerializeField]
private float _height;
private IEnumerator _moveCoroutine;
private void Start()
{
Init();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Move();
}
}
private void OnDestroy()
{
Destroy();
}
public void Init()
{
}
public void Destroy()
{
}
private void Move()
{
if (_moveCoroutine != null)
{
StopCoroutine(_moveCoroutine);
_moveCoroutine = null;
}
_moveCoroutine = MoveCoroutine();
StartCoroutine(_moveCoroutine);
}
private IEnumerator MoveCoroutine()
{
float distance = Vector3.Distance(BeginPos, EndPos);
float duration = distance / _moveSpeed;
float timer = 0f;
// 若是rigidbody,可以使用rigidbody.MovePostion(_beginPos),下同
_go.transform.position = BeginPos;
while (timer < duration)
{
float x = timer / duration;
Vector3 nextPos = Vector3.Lerp(BeginPos, EndPos, timer / duration);
// float y = 1 - 4 * (x - 0.5f) * (x - 0.5f);
float y = _posYCurve.Evaluate(x);
nextPos.y += y * _height;
_go.transform.LookAt(nextPos, transform.forward);
_go.transform.position = nextPos;
timer += Time.deltaTime;
yield return null;
}
_go.transform.position = EndPos;
}
}
网友评论