unity控制人物移动及相机跟随
·
一、在Mixamo网站下载人物模型和动画

选择人物模型进行下载,然后选择人物动画,在右侧可以预览效果,还能调整动画一些细节


二、将下载的人物模型和动画导入unity中,先将人物模型的动画类型设置为:Humanoid


将人物动画的Animation Type也调整为Humanoid

如果不想让动画控制人物位置变化,只通过代码控制人物位置,可以进行下图设置

三、创建空物体Player,将人物模型拖到Player下方,模型与空物体位置相同。在Player下添加组件Animator,在Project中新建一个Animator Controller,将Animator Controller拖入组件Animator,将模型的Avatar也拖入组件Animator。
![]()

进行动画切换



在Player上添加角色控制器Character Controller组件,调节Character Controller参数使其与模型大小匹配,Skin Width建议为Radius的10%,center.z建议偏人物前方一点,因为人物向前移动。

四、在Main Camera下新建脚本CameraController控制摄像机的移动,在Player新建脚本PlayerController,控制人物的移动与动画切换
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// CameraController 控制相机跟随指定目标,并根据鼠标输入调整相机角度和位置。
/// </summary>
public class CameraController : MonoBehaviour
{
// 目标变换对象,相机将跟随此对象移动和旋转
[SerializeField] private Transform followTarget;
// 相机与目标之间的距离
[SerializeField] private float distance = 5f;
// 旋转速度
[SerializeField] private float rotationSpeed = 1f;
// 垂直旋转角度的最小值和最大值
[SerializeField] private float minVerticalAngle = -20f;
[SerializeField] private float maxVerticalAngle = 80f;
// 是否反转水平和垂直旋转方向
[SerializeField] private bool invertX;
[SerializeField] private bool invertY;
// 框架偏移,用于调整相机相对于目标的位置
[SerializeField] Vector2 framingOffset;
// 水平和垂直旋转角度
private float rotationY;
private float rotationX;
// 根据是否反转,计算反转值
private float invertXVal;
private float invertYVal;
/// <summary>
/// Start 初始化相机控制器,隐藏光标并锁定。
/// </summary>
private void Start()
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
/// <summary>
/// Update 每帧更新相机位置和旋转,根据鼠标输入和目标位置。
/// </summary>
private void Update()
{
// 根据是否反转,计算反转值
invertXVal = invertX ? -1 : 1;
invertYVal = invertY ? -1 : 1;
// 计算垂直旋转角度,并限制在最小和最大值之间
rotationX += Input.GetAxis("Mouse Y") * rotationSpeed * invertYVal;
rotationX = Mathf.Clamp(rotationX, minVerticalAngle, maxVerticalAngle);
// 计算水平旋转角度
rotationY += Input.GetAxis("Mouse X") * rotationSpeed * invertXVal;
// 计算目标旋转
var targetRotation = Quaternion.Euler(rotationX, rotationY, 0);
// 计算焦点位置,根据框架偏移调整
var focusPosition = followTarget.position + new Vector3(framingOffset.x, framingOffset.y, 0);
// 计算相机位置,保持与目标的距离
transform.position = focusPosition - targetRotation * new Vector3(0, 0, distance);
// 应用目标旋转到相机
transform.rotation = targetRotation;
}
/// <summary>
/// PlanarRotation 获取水平旋转的四元数,忽略垂直旋转。
/// </summary>
/// <returns>水平旋转的四元数</returns>
public Quaternion PlanarRotation => Quaternion.Euler(0, rotationY, 0);
}
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
// 玩家控制器类,用于控制玩家角色的移动和动画
public class PlayerController : MonoBehaviour
{
// 移动速度变量,通过Inspector界面设置
[SerializeField] private float moveSpeed = 10f;
// 旋转速度变量,通过Inspector界面设置
[SerializeField] private float rotationSpeed = 500f;
// 地面检测设置的Header,用于Inspector界面的组织
[Header("Ground Check Settings")]
// 地面检测半径,通过Inspector界面设置
[SerializeField] private float groundCheckRadius = 0.2f;
// 地面检测偏移量,通过Inspector界面设置
[SerializeField] private Vector3 groundCheckOffset;
// 地面检测层,通过Inspector界面设置
[SerializeField] private LayerMask groundLayer;
// 是否处于地面状态
private bool isGrounded;
// Y轴速度
private float ySpeed;
// 玩家动画控制器
private Animator playerAnimator;
// 目标旋转
Quaternion targetRotation;
// 相机控制器
private CameraController cameraController;
// 角色控制器
private CharacterController characterController;
// 初始化方法,用于设置相机控制器、玩家动画控制器和角色控制器的引用
void Start()
{
cameraController = Camera.main.GetComponent<CameraController>();
playerAnimator = GetComponent<Animator>();
characterController = GetComponent<CharacterController>();
}
// 每帧调用的更新方法,用于处理玩家的移动、旋转和动画
void Update()
{
// 获取水平和垂直输入轴的值
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
// 计算移动量,并进行0到1之间的限制
float moveAmount = Mathf.Clamp01(Mathf.Abs(h) + Mathf.Abs(v));
// 创建一个标准化的移动输入向量,以确保在对角线移动时速度不会增加
var moveInput = (new Vector3(h, 0, v)).normalized;
// 使用相机控制器的平面旋转来调整移动方向,以适应玩家的视角
var moveDir = cameraController.PlanarRotation * moveInput;
// 进行地面检测
GroundCheck();
// 根据是否处于地面状态来调整Y轴速度
if (isGrounded)
{
ySpeed = -0.5f;
}
else
{
ySpeed += Physics.gravity.y * Time.deltaTime;
}
// 计算最终的移动速度,并设置Y轴速度
var velocity = moveDir * moveSpeed;
velocity.y = ySpeed;
// 使用角色控制器进行移动
characterController.Move(velocity * Time.deltaTime);
// 如果有移动输入,则更新玩家的旋转
if (moveAmount > 0)
{
transform.rotation = Quaternion.LookRotation(moveDir);
}
// 逐步向目标旋转靠近
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
// 更新玩家动画控制器的移动量参数
playerAnimator.SetFloat("moveAmount", moveAmount, 0.2f, Time.deltaTime);
}
// 地面检测方法,用于检查玩家是否处于地面
private void GroundCheck()
{
isGrounded = Physics.CheckSphere(transform.TransformPoint(groundCheckOffset), groundCheckRadius, groundLayer);
}
// 在编辑器中绘制选中时的Gizmos,用于可视化地面检测范围
void OnDrawGizmosSelected()
{
Gizmos.color = new Color(0, 1, 0, 0.5f);
Gizmos.DrawSphere(transform.TransformPoint(groundCheckOffset), groundCheckRadius);
}
}
五、新建一个Layer层,将地面的Layer设置为Obstacles

配置Player中Player Controller脚本的参数

配置主相机上控制相机的脚本

更多推荐
所有评论(0)