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

Unity中直接设置物体位置后,如何获取碰撞器的碰撞数量?

Unity直接设置transform.position后统计碰撞器碰撞数量的解决方法

问题根源

你当前的代码依赖OnCollisionEnter和OnCollisionExit物理回调统计碰撞数量,但直接修改transform.position属于瞬时位置变更,Unity物理系统不会为这种操作触发碰撞进入/退出的回调,导致统计结果完全不准确。

解决方案

方案1:用物理API替代直接修改position

如果物体带有Rigidbody组件,优先使用Rigidbody.MovePosition移动物体,物理系统会正常处理碰撞逻辑,原有回调即可正常工作。

示例代码:

using UnityEngine;

public class GettingQuantityOfCollisions : MonoBehaviour
{
    private int QuantityOfTheObjectsInTheZone = 0;
    private Rigidbody _rb;

    public int GetQuantityOfTheObjectsInTheZone() => QuantityOfTheObjectsInTheZone;

    void Awake()
    {
        _rb = GetComponent<Rigidbody>();
        // 若不需要重力等物理效果,可开启运动学刚体
        _rb.isKinematic = true;
    }

    // 调用此方法替代直接设置transform.position
    public void MoveToTarget(Vector3 targetPos)
    {
        _rb.MovePosition(targetPos);
    }

    private void OnCollisionEnter(Collision anyCollision) => QuantityOfTheObjectsInTheZone++;
    private void OnCollisionExit(Collision anyCollision) => QuantityOfTheObjectsInTheZone--;
}

方案2:直接改position后手动检测碰撞

如果必须直接修改transform.position,可在位置变更后,手动检测当前碰撞器接触的所有物体,更新统计数量。

修改后的脚本:

using UnityEngine;
using System.Collections.Generic;

public class GettingQuantityOfCollisions : MonoBehaviour
{
    private int QuantityOfTheObjectsInTheZone = 0;
    private Collider _collider;

    public int GetQuantityOfTheObjectsInTheZone() => QuantityOfTheObjectsInTheZone;

    void Awake()
    {
        _collider = GetComponent<Collider>();
    }

    // 每次直接设置transform.position后,调用此方法更新碰撞计数
    public void RefreshCollisionCount()
    {
        ContactFilter2D filter = new ContactFilter2D();
        // 可根据需求设置过滤条件,例如指定检测层:filter.layerMask = LayerMask.GetMask("Player");
        Collider[] tempColliders = new Collider[20]; // 数组大小根据场景预估调整
        int detectCount = _collider.OverlapCollider(filter, tempColliders);

        // 用HashSet去重,避免同一物体多个碰撞器重复计数
        HashSet<GameObject> uniqueColliders = new HashSet<GameObject>();
        for (int i = 0; i < detectCount; i++)
        {
            uniqueColliders.Add(tempColliders[i].gameObject);
        }

        QuantityOfTheObjectsInTheZone = uniqueColliders.Count;
    }

    // 保留原有回调,处理正常物理移动时的碰撞
    private void OnCollisionEnter(Collision anyCollision)
    {
        if (!anyCollision.gameObject.Equals(gameObject))
            QuantityOfTheObjectsInTheZone++;
    }

    private void OnCollisionExit(Collision anyCollision)
    {
        if (!anyCollision.gameObject.Equals(gameObject))
            QuantityOfTheObjectsInTheZone--;
    }
}

注意事项

  • 若使用2D物理系统,需替换为Collider2D.OverlapCollider和对应的ContactFilter2D
  • 手动检测时,可通过ContactFilter过滤特定层、标签的物体,减少不必要的检测
  • 调用RefreshCollisionCount()的时机必须在transform.position设置完成之后

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 07:50:27