You need to enable JavaScript to run this app. Unity如何将碰撞检测函数接入Update实现碰撞停5秒后穿过运动学物体
优惠活动
大模型
产品
解决方案
定价
更多

Unity如何将碰撞检测函数接入Update实现碰撞停5秒后穿过运动学物体

Unity 碰撞后临时停止再穿过Kinematic对象的实现修正

原代码的核心问题

  • 回调函数名错误:Unity 不会触发自定义命名的OnCollision方法,必须使用引擎内置的OnCollisionEnter(Collision collision)碰撞回调才能接收碰撞事件
  • 协程逻辑失效:原脚本里WaitBeforeMove协程没有绑定状态控制,在Start里启动时没有碰撞触发,只是无意义等待5秒,完全没有实现暂停移动的效果
  • 移动逻辑漏洞:Update里每帧无条件给Rigidbody加力,没有状态开关控制,就算临时把speed设为0也无法实现持续5秒的停止效果
  • Kinematic穿透逻辑缺失:要穿过标记为Is Kinematic的对象2,需要在暂停结束后主动配置物理碰撞忽略,否则仍会被Collider的实体碰撞效果阻挡

具体实现方案

  1. 新增状态标记变量:
    • isMovingAllowed:控制是否允许给Rigidbody施加移动力
    • targetStationCollider:存储碰撞到的对象2的Collider组件,用于后续设置穿透
  2. 在OnCollisionEnter回调中判定目标碰撞对象,触发停止逻辑:将移动开关关闭,启动等待协程
  3. 协程等待5秒后,重新打开移动开关,同时调用Physics.IgnoreCollision设置和对象2的Collider永久忽略碰撞,实现穿过效果
  4. Update中仅在移动开关开启时施加移动力,避免停止阶段仍有作用力

修正后完整代码

using System.Collections;
using UnityEngine;

public class TRAINMOVE : MonoBehaviour
{
    [Header("移动配置")]
    [SerializeField] private float speed = 200f;
    [SerializeField] private float stopDuration = 5f;
    
    private Rigidbody rb;
    private bool isMovingAllowed = true;
    private Collider targetStationCollider;

    private void Awake()
    {
        rb = GetComponent<Rigidbody>();
    }

    private void Update()
    {
        // 仅在允许移动时施加力,实现停止效果
        if (isMovingAllowed)
        {
            rb.AddForce(transform.up * speed * Time.deltaTime);
        }
    }

    // 引擎内置碰撞进入回调,会在两个非Trigger Collider碰撞时自动触发
    private void OnCollisionEnter(Collision collision)
    {
        // 仅第一次碰撞目标对象时触发停止逻辑
        if (collision.gameObject.name == "train trigger station1" && isMovingAllowed)
        {
            isMovingAllowed = false;
            // 记录目标Collider,用于后续穿透设置
            targetStationCollider = collision.collider;
            // 启动等待恢复的协程
            StartCoroutine(ResumeMoveAfterStop());
        }
    }

    private IEnumerator ResumeMoveAfterStop()
    {
        // 等待指定的停止时长
        yield return new WaitForSeconds(stopDuration);
        // 恢复移动权限
        isMovingAllowed = true;
        // 设置和目标对象的碰撞永久忽略,实现穿透效果
        if (targetStationCollider != null)
        {
            Physics.IgnoreCollision(GetComponent<Collider>(), targetStationCollider, true);
        }
    }
}

注意事项

  • 确保两个对象的Collider都没有勾选Is Trigger,否则OnCollisionEnter不会触发,需要改用OnTriggerEnter
  • 对象2开启Is Kinematic后不会受物理力影响,只要设置了碰撞忽略,对象1的Rigidbody就能顺利穿过
  • 不要在Update或碰撞回调里直接做5秒等待逻辑,会阻塞主线程,必须用协程实现延时处理

内容的提问来源于stack exchange,提问作者Karlnico Diego

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.03 18:36:08