实现移动可以用transform.Translate、rigidbody.velocity及最简单的改变position。但在人物移动中,往往会遇到一些坡度(slope)或者楼梯,这时候使用unity提供的CharacterController组件会简单快捷。
下面示例实现了一个较简单的人物控制器,功能有移动,跑、跳跃
这边我简单的搭建了一个场景。创建了一个空物体作为角色(FPS Player),将主相机拉到空物体下调整到合适的第一人称视角。同时创建一个圆柱体方便我们观察,最后再创建一个空物体(GroundCheck)拉到我们角色的底部(相当于脚的位置)后面地面检测时需要用到。
给我们的角色(FPS Player),添加上CharacterController组件和PlayerMovement脚本。给摄像机(Main Camera)添加上MouseLock脚本
接下来开始编写代码
PlayerMovement
定义相关的变量
//角色控制器
public CharacterController controller;
//获得GroundCheck的位置
public Transform groundCheck;
//GroundCheck检测半径
public float groundDistance = 0.4f;
//检测的LayerMask层
public LayerMask groundMask;
//移动速度
public float speed = 12f;
//奔跑速度
public float runSpeed = 20f;
//重力
public float gravity = -9.81f;
//跳跃高度
public float jumpHeight = 3f;
//仿重力vector3
private Vector3 velocity;
//是否在地面
private bool isGrounded;
采用Physics.CheckSphere进行地面检测。
这边可以使用OnDrawGizmos()方法可视化检测范围
private void OnDrawGizmos()
{
Gizmos.color = Color.blue;
Gizmos.DrawWireSphere(groundCheck.position, groundDistance);
}
使用CharacterController的Move方法实现移动
由速度随位移的变化规律:2gH=Vt²-V0²,跳跃向上的初速度会等于√-2gH
void Update()
{
//地面检测,如果踩在地面返回true否则返回false
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if (isGrounded && velocity.y < 0)
{
//如果在地面,将向下的重力改为2
velocity.y = -2f;
}
//获得键盘输入
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 move = transform.right * x + transform.forward * z;
//安住左shift跑
if (Input.GetKey(KeyCode.LeftShift))
controller.Move(move * runSpeed * Time.deltaTime);
else
controller.Move(move * speed * Time.deltaTime);
//跳跃
if (Input.GetButtonDown("Jump"))
{
//跳跃高度为jumpHeight的向上初速度
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
//时时刻刻都受到重力影响
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
拉取对应的物体,然后调整参数值,同时记得将能走的地方的Layer层和你选择的GroundMask层设为一致。
MouseLock
//灵敏度
public float mouseSensitivity = 100f;
//角色Transform
public Transform playerBody;
float xRotation = 0f;
// Start is called before the first frame update
void Start()
{
//锁定隐藏鼠标
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
//获得鼠标上下移动的值
xRotation -= mouseY;
//设置鼠标向上向下范围
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
//旋转摄像机(向上向下)
transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
//鼠标左右移动改变人物旋转
playerBody.Rotate(Vector3.up * mouseX);
}
拉取角色组件,调整合适参数