This commit is contained in:
2025-11-26 15:17:27 +08:00
commit a8e4f56999
350 changed files with 25023 additions and 0 deletions

182
posts/studycase1.md Normal file
View File

@@ -0,0 +1,182 @@
---
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>
[项目地址](http://home.gtuantuan.online:8300/TuanTuan/StudyCase)
## 课前准备
### 新建项目
- 创建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` 节点下。
完成以上步骤,即可得到一个可拓展的第三人称基础模板。