📌 概述
CharacterController 是 Unity 提供的一个 专用胶囊体碰撞器,主要用于角色的移动与碰撞检测。与普通 Collider 不同,它不依赖物理力学,而是通过调用 Move 或 SimpleMove 来驱动角色。
- 继承自:
Collider
- 特点:不受力影响,仅在调用移动函数时才会移动,并自动处理与环境的碰撞。
- 特殊性:虽然没有显式
Rigidbody,但 Unity 内部将其视为“运动体”,因此仍能触发碰撞与触发器事件。
🧠 原理解析
- 内部实现:
CharacterController 本质上是一个带有胶囊体形状的 Collider,Unity 在底层为它实现了类似 Rigidbody 的交互逻辑。
- 事件触发:当调用
Move() 或 SimpleMove() 时,Unity 会计算与其他 Collider 的接触:
- 触发
OnControllerColliderHit(专属回调)。
- 同时也能触发其他物体上的
OnTriggerEnter / OnCollisionEnter。
- 区别于普通 Collider:
- 普通 Collider 没有 Rigidbody 时,只是静态碰撞体,不会触发事件。
CharacterController 是例外,它被 Unity 内部特殊处理。
🧩 核心属性
| 属性 |
类型 |
描述 |
| center |
Vector3 |
胶囊体中心点,相对于角色的 Transform。 |
| height |
float |
胶囊体总高度(包含上下半球和中间圆柱)。 |
| radius |
float |
胶囊体半径,决定粗细和上下半球大小。 |
| skinWidth |
float |
碰撞皮肤宽度,防止角色卡住。默认约 0.08。 |
| stepOffset |
float |
台阶偏移量,允许角色自动跨越小台阶。 |
| slopeLimit |
float |
最大允许斜坡角度(单位:度)。超过此角度角色无法攀爬。 |
| isGrounded |
bool |
上次移动后角色是否接触地面。 |
| minMoveDistance |
float |
最小移动距离,设为 0 表示即使极小的移动也会检测。 |
| detectCollisions |
bool |
是否启用碰撞检测。 |
| enableOverlapRecovery |
bool |
是否启用重叠恢复,避免角色穿透静态物体。 |
| velocity |
Vector3 |
当前相对速度(只读)。 |
| collisionFlags |
CollisionFlags |
上次移动时角色与环境的碰撞情况(如上/下/侧面)。 |
⚙️ 常用方法
| 方法 |
描述 |
| Move(Vector3 motion) |
按给定位移移动角色,受碰撞约束。 |
| SimpleMove(Vector3 speed) |
按速度移动角色,自动应用重力。 |
| OnControllerColliderHit(ControllerColliderHit hit) |
当角色控制器在移动过程中撞到碰撞体时调用。 |
📐 使用示例
基本移动
CharacterController controller;
void Start()
{
controller = GetComponent<CharacterController>();
}
void Update()
{
Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
controller.Move(move * Time.deltaTime * 5f);
}
检测落地
if (controller.isGrounded)
{
Debug.Log("角色在地面上");
}
台阶与斜坡设置
controller.stepOffset = 0.3f; // 可跨越 0.3 米的台阶
controller.slopeLimit = 45f; // 最大斜坡角度 45°
⚖️ 注意事项
- 高度计算:
height 已包含上下半球,不需要额外加上 radius * 2。
- 事件更新:
isGrounded 只在调用 Move 或 SimpleMove 后更新。
- 皮肤宽度:
skinWidth 太小可能导致卡住,太大可能导致角色悬空。
- 台阶与斜坡:
stepOffset 和 slopeLimit 是 3D CharacterController 的优势,2D 中需要手动实现。
- 物理交互:虽然没有 Rigidbody,但仍能触发碰撞/触发器事件,这是 Unity 内部的特殊处理。