You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity 3D中如何在Character Controller里实现OnCollisionExit?

在OnControllerColliderHit中实现类似OnCollisionEnter/Exit的功能

核心问题说明

OnControllerColliderHit 仅会在控制器与碰撞体接触的每一帧触发,没有内置的碰撞退出回调。要实现"碰撞显示、离开隐藏"的效果,需要手动跟踪当前接触的目标对象状态。

解决方案代码

using UnityEngine;
using System.Collections.Generic;

public class PlayerCollision : MonoBehaviour
{
    public PlayerMovement movement;
    [SerializeField] GameObject _toggleObject;
    // 存储当前正在接触的障碍物对象,自动去重
    private HashSet<GameObject> _currentObstacles = new HashSet<GameObject>();

    private void OnControllerColliderHit(ControllerColliderHit hit)
    {
        if (hit.gameObject.CompareTag("Obstacle"))
        {
            // 将接触的障碍物加入集合
            _currentObstacles.Add(hit.gameObject);
            // 激活目标物体
            _toggleObject.SetActive(true);
        }
    }

    private void Update()
    {
        // 清理集合中已销毁的对象,避免内存泄漏
        _currentObstacles.RemoveWhere(obj => obj == null);
        
        // 如果没有接触任何障碍物,隐藏目标物体
        if (_currentObstacles.Count == 0)
        {
            _toggleObject.SetActive(false);
        }
    }

    private void OnDisable()
    {
        // 对象禁用时清空集合,防止残留数据
        _currentObstacles.Clear();
    }
}

代码逻辑解释

  1. HashSet跟踪接触对象:用HashSet<GameObject>存储当前接触的障碍物,避免同一对象重复添加,确保状态准确。
  2. OnControllerColliderHit处理碰撞中状态:每次检测到与障碍物接触时,将对象加入集合并激活显示物体。
  3. Update检测退出状态:每帧检查集合,若集合为空(无任何障碍物接触),则隐藏显示物体;同时清理已销毁的对象,避免无效引用。
  4. OnDisable清理数据:对象禁用或场景切换时清空集合,防止残留状态影响后续逻辑。

额外注意事项

  • 确保CharacterController的Skin Width和Min Move Distance参数设置合理,避免因控制器抖动导致的状态频繁切换。
  • 如果需要更精确的碰撞进入/退出时机,可以结合Physics.OverlapCapsule(匹配CharacterController的碰撞范围)在Update中主动检测,但上述方案是适配OnControllerColliderHit的最直接实现方式。

内容的提问来源于stack exchange,提问作者Richard Johnson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 14:20:22