unity character controller 碰撞

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

背景

在使用摄像机游览场景的时候,需要控制摄像机不穿透场景中的物体,这需要用到碰撞。在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> 
<think>首先,用户请求UnityCharacterController的使用指南。用户提到了几个站内引用,这些引用提供了CharacterController的信息,如它是一种用于角色控制的组件,常用于第三人称或第一人称游戏,具有碰撞检测但无物理效果等。 我的响应必须符合系统级指令: - 所有行内数学表达式使用 `$...$` 格式。 - 独立公式用 `$$...$$` 并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾添加引用标识,如 `[^1]`。 用户可见层的指令: - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 用户的问题:"我想查找UnityCharacterController的使用方法 请问UnityCharacterController的使用指南" 响应结构: 1. **介绍CharacterController**:简要解释它是什么、用途。 2. **关键特性**:基于引用,讨论其属性、方法、使用场景。 3. **使用方法**:逐步指南如何使用,包括代码示例。 4. **注意事项**:常见问题、优化建议。 5. **生成相关问题**:在末尾添加相关问题列表。 从引用中提取关键点: - 引用[1]:CharacterController是胶囊碰撞体,用于角色控制,检测碰撞但无物理效果。 - 引用[2]:使用场景,如相机碰撞检测、解决移动抖动。 - 引用[3]:不受力的影响,移动通过Move函数调用。 - 引用[4]:示例代码,使用CharacterController移动角色。 - 引用[5]:OnControllerColliderHit事件用于检测碰撞。 确保添加引用标识: - 在响应中引用特定信息时,末尾添加 `[^1]` 等。 生成相关问题: - 类似于示例中的,如性能优化、常见错误等。 响应大纲: 1. **引言**:解释CharacterController的作用。 2. **特性**:列出核心属性(如重力、速度等)。 3. **使用方法**: - 添加组件。 - 移动角色(使用Move方法)。 - 处理碰撞事件。 4. **代码示例**:提供简单代码片段。 5. **注意事项**:如无物理力、抖动问题解决。 6. **相关问题**:末尾列出。 因为用户提到"参考站内引用",我会在内容中引用特定部分。 最终响应结构: - 清晰分段。 - 使用中文。 - 代码区块显示示例。 - 末尾添加相关问题。 </think>以下是针对UnityCharacterController使用指南的详细说明。CharacterControllerUnity引擎中的一个内置组件,专为角色移动控制设计,特别适用于第一人称或第三人称游戏(如角色行走、跳跃),它提供了碰撞检测功能但不会响应物理力(如重力或推力),从而简化角色控制逻辑[^1]。本指南将基于Unity官方文档和社区实践,结合引用内容,为您提供结构清晰的步骤指南。所有解释确保真实可靠,并尽可能引用您的参考信息。注意:CharacterController的核心方法是`Move`,移动基于每帧调用,且不受外力影响[^3]。 ### 1. CharacterController组件概述 CharacterController本质上是一个胶囊形状的碰撞体,用于处理角色的移动和碰撞检测。它不涉及刚体(Rigidbody)的物理模拟,因此适合需要精确控制角色移动的场景(如避免相机抖动或实现平滑移动)[^1][^2]。主要特性包括: - **无物理效果**:不会响应重力以外的力(您需手动处理重力),也无法推动其他物理对象[^1][^3]。 - **碰撞检测**:自动检测与环境物体的碰撞,并通过事件如`OnControllerColliderHit`报告碰撞信息[^5]。 - **核心属性**:在Inspector窗口中可配置: - Slope Limit:角色可爬上的最大坡度(单位:度),例如45度。 - Step Offset:角色可跨越的最大台阶高度(单位:米),例如0.3米。 - Skin Width:碰撞检测的皮肤厚度,避免角色卡在物体中,推荐值0.08米[^1][^3]。 ### 2. CharacterController的使用步骤 使用CharacterController涉及添加组件、移动角色和处理碰撞。以下是逐步指南,基于引用[4]的代码框架优化而来。 #### 步骤1:添加组件并初始化 - 在Unity编辑器中,选中您的角色GameObject。 - 添加CharacterController组件:通过Inspector窗口的"Add Component"按钮,搜索"Character Controller"。 - 在脚本中初始化组件(建议在`Start`方法中)。 ```csharp using UnityEngine; public class PlayerController : MonoBehaviour { private CharacterController controller; private Vector3 moveDirection = Vector3.zero; void Start() { controller = GetComponent<CharacterController>(); // 获取组件引用 } } ``` #### 步骤2:移动角色 - 使用`Move`方法进行移动:该方法接受一个世界坐标系下的向量作为移动方向。每次调用需在`Update`或`FixedUpdate`中。 - 手动处理重力:CharacterController不自动应用重力,需在代码中模拟(例如,通过`moveDirection.y -= gravityForce * Time.deltaTime`)。 - 坐标转换:使用`TransformDirection`将局部方向转为世界方向,确保移动正确[^4]。 ```csharp void Update() { // 获取输入(例如键盘或摇杆) float horizontal = Input.GetAxis("Horizontal"); float vertical = Input.GetAxis("Vertical"); float gravity = 9.8f; // 重力加速度 // 计算方向和重力 Vector3 move = new Vector3(horizontal, 0, vertical); // 输入方向 move = transform.TransformDirection(move); // 转为世界坐标 moveDirection = move * moveSpeed * Time.deltaTime; // 移动速度,例如5.0f // 应用重力 moveDirection.y -= gravity * Time.deltaTime; // 执行移动 controller.Move(moveDirection); // Move方法内置碰撞检测 } ``` #### 步骤3:处理碰撞事件 - 使用`OnControllerColliderHit`事件检测碰撞,并从`hit`参数获取碰撞信息(如碰撞物体或点)[^5]。 ```csharp private void OnControllerColliderHit(ControllerColliderHit hit) { // 检测碰撞物体 Debug.Log("Collided with: " + hit.collider.name); // 可选:添加自定义逻辑,如推动物体或播放声音 } ``` ### 3. 注意事项和优化建议 - **避免移动抖动**:如果角色在移动中出现抖动,尝试增加`Skin Width`值或确保移动计算在`FixedUpdate`中进行(而非`Update`),以匹配物理帧率[^2]。 - **无物理响应**:CharacterController不会受外力影响(如爆炸或推力),如果游戏需要物理交互(如角色被击飞),应改用Rigidbody组件或组合使用[^3]。 - **重力处理**:重力必须手动添加;否则角色会悬空。引用[4]示例中展示了`moveDirection.y -= 9.8f * Time.deltaTime`的经典实现。 - **性能优化**:CharacterController比Rigidbody更高效,适用于移动端游戏;但复杂地形中,需调整属性如`Slope Limit`防止角色滑落。 - **常见错误**: - 移动向量未转世界坐标会导致角色方向错误[^4]。 - 忘记应用重力会使角色无法下落。 - 碰撞检测时,`OnControllerColliderHit`只触发当角色主动移动时碰撞[^5]。 ### 4. 完整示例代码 以下是一个简单角色控制器脚本,集成上述所有步骤: ```csharp using UnityEngine; public class CharacterMove : MonoBehaviour { public float moveSpeed = 5.0f; public float gravity = 9.8f; private CharacterController controller; void Start() { controller = GetComponent<CharacterController>(); } void Update() { float h = Input.GetAxis("Horizontal"); float v = Input.GetAxis("Vertical"); Vector3 move = new Vector3(h, 0, v); move = transform.TransformDirection(move) * moveSpeed * Time.deltaTime; move.y = -gravity * Time.deltaTime; // 简化重力应用 controller.Move(move); } private void OnControllerColliderHit(ControllerColliderHit hit) { Debug.Log("Hit object: " + hit.collider.name); } } ``` 将此脚本附加到角色GameObject上,并确保角色有CharacterController组件。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值