unity character controller 碰撞

本文介绍如何在Unity中使用CharacterController来控制摄像机移动并处理碰撞。通过CharacterController,可以在不使用刚体的情况下实现复杂的碰撞检测,适用于第一人称视角等应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

在使用摄像机游览场景的时候,需要控制摄像机不穿透场景中的物体,这需要用到碰撞。在unity物理引擎中有两类的情况可以检测到碰撞,一种是一方是刚体+碰撞器和另一方碰撞器碰撞(参加碰撞器和刚体),另一种就是Character Controller与其他的碰撞器碰撞的时候


在使用摄像机游览场景的时候,虽然需要去碰撞检测,但是一个特别的要求就是摄像机和其他物体碰撞之后不能对它们产生任何力的作用,同时摄像机本身也不需要受到模拟真实碰撞的反作用力,也就是说这个时候给摄像机挂载刚体属性还是不大适合的


这个时候Character Controller就被制作出来满足这种需求,Character Controller本身自带一个碰撞器,无需刚体即可完成触发(Trigger)和碰撞(Collision)功能。


使用

使用character controller来控制摄像机的移动,可以获取更加丰富的碰撞信息,完成更好的控制。


要使用角色控制器,首先将Character Controller 组件挂载到目标对象上,一般是摄像机的父节点,然后同时添加一个脚本,脚本获取Character Controller组件实例,并且在Update或者FixedUpdate函数中调用controller.Move更新控制器的位置(同时也会移动子节点摄像机的位置),假如与其他的碰撞器发生碰撞之后,角色控制器会被阻挡前进,同时会触发OnControllerColliderHit 函数。需要注意的是

OnControllerColliderHit要被触发,需要在同一脚本中同时要调用角色控制器的Move函数。character controller与其他的碰撞器发生碰撞后,会自动调用函数

void OnControllerColliderHit (ControllerColliderHit hit)


ControllerColliderHit

ControllerColliderHit is used by CharacterController.OnControllerColliderHit to give detailed information about the collision and how to deal with it.

Variables

collider

The collider that was hit by the controller.

controller

The controller that hit the collider.

gameObject

The game object that was hit by the controller.

moveDirection

Approximately the direction from the center of the capsule to the point we touch.

moveLength

How far the character has travelled until it hit the collider.

normal

The normal of the surface we collided with in world space.

point

The impact point in world space.

rigidbody

The rigidbody that was hit by the controller.

transform

The transform that was hit by the controller.


示例

创建一个空游戏对象FpsController,给它添加CharacterController组件,同时添加一个摄像机作为它的子成员,同时将如下代码挂到FpsController上

[csharp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:14px;">[RequireComponent (typeof(CharacterController))]  
  2. public class FPSNavigator : MonoBehaviour   
  3. {  
  4.   
  5.   
  6.     public KeyCode mKeyLeft = KeyCode.LeftArrow;  
  7.     public KeyCode mKeyRight = KeyCode.RightArrow;  
  8.     public KeyCode mKeyForward = KeyCode.UpArrow;  
  9.     public KeyCode mKeyBackward = KeyCode.DownArrow;  
  10.       
  11.     public float mKeyStrokeMoveStep = 0.07f;    //metre  
  12.   
  13.     private CharacterController controller;  
  14.     private Vector3 mMoveDir ;  
  15.       
  16.     void Start () {  
  17.       
  18.         controller = GetComponent<CharacterController>();  
  19.   
  20.     }  
  21.       
  22.     // Update is called once per frame  
  23.     void Update () {  
  24.       
  25.         Vector3 vDir = Vector3.zero;  
  26.         if(Input.GetKey(mKeyLeft))  
  27.         {  
  28.             vDir.x -= mKeyStrokeMoveStep;  
  29.         }  
  30.         if(Input.GetKey(mKeyRight))  
  31.         {  
  32.             vDir.x += mKeyStrokeMoveStep;  
  33.         }  
  34.   
  35.         if(Input.GetKey(mKeyForward))  
  36.         {  
  37.             vDir.z += mKeyStrokeMoveStep;  
  38.         }  
  39.         if(Input.GetKey(mKeyBackward))  
  40.         {  
  41.             vDir.z -= mKeyStrokeMoveStep;  
  42.         }  
  43.         mMoveDir = transform.rotation*vDir;  
  44.   
  45.         controller.Move(mMoveDir);  
  46.       
  47.     }  
  48. }</span> 
### Unity CharacterController 碰撞检测与处理 #### 使用刚体和碰撞器组合 当希望使用传统物理引擎特性来管理对象间的交互时,可以选择给一个游戏对象配置 `Rigidbody` 和 `Collider` 组件。这种情况下,另一个参与碰撞的对象只需要拥有 `Collider` 即可实现两者之间的碰撞响应[^1]。 对于此类设置,在确保两个物体能够正常发生碰撞前,需核查 **Project Settings -> Physics -> Layer Collision Matrix** 的设定是否允许所涉及图层间相互作用[^2]。 #### 利用Character Controller组件 针对更复杂的角色行为模拟需求,则推荐采用专门设计用于人物控制的 `Character Controller` 组件。此组件内建有基本形状(胶囊形或其他自定义形式)作为其自身的碰撞边界,并能直接参与到环境内的其他静态或动态障碍物产生的碰撞事件之中而不需要额外附加 `Rigidbody` 来辅助工作。 具体来说,通过脚本调用 `CharacterController.SimpleMove(Vector3)` 或者 `CharacterController.Move(Vector3)` 方法可以让角色按照指定方向前进的同时自动处理好可能遇到的各种地形变化以及周围实体带来的阻碍情况[^3]。 下面是一个简单的例子展示如何利用 `CharacterController` 实现基础运动并保证不会穿过墙壁等结构: ```csharp using UnityEngine; public class PlayerMovement : MonoBehaviour { private CharacterController _controller; void Start() { _controller = GetComponent<CharacterController>(); } void Update() { float horizontalInput = Input.GetAxis("Horizontal"); float verticalInput = Input.GetAxis("Vertical"); Vector3 movementDirection = transform.right * horizontalInput + transform.forward * verticalInput; if (_controller.isGrounded) { _controller.Move(movementDirection.normalized * speed * Time.deltaTime); } } } ``` 上述代码片段展示了基于玩家输入计算出移动向量后传递给 `_controller.Move()` 函数执行实际位移操作的过程。由于 `CharacterController` 自带了防止穿模的功能,因此只要合理调整参数就能轻松达成预期效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值