创建角色
Assets/
Scenes/
Arena.unity
Scripts/
Prefabs/
Models/
你已经有的这一课新增
打开 tab 01 的 Arena.unity。地板上站着三个 capsule —— Knight、Mage、Archer —— 用按键 1 / 2 / 3 切换。本 tab 的所有操作都在 Knight 身上。
Mage 和 Archer 全程保持 capsule。故意留着它们:每课学完按一下 2,把它们和 Knight 摆在一起,一眼就看出 Knight 进步了多少。
一个游戏角色是同一个 GameObject 上的四层:用来看的 model、用来做动画的骨架、负责选 clip 的 Animator,以及和世界碰撞的 collider。
模型、骨架、Animator、controller —— 四样凑齐,角色才能迈步。
去哪里弄一个角色
Mixamo(免费,需要 Adobe 账号):选角色、选动画、下载 FBX。最快的起步方式。
Unity Asset Store:搜索 “free character”,再按价格 0 筛选。
或者继续用 tab 01 的 Knight capsule —— 下面的每个脚本在 capsule 上同样能跑,model 以后随时替换。
要紧的导入设置
- 1
把 .fbx 拖进 Assets/Models。选中它,打开 Rig tab。
- 2
Animation Type → Humanoid,然后 Apply。这一步把模型的骨骼映射到 Unity 的标准骨架上。
- 3
选了 Humanoid,任何 Mixamo 动画都能用在任何 Mixamo 角色上 —— clip 可以互相通用。
- 4
在 Materials tab 里选 Extract Textures / Extract Materials,这样才编辑得了。
拼装角色对象
- 1
在 Hierarchy 里选中 Knight。删掉 capsule 的 MeshFilter、MeshRenderer 和 Capsule Collider —— 下面的 Character Controller 会顶替 collider —— 但保留 GameObject 和它的名字。
- 2
把 model 拖进来,作为 Knight 的子物体,本地位置 0, 0, 0。父物体保留自己的名字、自己的脚本,也保留在 switcher 列表里的位置。
- 3
在 Knight 本体上,添加 。
- 4
把 Height 设为 1.8、Radius 0.3、Center Y 0.9,让 capsule 正好贴住身体、脚在 Y = 0。然后把 Knight 的 Position Y 调回 0 —— 现在负责把人抬起来的是 collider,不是 transform。
- 5
在 Y = 1.5 创建一个空子物体,叫 CameraTarget —— 相机以后对着它,而不是对着脚。Tab 03 会用到。
- 6
最后把 Knight 拖进 Assets/Prefabs。从此它是 prefab —— Knight 作为自己的文件被保存下来,而不只是这个场景里的一个 object。
用 CharacterController 还是 Rigidbody?
✓ CharacterController
✓ Rigidbody
一个可以往上搭的数值组件
using UnityEngine;
public class CharacterStats : MonoBehaviour
{
[Header("Base")]
public float maxHealth = 100f;
public float attack = 20f;
public float defense = 10f;
public float moveSpeed = 5f;
[Header("Runtime")]
public float currentHealth;
public bool IsAlive => currentHealth > 0f;
void Awake()
{
currentHealth = maxHealth;
}
public void TakeDamage(float rawDamage)
{
if (!IsAlive) return;
float reduced = Mathf.Max(1f, rawDamage - defense); // always at least 1
currentHealth = Mathf.Max(0f, currentHealth - reduced);
if (!IsAlive) Die();
}
void Die()
{
Debug.Log(name + " died");
// animator.SetTrigger("Die"); next lesson
}
}