Unity俯视视角角色控制器

Unity Dec 04, 2019

创建Unity俯视视角(Top Down)角色控制器;

包括以下功能:

  • 移动
  • 重力

不包括以下操作:

  • 角色导入
  • 角色动画

我们要是有Unity自带的CharacterController组件,所以一些基础的东西不再详述,可以看官方文档

Step1-使用Unity的CharacterController组件

在角色上添加CharacterController组件
FnPtuSeUykfE1QhkUw46I_lj8fTH

Step2-创建一个脚本并添加到角色上

这里创建一个PlayController.cs基本并添加到角色上

这是基础代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayController : MonoBehaviour
{
    private CharacterController _characterController;    // 角色控制器组件
    
    void Start()
    {
        _characterController = gameObject.GetComponent<CharacterController>();
    }
    
    void FixedUpdate()
    {
        
    }
}

Step3-实现角色的移动

要实现按下键盘上的WASD角色会朝四个不同的方向移动,甚至同时按下WA或WD、SA或SD的时候角色会在西北或东北、西南或东南的方向移动;

FjwzSs20e9qVxUUQd0Am2dJoBhiR

1.在脚本中创建一个float类型的速度变量和两个Vector3类型的变量

public float walkSpeed;
private Vector3 direction = Vector3.zero;
private Vector3 velocity = Vector3.zero;

然后再FixedUpdate方法中添加以下脚本

direction = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
velocity = direction * walkSpeed * Time.fixedDeltaTime;

_characterController.Move(velocity+gravityVector);

然后预览游戏,按下键盘上的WASD键角色就会按四个不同的方向移动。
FtfM1fgdkb98LUDyMGP7iwRJWz-y

Step4-实现角色的朝向

1.上面已经实现了角色的移动,但是有一个问题就是它在向左、向右、向后移动的时候角色的脸一直朝向向前的方向,可以在FixedUpdate方法中添加以下脚本来实现朝向。

float yAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg;
transform.localEulerAngles = new Vector3(0, yAngle, 0);

2.添加上面脚本后确实修复了朝向的问题,但是你会发现当你抬起键盘的时候角色的脸就又朝向前方了,那么还需要对上方的代码就像一下修改;

if (velocity.magnitude > 0)
{
    float yAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg;
    transform.localEulerAngles = new Vector3(0, yAngle, 0);
}

效果如下
FuvICUf8TNF37U34kb5Yiwvy4UzL

Step5-实现重力

CharacterController组件自带了检测角色是否为落地状态的一个方法isGrounded;
FmcXTvLEJLSaxbHkJyLqMg_-9zvq

要实现重力我们还需要一个重力速度的变量,也是float类型

public float gravity;

然后需要修改FixedUpdate方法中的脚本如下:

if (_characterController.isGrounded)
{
    // 如果是落地状态就执行此处代码
    direction = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
    velocity = direction * walkSpeed * Time.fixedDeltaTime;
    gravity = 0;
}
else
{
    // 如果不是落地状态就执行此处代码(跌落)
    gravity += 0.25f;
    gravity = Mathf.Clamp(gravity, 1f, 20f);  // 我们这边将跌落速度进行处理,防止角色一瞬间就掉到地上
}
Vector3 gravityVector = -Vector3.up * gravity * Time.fixedDeltaTime;

// 角色转向
if (velocity.magnitude > 0)
{
    float yAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg;
    transform.localEulerAngles = new Vector3(0, yAngle, 0);
}

_characterController.Move(velocity+gravityVector);

最终代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayController : MonoBehaviour
{
    public float walkSpeed;    // 移动速度
    public float gravity;    // 重力
    private CharacterController _characterController;    // 角色控制器组件
    private Vector3 direction = Vector3.zero;
    private Vector3 velocity = Vector3.zero;
    
    void Start()
    {
        _characterController = gameObject.GetComponent<CharacterController>();
    }
    
    void FixedUpdate()
    {
        if (_characterController.isGrounded)
        {
            direction = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
            velocity = direction * walkSpeed * Time.fixedDeltaTime;
            gravity = 0;
        }
        else
        {
            gravity += 0.25f;
            gravity = Mathf.Clamp(gravity, 1f, 20f);
        }
        Vector3 gravityVector = -Vector3.up * gravity * Time.fixedDeltaTime;
        // 角色转向
        if (velocity.magnitude > 0)
        {
            float yAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg;
            transform.localEulerAngles = new Vector3(0, yAngle, 0);
        }
        _characterController.Move(velocity+gravityVector);
    }
}

相关文档