移动 转向 抛物线 附件 BaseProp.cs 道具基类 配合抛物线实现掉落效果
//面向前方移动 需类外配合转向
private void Move()
{
// 方向*输入轴*速度*单位时间=移动距离
Vector3 movement = transform.forward * m_MovementInput * m_Speed * Time.deltaTime;
// 刚体位置+单位时间移动距离 实现位置前进
m_Rigidbody.MovePosition(m_Rigidbody.position + movement);
}
//全向移动 不考虑面向的方向
void Move(float h,float v)
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 movement;
movement.Set(h,0f,v);
//防止斜方向向量大于1,使用normalized使向量归1
movement = movement.normalized * speed * Time.deltaTime;
playerRigidbody.MovePosition(transform.position+movement);
}
//射线检测 实现角色面向鼠标指向
void Turning()
{
Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);
//声明变量 用于从射线投射获取信息的结构
RaycastHit floorHit;
//检测射线是否碰撞,参数1射线位置与方向,参数2包含有碰撞体的信息输出到floorHit,参数3射线长度,参数4用于忽略其他碰撞的遮罩层
if (Physics.Raycast(camRay, out floorHit, camRayLength, floorMask))
{
//计算射线击中的点与角色之间的向量
Vector3 playerToMouse = floorHit.point - transform.position;
//保证y坐标为0,角色不会飘起来
playerToMouse.y = 0f;
//角色注视的位置转为射线击中的点
Quaternion newRotation = Quaternion.LookRotation(playerToMouse);
//角色刚体面向新方向
playerRigidbody.MoveRotation(newRotation);
}
}
//刚体转向
private void Turn()
{
// 输入轴*速度*单位时间 = 转向率
float turn = m_TurnInput * m_TurnSpeed * Time.deltaTime;
// 返回一个Y轴转向度
Quaternion inputRotation = Quaternion.Euler(0f, turn, 0f);
// 刚体方向移动到当前方向*转向度 实现转向
m_Rigidbody.MoveRotation(m_Rigidbody.rotation * inputRotation);
}
//应用旋转 方向*速度*单位时间 世界坐标 或 本地坐标
transform.Rotate(Vector3.left * 10 * Time.deltaTime,Space.World);
//面向一个方向
Vector3 relativePos = target.position - transform.position;
Quaternion rotation = Quaternion.LookRotation(relativePos);
transform.rotation = rotation;
//以轴进行旋转 一定角度 Y轴旋转30°
rotation = Quaternion.Euler(new Vector3(0, 30, 0));
//从一个角度过度到另一角度 timeCount 0-1之间
transform.rotation = Quaternion.Slerp(from.rotation, to.rotation, timeCount);
//直接旋转 例 正方体上面向前转到正前面
transform.rotation = Quaternion.FromToRotation(Vector3.up, transform.forward);
using UnityEngine;
/// <summary>
/// 抛物线运动轨迹
/// ZhangYu 2019-04-28
/// <param>blog:https://segmentfault.com/a/1190000018336439</param>
/// </summary>
public class ParabolaPath {
/// <summary> 是否夹紧起点和终点 </summary>
public bool isClampStartEnd;
private Vector3 m_start;
private Vector3 m_end;
private float m_height;
private float m_gravity;
private float m_upTime;
private float m_downTime;
private float m_totalTime;
private Vector3 m_velocityStart;
private Vector3 m_position;
private float m_time;
/// <summary> 初始化抛物线运动轨迹 </summary>
/// <param name="start">起点</param>
/// <param name="end">终点</param>
/// <param name="height">高度(相对于两个点的最高位置 高出多少)</param>
/// <param name="gravity">重力加速度(负数)</param>
/// <returns></returns>
public ParabolaPath(Vector3 start, Vector3 end, float height = 10, float gravity = -9.8f) {
Init(start, end, height, gravity);
}
/// <summary> 初始化抛物线运动轨迹 </summary>
/// <param name="start">起点</param>
/// <param name="end">终点</param>
/// <param name="height">高度(相对于两个点的最高位置 高出多少)</param>
/// <param name="gravity">重力加速度(负数)</param>
/// <returns></returns>
public void Init(Vector3 start, Vector3 end, float height = 10, float gravity = -9.8f) {
float topY = Mathf.Max(start.y, end.y) + height;
float d1 = topY - start.y;
float d2 = topY - end.y;
float g2 = 2 / -gravity;
float t1 = Mathf.Sqrt(g2 * d1);
float t2 = Mathf.Sqrt(g2 * d2);
float t = t1 + t2;
float vX = (end.x - start.x) / t;
float vZ = (end.z - start.z) / t;
float vY = -gravity * t1;
m_start = start;
m_end = end;
m_height = height;
m_gravity = gravity;
m_upTime = t1;
m_downTime = t2;
m_totalTime = t;
m_velocityStart = new Vector3(vX, vY, vZ);
m_position = m_start;
m_time = 0;
}
/// <summary> 起点 </summary>
public Vector3 start { get { return m_start; } }
/// <summary> 终点 </summary>
public Vector3 end { get { return m_end; } }
/// <summary> 目标高度 </summary>
public float height { get { return m_height; } }
/// <summary> 重力加速度 </summary>
public float gravity { get { return m_gravity; } }
/// <summary> 上升时间 </summary>
public float upTime { get { return m_upTime; } }
/// <summary> 下降时间 </summary>
public float downTime { get { return m_downTime; } }
/// <summary> 总运动时间 </summary>
public float totalTime { get { return m_totalTime; } }
/// <summary> 顶点 </summary>
public Vector3 top { get { return GetPosition(m_upTime); } }
/// <summary> 初始速度 </summary>
public Vector3 velocityStart { get { return m_velocityStart; } }
/// <summary> 当前位置 </summary>
public Vector3 position { get { return m_position; } }
/// <summary> 当前速度 </summary>
public Vector3 velocity { get { return GetVelocity(m_time); } }
/// <summary> 当前时间 </summary>
public float time {
get { return m_time; }
set {
if (isClampStartEnd) value = Mathf.Clamp(value, 0, m_totalTime);
m_time = value;
m_position = GetPosition(value);
}
}
/// <summary> 获取某个时间点的位置 </summary>
public Vector3 GetPosition(float time) {
if (time == 0) return m_start;
if (time == m_totalTime) return m_end;
float dY = 0.5f * m_gravity * time * time;
return m_start + m_velocityStart * time + new Vector3(0, dY, 0);
}
/// <summary> 获取某个时间点的速度 </summary>
public Vector3 GetVelocity(float time) {
if (time == 0) return m_velocityStart;
return m_velocityStart + new Vector3(0, m_velocityStart.y + m_gravity * time, 0);
}
}
using UnityEngine;
/// <summary>
/// 抛物线导弹
/// <para>计算弹道和转向</para>
/// <para>ZhangYu 2019-02-27</para>
/// </summary>
public class Missile : MonoBehaviour {
public Transform target; // 目标
public float height = 16f; // 高度
public float gravity = -9.8f; // 重力加速度
private ParabolaPath path; // 抛物线运动轨迹
private void Start() {
path = new ParabolaPath(transform.position, target.position, height, gravity);
path.isClampStartEnd = true;
transform.LookAt(path.GetPosition(path.time + Time.deltaTime));
}
private void Update() {
// 计算位移
float t = Time.deltaTime;
path.time += t;
transform.position = path.position;
// 计算转向
transform.LookAt(path.GetPosition(path.time + t));
// 简单模拟一下碰撞检测
if (path.time >= path.totalTime) enabled = false;
}