2025-11-26 15:17:27 +08:00
|
|
|
|
---
|
|
|
|
|
|
title: StudyCase1
|
|
|
|
|
|
date: 2025-11-25 15:35
|
|
|
|
|
|
tags: [studycase, unity]
|
|
|
|
|
|
pinned: true
|
|
|
|
|
|
head:
|
|
|
|
|
|
- - meta
|
|
|
|
|
|
- name: description
|
|
|
|
|
|
content: vitepress-theme-bluearchive StudyCase1
|
|
|
|
|
|
- - meta
|
|
|
|
|
|
- name: keywords
|
|
|
|
|
|
content: vitepress theme bluearchive StudyCase1
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# 第三人称角色控制器
|
|
|
|
|
|
|
|
|
|
|
|
## 编辑器
|
|
|
|
|
|
- **Unity 2022.3.62f2**:
|
|
|
|
|
|
- **Visual Studio 2022**
|
|
|
|
|
|
|
|
|
|
|
|
## 课程目标
|
|
|
|
|
|
- **鼠标控制视角旋转**
|
|
|
|
|
|
- **WASD控制模型移动**
|
|
|
|
|
|
- **空格控制跳跃**
|
|
|
|
|
|
|
|
|
|
|
|
## 演示视频
|
|
|
|
|
|
<video id="vdMain" controls muted poster="/video/studycase1/演示视频.png" playsinline>
|
|
|
|
|
|
<source id="vSource" src="/video/studycase1/演示视频.mp4" type="video/mp4" />
|
|
|
|
|
|
</video>
|
|
|
|
|
|
|
|
|
|
|
|
## 课前准备
|
|
|
|
|
|
### 新建项目
|
|
|
|
|
|
- 创建URP项目
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/创建URP项目.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
- 移除Readme
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/移除Readme.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
- 新建场景或者修改初始场景为StudyCase1
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/创建StudyCase1场景.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
### 安装 Input System 与 Cinemachine
|
|
|
|
|
|
- 打开 Package Manager
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/打开PackageManager.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
- 切换到 Unity Registry
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/切换到UnityRegistry.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
- 安装 `Input System` 与 `Cinemachine`
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/安装俩个包.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
- 导入示例
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/导入示例.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
- 创建初始场景(StudyCase1)
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/创建初始场景.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
- 从示例项目导入模型到场景
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/从示例项目导入模型到场景.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
> 提示:安装 Input System 后,Unity 会提示重启并切换至新输入系统,务必确认。
|
|
|
|
|
|
|
|
|
|
|
|
## 课堂任务
|
|
|
|
|
|
### 添加虚拟相机根节点
|
|
|
|
|
|
- 为相机添加 `CinemachineBrain`作为根节点以便统一控制
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/添加虚拟相机根节点.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
### 创建玩家节点
|
|
|
|
|
|
- 创建 `Player` 空节点,创建`Forward`和`Model`空节点并作为`Player`子节点以及虚拟相机
|
|
|
|
|
|
- 注意`Forward`和`Model`的尽量不要有偏移
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/创建玩家层级.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
- 创建胶囊体和正方体作为`Model`的子物体,可以去掉碰撞器,尽量不要有偏移
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/玩家节点.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
### 配置虚拟相机
|
|
|
|
|
|
- 将虚拟相机 `Follow`、`LookAt` 指向玩家模型,调整 Body/ Aim,使镜头保持第三人称视角
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/配置虚拟相机.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
### 创建 InputActions
|
|
|
|
|
|
- 在项目窗口右键 `Create > Input Actions`,命名为 `PlayerInputActions`
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/创建InputActions.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
- 创建 `Player` Action Map,添加 `Move`(Vector2)与 `Jump`(Button)
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/创建playerinputactions.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
- Move 绑定 `WASD` ;Jump 绑定 `space`
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/创建4向绑定.png" data-fancybox="gallery"/>
|
|
|
|
|
|
<img src="/image/studycase1/绑定wasd.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
### 编写脚本`ThirdCharacterController.cs`
|
|
|
|
|
|
- 在 `Assets\Scripts\StudyCase1` 下创建脚本 `ThirdCharacterController`
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.InputSystem;
|
|
|
|
|
|
|
|
|
|
|
|
namespace StudyCase1
|
|
|
|
|
|
{
|
|
|
|
|
|
public class ThirdCharacterController : MonoBehaviour
|
|
|
|
|
|
{
|
|
|
|
|
|
public CharacterController characterController;
|
|
|
|
|
|
public Transform forward;
|
|
|
|
|
|
public Transform model;
|
|
|
|
|
|
public Cinemachine.CinemachineVirtualCamera vCam;
|
|
|
|
|
|
public float moveSpeed = 5f;
|
|
|
|
|
|
public float jumpSpeed = 2f;
|
|
|
|
|
|
public float turnSpeed = 10f;
|
|
|
|
|
|
public float gravity = 10f;
|
|
|
|
|
|
Vector3 moveDir;
|
|
|
|
|
|
Vector2 moveInput;
|
|
|
|
|
|
private void Update()
|
|
|
|
|
|
{
|
|
|
|
|
|
moveDir = new Vector3(moveInput.x, moveDir.y, moveInput.y);
|
|
|
|
|
|
forward.eulerAngles = new Vector3(0, vCam.transform.eulerAngles.y, 0);
|
|
|
|
|
|
moveDir = forward.TransformDirection(moveDir);
|
|
|
|
|
|
if (moveInput != Vector2.zero)
|
|
|
|
|
|
{
|
|
|
|
|
|
Quaternion target = Quaternion.LookRotation(new Vector3(moveDir.x, 0, moveDir.z));
|
|
|
|
|
|
model.rotation = Quaternion.Slerp(model.rotation, target, turnSpeed * Time.deltaTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!characterController.isGrounded)
|
|
|
|
|
|
moveDir.y -= gravity * Time.deltaTime;
|
|
|
|
|
|
characterController.Move(moveDir * moveSpeed * Time.deltaTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
public void OnMove(InputAction.CallbackContext context)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (characterController.isGrounded)
|
|
|
|
|
|
moveInput = context.ReadValue<Vector2>();
|
|
|
|
|
|
else moveInput = Vector2.zero;
|
|
|
|
|
|
}
|
|
|
|
|
|
public void OnJump(InputAction.CallbackContext context)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (context.performed && characterController.isGrounded)
|
|
|
|
|
|
{
|
|
|
|
|
|
moveDir.y = jumpSpeed;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 代码讲解
|
|
|
|
|
|
- **namespace StudyCase1**:因为可能出现同名文件
|
|
|
|
|
|
- **forward**:作为“参照物”同步虚拟相机的 Y 轴旋转,用来转换输入的坐标轴。
|
|
|
|
|
|
- **moveDir**:在本地坐标系下计算移动向量,并通过 `CharacterController.Move` 驱动。
|
|
|
|
|
|
- **OnMove/OnJump**:直接使用 Input System 回调,确保只有在贴地时才写入输入,避免空中漂移。
|
|
|
|
|
|
- **旋转插值**:`Quaternion.Slerp` 让角色转身更加顺滑,可根据手感微调 `turnSpeed`。
|
|
|
|
|
|
|
|
|
|
|
|
### Player节点设置
|
|
|
|
|
|
- 挂载`ThirdCharacterController`
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/挂载ThirdCharacterController.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
- 添加组件`PlayerInput`
|
|
|
|
|
|
|
|
|
|
|
|
<img src="/image/studycase1/添加组件PlayerInput.png" data-fancybox="gallery"/>
|
|
|
|
|
|
|
|
|
|
|
|
## 常见问题速查
|
|
|
|
|
|
- **角色不动**:确认 `CharacterController` 已赋值且 `Move` Action Map 激活。
|
|
|
|
|
|
- **镜头不同步**:检查 `forward` 对象是否正确引用虚拟相机的朝向,检查模型和`player`是否偏移过大。
|
|
|
|
|
|
- **跳跃失效**:确认 `Jump` 绑定的动作类型为 `Button`,确认角色是否在地上。
|
|
|
|
|
|
- **移动时会旋转镜头**:确认虚拟相机是在 `Player` 节点下,不是在 `Model` 节点下。
|
|
|
|
|
|
|
2025-11-26 15:32:18 +08:00
|
|
|
|
完成以上步骤,即可得到一个可拓展的第三人称基础模板。[项目地址](http://home.gtuantuan.online:8300/TuanTuan/StudyCase)
|