Files
BA-VitePress-Pages/posts/studycase2.md
2025-11-26 19:26:14 +08:00

217 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: StudyCase2
date: 2025-11-26 15:38
tags: [studycase, unity]
pinned: true
head:
- - meta
- name: description
content: vitepress-theme-bluearchive StudyCase2
- - meta
- name: keywords
content: vitepress theme bluearchive StudyCase2
---
# 绑定动画
- [世界构筑的起始篇章-编辑器](#1世界构筑的起始篇章-编辑器)
- [光芒汇聚之所-章节目标](#_2光芒汇聚之所-章节目标)
- [光流影卷-演示视频](#3光流影卷-演示视频)
- [初始祭坛-前置准备](#4初始祭坛-前置准备)
- [勇者行迹录-章节任务](#5勇者行迹录-章节任务)
- [异闻录-FAQ](#6异闻录-faq)
## 1.世界构筑的起始篇章-编辑器
- **Unity 2022.3.62f2**
- **Visual Studio 2022**
## 2.光芒汇聚之所-章节目标
- **导入模型修改材质**
- **控制器绑定动画**
## 3.光流影卷-演示视频
<video id="vdMain" controls muted poster="/video/studycase2/演示视频.png" playsinline>
<source id="vSource" src="/video/studycase2/演示视频.mp4" type="video/mp4" />
</video>
## 4.初始祭坛-前置准备
### 1. 导入[FBX模型](/resources/studycase2/FBX.zip),导入[shader](/resources/studycase2/SimpleURPToon.zip)
- 新健文件夹导入FBX
<img src="/image/studycase2/新健文件夹导入FBX.png" data-fancybox="gallery"/>
- 导入shader
<img src="/image/studycase2/导入shader.png" data-fancybox="gallery"/>
## 5.勇者行迹录-章节任务
### 创建StudyCase2
- 复制场景和脚本改名为StudyCase2
<img src="/image/studycase2/复制场景和脚本改名为StudyCase2.png" data-fancybox="gallery"/>
- 修改控制器的命名空间
<img src="/image/studycase2/修改控制器的命名空间.png" data-fancybox="gallery"/>
### 模型处理
- 导出FBX材质球到Mats文件夹方便修改
<img src="/image/studycase2/导出材质.png" data-fancybox="gallery"/>
- 替换模型材质Shader
<img src="/image/studycase2/嘴部材质特殊处理.png" data-fancybox="gallery"/>
- 嘴巴贴图特殊处理
<img src="/image/studycase2/嘴巴贴图特殊处理.png" data-fancybox="gallery"/>
- 属于脸部材质需勾选isFace嘴部材质特殊处理
<img src="/image/studycase2/嘴部材质特殊处理.png" data-fancybox="gallery"/>
### 用模型替换之前的胶囊体
- 替换模型
<img src="/image/studycase2/替换模型.png" data-fancybox="gallery"/>
- 调整模型大小和位置
<img src="/image/studycase2/调整模型大小和位置.png" data-fancybox="gallery"/>
### 创建动画控制器添加Idle和Move动画片段
- 创建动画控制器
<img src="/image/studycase2/创建动画控制器.png" data-fancybox="gallery"/>
- 模型节点添加动画控制器组件
<img src="/image/studycase2/模型节点添加动画控制器组件.png" data-fancybox="gallery"/>
- 打开动画控制器界面Idle作为默认动画
<img src="/image/studycase2/Idle作为默认动画.png" data-fancybox="gallery"/>
- 添加移动动画创建连接创建bool参数
<img src="/image/studycase2/添加移动动画创建连接创建bool参数.png" data-fancybox="gallery"/>
- moving和idle设置为循环播放
<img src="/image/studycase2/moving和idle设置为循环播放.png" data-fancybox="gallery"/>
### 创建状态条件
- 设置idle到moving的条件
<img src="/image/studycase2/设置idle到moving的条件.png" data-fancybox="gallery"/>
- 设置moving到move end的条件
<img src="/image/studycase2/设置moving到move end的条件.png" data-fancybox="gallery"/>
- 设置move end到moving的条件的条件
<img src="/image/studycase2/设置move end到moving的条件.png" data-fancybox="gallery"/>
### 编写脚本`ThirdCharacterController.cs`
- 修改`Assets\Scripts\StudyCase2` 下脚本 `ThirdCharacterController`
```csharp
using UnityEngine;
using UnityEngine.InputSystem;
namespace StudyCase2
{
public class ThirdCharacterController : MonoBehaviour
{
CharacterController characterController;
InputActionAsset inputAction;
Animator animator;
Transform forward;
Transform model;
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 Awake()
{
characterController = GetComponent<CharacterController>();
forward = transform.Find("Forward");
model = transform.Find("Model");
animator = model.GetComponentInChildren<Animator>();
vCam = transform.Find("Virtual Camera").GetComponent<Cinemachine.CinemachineVirtualCamera>();
inputAction = Resources.Load<InputActionAsset>("Player");
inputAction.FindAction("Move").started += OnMove;
inputAction.FindAction("Move").performed += OnMove;
inputAction.FindAction("Move").canceled += OnMove;
inputAction.FindAction("Jump").performed += OnJump;
inputAction.Enable();
}
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)
{
animator?.SetBool("Move", true);
Quaternion target = Quaternion.LookRotation(new Vector3(moveDir.x, 0, moveDir.z));
model.rotation = Quaternion.Slerp(model.rotation, target, turnSpeed * Time.deltaTime);
}
else animator?.SetBool("Move", false);
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;
}
}
}
}
```
### 代码讲解
在Awake中自动获取组件移除PlayerInput
```csharp
private void Awake()
{
characterController = GetComponent<CharacterController>();
forward = transform.Find("Forward");
model = transform.Find("Model");
animator = model.GetComponentInChildren<Animator>();
vCam = transform.Find("Virtual Camera").GetComponent<Cinemachine.CinemachineVirtualCamera>();
inputAction = Resources.Load<InputActionAsset>("Player");
inputAction.FindAction("Move").started += OnMove;
inputAction.FindAction("Move").performed += OnMove;
inputAction.FindAction("Move").canceled += OnMove;
inputAction.FindAction("Jump").performed += OnJump;
inputAction.Enable();
}
```
```csharp
//设置动画控制器参数
//true播放Moveing动画
//false播放Move end动画然后回到Idle
animator.SetBool("Move", true);
```
### Player节点设置
挂载studycase2的控制器移除PlayerInput组件
<img src="/image/studycase2/重载控制器.png" data-fancybox="gallery"/>
## 6.异闻录-FAQ
- **移动不播放动画**:确认动画控制器的参数名字和脚本中设置的一样。
- **动画只播放一遍**:检查是否勾选循环播放,在模型上看。
- **动画状态切换有延迟**确认动画控制器中连接线的HasExitTime是否勾选。
完成以上步骤,即可得到一个带动画的第三人称控制器。[项目地址](http://home.gtuantuan.online:8300/TuanTuan/StudyCase)