Unity Character Controller移动控制(第一人称)
Character Controller组件
官方文档:https://docs.unity.cn/cn/2019.4/Manual/class-CharacterController.html
1. 移动
直接上代码:
public class PlayerController : MonoBehaviour
{
//获取组件
public CharacterController characterController;
//设置移动和跳跃速度
public float moveSpeed;
//定义按键输入
public float getHorizontal, getVertical;
//定义移动向量
private Vector3 dir;
private void Start()
{
moveSpeed = 4;
characterController = GetComponent<CharacterController>();
}
private void Update()
{
getHorizontal = Input.GetAxis("Horizontal") * moveSpeed;
getVertical = Input.GetAxis("Vertical") * moveSpeed;
dir = transform.forward * getVertical + transform.right * getHorizontal;
characterController.Move(dir * Time.deltaTime);
}
}
2. 重力和跳跃
2.1 重力
- 定义重力、向下的速度(通过计算得出)
- 判断物体是否在地面上,不在时开始计算向下的速度
- 通过physics.CheckSphere方法判断物体是否在地面上
- 需要定义目标点transform、检测半径float、检测图层LayerMask来进行判断
代码:
public class PlayerController : MonoBehaviour
{
//定义重力和下落加速度
public float gravity = 9.8f;
private Vector3 velocity = Vector3.zero;
//定义bool值判断角色是否在地面上
public bool isGround;
//定义一个目标点,一个检测半径,一个检测图层
public Transform checkGround;
public float checkRedius;
public LayerMask checkLayer;
private void Start()
{
checkRedius = 0.2f;
}
private void Update()
{
isGround = Physics.CheckSphere(checkGround.position, checkRedius, checkLayer);
if (isGround && isJumping < 0.1)
{
velocity.y = 0;
}
velocity.y -= gravity * Time.deltaTime;
characterController.Move(velocity * Time.deltaTime);
}
}
2.2 跳跃
在这里遇到一个困难,如果直接用以下代码的话:
if (Input.GetButtonDown("Jump") && isGround)
{
velocity.y = jumpSpeed;
}
理论上可行,但是通过实践发现根本跳不起来,猜测和在上一步添加重力时的这一段代码有关:
if (isGround && isJumping < 0.1)
{
velocity.y = 0;
}
在起跳的时候程序又执行到这一部分,导致角色的velocity.y=0,从而使角色不能跳跃
暂时想到的解决办法就是添加一个计时器,让在起跳0.1秒内不再执行判断isGround的代码
通过修改后,PlayerController代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
//获取组件
public CharacterController characterController;
//设置移动速度
public float moveSpeed;
//定义按键输入
public float getHorizontal, getVertical;
//定义移动向量
private Vector3 dir;
//定义跳跃速度和跳跃状态
public float jumpSpeed;
public float isJumping;
//定义重力和下落加速度
public float gravity = 9.8f;
private Vector3 velocity = Vector3.zero;
//定义bool值判断角色是否在地面上
public bool isGround;
//定义一个目标点,一个检测半径,一个检测图层
public Transform checkGround;
public float checkRedius;
public LayerMask checkLayer;
private void Start()
{
moveSpeed = 4;
jumpSpeed = 5;
checkRedius = 0.2f;
characterController = GetComponent<CharacterController>();
isJumping = 0.2f;
}
private void Update()
{
isGround = Physics.CheckSphere(checkGround.position, checkRedius, checkLayer);
if (isGround && isJumping < 0.1)
{
velocity.y = 0;
}
getHorizontal = Input.GetAxis("Horizontal") * moveSpeed;
getVertical = Input.GetAxis("Vertical") * moveSpeed;
dir = transform.forward * getVertical + transform.right * getHorizontal;
characterController.Move(dir * Time.deltaTime);
if (Input.GetButtonDown("Jump") && isGround)
{
velocity.y = jumpSpeed;
isJumping = 0.2f;
}
if(isJumping > 0)
{
isJumping -= Time.deltaTime;
}
velocity.y -= gravity * Time.deltaTime;
characterController.Move(velocity * Time.deltaTime);
}
}
** 如果有关于玩家跳跃的更好解决办法,欢迎发表在评论区 **
实现第一人称视角控制
前面完成了前后左右移动和跳跃,这一步完成一个第一视角的转动功能
将Camera拖到Player的节点下,调整位置,然后为Camera添加脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
public Transform Player;
private float mouseX, mouseY; //获取鼠标移动的值
public float mouseSensitivity; //鼠标灵敏度
private float xRotation;
private void Start()
{
mouseX = 0;
mouseY = 0;
mouseSensitivity = 800;
}
private void Update()
{
mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
xRotation -= mouseY;
if (xRotation > 90)
{
xRotation = 90;
}
else if (xRotation < -90)
{
xRotation = -90;
}
Player.Rotate(Vector3.up * mouseX);
transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
}
}
完成!