工具类
public class ShootTool
{
private Transform start, target, control;
private float speed, height;
private Vector3 moveDir = Vector3.zero;
private Vector3[] moveNode;
private int moveIndex = 5;
private int segmentNumber = 30;
private LineRenderer lineRenderer = null;
private bool onShoot = false;
private Vector3 originalPos = Vector3.zero;
private Vector3 originalRot = Vector3.zero;
public void InitData(Transform startTemp, Transform controlTemp, Transform targetTemp, float speedTemp, float heightTemp, LineRenderer line = null)
{
start = startTemp;
control = controlTemp;
target = targetTemp;
speed = speedTemp;
height = heightTemp;
lineRenderer = line;
originalPos = start.transform.position;
originalRot = start.transform.eulerAngles;
}
public void OnBegin()
{
if (onShoot) return;
moveNode = GetBeizerList(start.position, control.position, target.position, segmentNumber);
onShoot = true;
}
public void OnUpdate()
{
DrawCurve();
if (onShoot)
{
if (moveIndex >= moveNode.Length)
{
OnFlyFinish();
return;
}
moveDir = (moveNode[moveIndex] - start.transform.position).normalized;
start.LookAt(moveNode[moveIndex]);
start.transform.position += moveDir * Time.deltaTime * speed;
if (Vector3.Distance(start.transform.position, moveNode[moveIndex]) <= 0.5f) moveIndex += 1;
}
}
private void OnFlyFinish()
{
onShoot = false;
moveIndex = 5;
start.gameObject.SetActive(false);
start.transform.position = originalPos;
start.transform.eulerAngles = originalRot;
start.gameObject.SetActive(true);
}
private void DrawCurve()
{
if (lineRenderer == null) return;
for (int i = 1; i <= segmentNumber; i++)
{
float value = i / (float)segmentNumber;
Vector3 pixel = CalculateCubicBezierPoint(value, originalPos, control.position, target.position);
lineRenderer.positionCount = i;
lineRenderer.SetPosition(i - 1, pixel);
}
}
private Vector3 CalculateCubicBezierPoint(float value, Vector3 startPoint, Vector3 controlPoint, Vector3 endPoint)
{
float tempValue01 = 1 - value;
float tempValue02 = value * value;
float tempValue03 = tempValue01 * tempValue01;
Vector3 newPos = tempValue03 * startPoint;
newPos += 2 * tempValue01 * value * controlPoint;
newPos += tempValue02 * endPoint;
return newPos;
}
public Vector3[] GetBeizerList(Vector3 startPoint, Vector3 controlPoint, Vector3 endPoint, int segmentNumber)
{
Vector3[] path = new Vector3[segmentNumber];
for (int i = 1; i <= segmentNumber; i++)
{
float value = i / (float)segmentNumber;
Vector3 pixel = CalculateCubicBezierPoint(value, startPoint, controlPoint, endPoint);
path[i - 1] = pixel;
}
return path;
}
}
调用类
public class ShootToolExample : MonoBehaviour
{
[SerializeField] Transform start, target, control;
[SerializeField] float height = 40;
[SerializeField] float speed = 30;
[SerializeField] LineRenderer lineRenderer;
private ShootTool shootTool = new ShootTool();
private void Awake()
{
shootTool = new ShootTool();
shootTool.InitData(start, control, target, speed, height, lineRenderer);
}
private void Update()
{
if (Input.GetMouseButton(0)) { shootTool.OnBegin(); }
shootTool.OnUpdate();
}
}