第三人称的角色移动控制方案有很多种:
- 前提:相机Camera已经为角色Player的子物体【自行调节第三人称角度】
1. rigidbody.velocity() : 通过控制刚体的速度 来实现对角色的移动控制
public GameObject thirdPersonPlayer; //角色
public float MoveSpeed = 10.0f; //移动速度
public float RotateSpeed = 10.0f; //旋转速度
private Rigidbody PlayerRigidbody; //角色的刚体组件
void Start()
{
PlayerRigidbody = thirdPersonPlayer.GetComponent<Rigidbody>();
}
void FixedUpdate()
{
if (Input.GetKeyDown(KeyCode.Space))//跳跃
{
PlayerRigidbody.velocity = new Vector3(0, 5, 0);
}
//获取WSAD键
float h = Input.GetAxis("Horizontal"); //左右
float v = Input.GetAxis("Vertical"); //前后
Vector3 GlobalPos = thirdPersonPlayer.transform.position;//物体所处的世界坐标
//方案1:
//通过transform.TransformPoint()求出相对与物体前方距离为-1-的世界坐标
//通过两坐标向量相减得到 物体需要移动的方向
//Vector3 GlobalPosForward = thirdPersonPlayer.transform.TransformPoint(Vector3.forward);
//Vector3 ForwardDirection = v * (GlobalPosForward - GlobalPos);//物体前后移动的方向
//求出物体右方距离为-1-的世界坐标
//Vector3 GlobalPosRight = thirdPersonPlayer.transform.TransformPoint(Vector3.right);
//Vector3 RightDirection = h * (GlobalPosRight - GlobalPos);//物体左右移动的方向
//方案2:
//通过transform.TransformDirection()求出相对与物体前方方向的世界方向
Vector3 GlobalDirectionForward = thirdPersonPlayer.transform.TransformDirection(Vector3.forward);
Vector3 ForwardDirection = v * GlobalDirectionForward;//物体前后移动的方向
//求出相对于物体右方方向的世界方向
Vector3 GlobalDirectionRight = thirdPersonPlayer.transform.TransformDirection(Vector3.right);
Vector3 RightDirection = h * GlobalDirectionRight;//物体左右移动的方向
//再将前后左右需要移动的方向都加起来 得出 最终要移动的方向
Vector3 MainDirection = ForwardDirection + RightDirection;
//通过给刚体的 指定的方向 施加速度,得以控制角色运动
PlayerRigidbody.velocity = new Vector3(
MoveSpeed * MainDirection.x,
PlayerRigidbody.velocity.y,
MoveSpeed * MainDirection.z
);
//另外,一般第三人称角色控制的游戏,可通过鼠标左右移动控制旋转
float x = RotateSpeed * Input.GetAxis("Mouse X");
thirdPersonPlayer.transform.rotation = Quaternion.Euler(
thirdPersonPlayer.transform.rotation.eulerAngles +
Quaternion.AngleAxis(x, Vector3.up).eulerAngles
);
}
- 小提示: 对于角色控制,也可以通过控制Player的刚体组件的 Drag/AngularDrag【阻力】 来限制角色的移动
可能有人会问,用一次rigidbody.velocity()这么麻烦!!
确实,使用这个接口所改变的速度的方向始终是世界坐标的方向,真是麻烦~~~
2. rigidbody.MovePosition() : 通过调整刚体的Position 来实现对角色的移动控制
- 提示 1: 不直接修改刚体的position而是通过调用公共函数MovePosition() : 使运动更加平滑(使用内插值)
- 提示 2: 不使用transform.position而是使用刚体的position : 前者会导致物体的Colliders重新计算相对于刚体的位置,会更加耗费性能
public GameObject thirdPersonPlayer; //角色
public float MoveSpeed = 10.0f; //移动速度
public float RotateSpeed = 10.0f; //旋转速度
private Rigidbody PlayerRigidbody; //角色的刚体组件
void Start()
{
PlayerRigidbody = thirdPersonPlayer.GetComponent<Rigidbody>();
}
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal"); //左右
float v = Input.GetAxis("Vertical"); //前后
Vector3 GlobalDirectionForward = thirdPersonPlayer.transform.TransformDirection(Vector3.forward);
Vector3 ForwardDirection = v * GlobalDirectionForward * Time.fixedDeltaTime;//物体前后移动的方向
Vector3 GlobalDirectionRight = thirdPersonPlayer.transform.TransformDirection(Vector3.right);
Vector3 RightDirection = h * GlobalDirectionRight * Time.fixedDeltaTime;//物体左右移动的方向
Vector3 MainDirection = ForwardDirection + RightDirection;
PlayerRigidbody.MovePosition(PlayerRigidbody.position + MainDirection * MoveSpeed);
}
3. rigidbody.AddForce() / AddRelativeForce(): 通过给刚体的施加力,来实现对角色的移动控制,模拟惯性(例如:开车)
public GameObject thirdPersonPlayer; //角色
private Rigidbody PlayerRigidbody; //角色的刚体组件
public float MoveForce = 10.0f; //施加的力的大小
void Start()
{
PlayerRigidbody = thirdPersonPlayer.GetComponent<Rigidbody>();
}
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal"); //左右
float v = Input.GetAxis("Vertical"); //前后
//方案1 :
Vector3 GlobalDirectionForward = thirdPersonPlayer.transform.TransformDirection(Vector3.forward);
Vector3 ForwardDirection = v * GlobalDirectionForward;//物体前后移动的方向
Vector3 GlobalDirectionRight = thirdPersonPlayer.transform.TransformDirection(Vector3.right);
Vector3 RightDirection = h * GlobalDirectionRight;//物体左右移动的方向
Vector3 MainDirection = ForwardDirection + RightDirection;
PlayerRigidbody.AddForce(MainDirection * MoveForce , ForceMode.Force);
//方案2 :
PlayerRigidbody.AddRelativeForce((h * Vector3.right + v * Vector3.forward) * MoveForce,ForceMode.Force);
}