上一篇文章实现了到指定点的抛物线运动。但是,在水平方向是匀速运动的。但实际炮弹应该是在水平方向是匀加速运动的。因此水平方向的速度不能是距离除以时间。而应该是根据距离公式得出
s=Vi*t+0.5*a*t^2=>Vi=(s-0.5*a*t^2)/t
float dis = Vector3.Distance(targetPos, transform.position);//s=Vi*t+0.5*a*t^2=>Vi=(s-0.5*a*t^2)/tvolocityX = (dis - 0.5f * accelerateX * Mathf.Pow(totalTime, 2)) / totalTime;
而垂直方向的初速度求法和上一篇文章相同。
完整代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;///
/// 已知仰角和总时间,水平方向是匀加速运动,抛物到指定位置的运动
///
public class GTest_03 : MonoBehaviour
{public float angle = 30;public float totalTime = 1.5f;public float accelerateX = 0.2f;float volocityY = 0;float volocityX = 0;float accumulateTime = 0;Vector3 targetPos;bool couldFly = false;Vector3 dir;Vector3 iPos;void Start(){}void Update(){var pos = GetTargetPos();if (pos != Vector3.zero){couldFly = true;accumulateTime = 0;targetPos = pos;GameObject.CreatePrimitive(PrimitiveType.Cube).transform.position = targetPos;iPos = transform.position;dir = (targetPos - transform.position).normalized;transform.LookAt(targetPos);float dis = Vector3.Distance(targetPos, transform.position);//s=Vi*t+0.5*a*t^2=>Vi=(s-0.5*a*t^2)/tvolocityX = (dis - 0.5f * accelerateX * Mathf.Pow(totalTime, 2)) / totalTime;//根据加速度公式 加速度=(末速度-初速度)/时间//地面是平的,垂直方向的初速度=末速度,但方向相反。//a = (Vf-Vi)/t = (-Vi-Vi)/t => Vi=a*t/-2volocityY = 4.9f * totalTime;}if (!couldFly){return;}accumulateTime += Time.deltaTime;if (accumulateTime < totalTime){Vector3 moveX = (volocityX * accumulateTime + accelerateX * 0.5f * Mathf.Pow(accumulateTime, 2)) * dir;Vector3 move = iPos + moveX;float y = volocityY * accumulateTime - 9.8f * 0.5f * Mathf.Pow(accumulateTime, 2);move = move + Vector3.up * y;transform.position = move;}else{couldFly = false;}}Vector3 GetTargetPos(){//鼠标左键if (Input.GetButtonDown("Fire1")){Plane plane = new Plane(new Vector3(0f, 1f, 0f), 0f);var p = GetPointInPlane(Camera.main, Input.mousePosition, plane);return p;}return Vector3.zero;}public static Vector3 GetPointInPlane(Ray ray, Plane plane){float d = ray.origin.y - (plane.normal * plane.distance).y;Vector3 a = ray.direction / ray.direction.y;return ray.origin - a * d;}public static Vector3 GetPointInPlane(Camera cam, Vector3 sPos, Plane plane){var ray = cam.ScreenPointToRay(sPos);//plane.Raycast是有物体的时候, GetPointInPlane是用的平面相交float distance = 0;if (plane.Raycast(ray, out distance)){return ray.GetPoint(distance);}return Vector3.zero;//return GetPointInPlane(ray, plane);}
}