news 2026/10/26 6:34:59

Unity物理交互:Collider与Trigger核心机制与实战避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Unity物理交互:Collider与Trigger核心机制与实战避坑指南

1. 碰撞与触发:物理交互的两套底层逻辑

做Unity项目的人,绕不开物理交互这块。不管是做角色控制、子弹命中判定、道具拾取,还是做关卡里的机关触发,Collider和Trigger这两套机制几乎贯穿了所有交互场景。我见过不少刚入行的朋友,角色撞墙能停住,但走到传送门前面死活触发不了;也见过子弹打出去穿透敌人,明明加了碰撞体却毫无反应。这些问题九成以上都出在对Collider和Trigger的理解偏差上。

先把概念摆清楚。Collider(碰撞器)是挂在GameObject上的物理形状组件,它定义了物体的物理边界,让物理引擎知道"这个东西占多大空间、长什么形状"。而Trigger(触发器)本质上不是独立组件,它是Collider上的一个开关属性——勾选Is Trigger之后,这个碰撞体就不再产生物理阻挡,转而只负责检测"有没有东西进来、出去、停留"。一句话概括:Collider负责"挡",Trigger负责"感知"。

这个区别听起来简单,但实际项目里出问题的往往不是概念本身,而是配套条件没配齐。比如两个物体要发生碰撞或触发,至少一方必须挂Rigidbody(刚体),这是物理引擎参与计算的前提。很多人只给碰撞体不给刚体,然后纳闷为什么OnTriggerEnter不执行——因为物理系统压根没把这两个物体纳入模拟。再比如Layer碰撞矩阵、Collider的尺寸精度、刚体的isKinematic设置,每一个都会直接影响最终行为。

这篇内容适合谁看?如果你是刚接触Unity物理系统、被各种"撞不到""触发不了"折磨过的开发者,或者你已经有项目经验但想系统梳理一遍碰撞检测的完整链路,那接下来的内容应该能帮你把这块知识补扎实。我会从设计思路、核心参数、实操流程到排查技巧,把Collider和Trigger这套机制拆开讲透,每个环节都配上能直接抄的配置和踩坑经验。

2. 整体设计思路:为什么物理交互要分两套机制

2.1 碰撞与触发的职责边界

Unity把物理交互拆成"碰撞"和"触发"两条路径,背后是有明确工程考量的。碰撞(Collision)走的是物理求解流程:物理引擎检测到两个碰撞体相交后,会计算穿透深度、法线方向、相对速度,然后施加冲量把物体推开,同时回调OnCollisionEnter/Stay/Exit。这套流程是有计算成本的,涉及连续碰撞检测、摩擦力和弹性系数的求解。

触发(Trigger)走的是重叠检测流程:物理引擎只判断两个碰撞体的包围体是否相交,相交就回调OnTriggerEnter/Stay/Exit,但不做任何物理响应。计算量明显更小,适合"只需要知道发生了接触、不需要物理反应"的场景。

这个拆分带来的直接好处是性能可控。你想想,一个场景里可能有几百个道具、几十发子弹、一堆检测区域,如果全部走物理求解,帧率直接崩掉。而把这些"感知型"交互全部改成Trigger,物理引擎只需要做重叠判断,开销小得多。我在一个塔防项目里做过对比:200个敌人和防御塔的接触检测,用Collision方案在低端机上掉到40帧,改成Trigger后稳定60帧。这不是玄学,是物理求解和重叠检测的本质差异。

2.2 什么时候用Collider,什么时候用Trigger

判断标准其实很朴素:需要物理阻挡或力的反馈,用Collider;只需要知道"碰到了"这个事件,用Trigger。

需要Collider的典型场景:角色撞墙停住、箱子被推动、球体弹跳、物体堆叠、载具碰撞。这些都需要物理引擎介入,产生位置修正或力的作用。

需要Trigger的典型场景:进入区域触发剧情、拾取道具、子弹命中判定、检测玩家是否在攻击范围内、关卡边界检测、UI交互区域。这些场景里,物体之间不应该有物理阻挡——你总不希望玩家走过去捡金币的时候被金币弹开吧。

有个容易混淆的点:子弹命中判定。很多教程会让子弹用Collider加Rigidbody,靠OnCollisionEnter检测命中。这在慢速子弹上没问题,但高速子弹会出现"穿透"——因为物理引擎是按帧离散检测的,子弹一帧移动距离超过目标厚度,就直接穿过去了。正确做法是子弹用Trigger加Rigidbody,开启Continuous Dynamic连续碰撞检测,或者干脆用射线检测(Raycast)做命中判定。这个取舍后面会详细讲。

2.3 物理引擎的参与条件:Rigidbody是入场券

这是新手最容易忽略的一点。Unity的物理系统(不管是PhysX还是Box2D)只处理至少一方带Rigidbody的碰撞体对。两个都只有Collider没有Rigidbody的物体,物理引擎根本不会计算它们之间的交互,回调也不会触发。

具体规则是这样的:

物体A物体B碰撞回调触发回调
Rigidbody + ColliderCollider(静态)触发触发
Rigidbody + ColliderRigidbody + Collider触发触发
Collider(静态)Collider(静态)不触发不触发
Rigidbody + TriggerCollider不触发触发
Rigidbody + TriggerRigidbody + Trigger不触发触发

注意最后两行:Trigger之间的交互只走触发回调,永远不会有碰撞回调。哪怕两个都勾了Is Trigger,它们之间只会触发OnTrigger系列事件。这个表格建议截图存手机里,排查问题时对着看,能省掉大量试错时间。

还有一个隐藏条件:Rigidbody的isKinematic。如果刚体勾了isKinematic,它不受物理力影响,但依然能参与触发检测。这个特性在做"跟随移动的检测区域"时特别有用——比如一个挂在角色身上的攻击范围Trigger,你希望它跟着角色走但不被物理推来推去,就给它挂个isKinematic的Rigidbody。

3. 核心参数与组件配置详解

3.1 Collider类型选型:形状决定性能与精度

Unity提供了多种Collider,选型的核心原则是:用最简单的形状覆盖需求,精度不够再升级。

  • BoxCollider:盒形,计算最快,适合箱子、墙壁、地板、角色胶囊的替代。绝大多数静态场景物体用它就够了。
  • SphereCollider:球形,计算快且各向同性,适合球体、检测范围、爆炸波及范围。
  • CapsuleCollider:胶囊形,角色控制器的标配,因为它在斜坡和台阶上的滑动表现比Box平滑。
  • MeshCollider:网格形,精度最高但计算最贵,而且默认不支持非凸(non-convex)网格参与物理碰撞。静态地形可以用,动态物体慎用。
  • TerrainCollider:地形专用,配合Terrain组件使用。

MeshCollider有个大坑:Convex(凸体)选项。勾了Convex,MeshCollider才能参与动态碰撞和触发;不勾的话只能作为静态碰撞体,而且不能和另一个MeshCollider发生碰撞。我见过有人给角色挂了个不勾Convex的MeshCollider,结果角色直接穿地——因为物理引擎把它当静态物体处理了。另外,Convex MeshCollider最多支持255个三角面,超过会被简化,精度反而下降。所以角色和动态物体,老老实实用Capsule或Box,别上Mesh。

3.2 Is Trigger开关:一个勾选框改变整个行为

Is Trigger这个勾选框的作用,是把Collider从"物理实体"切换成"感知区域"。勾上之后:

  • 不再产生物理阻挡,其他物体可以直接穿过
  • 不再触发OnCollision系列回调
  • 改为触发OnTriggerEnter/Stay/Exit
  • 依然需要至少一方有Rigidbody才能检测

这里有个细节很多人不知道:Trigger的检测精度依赖Collider的形状和尺寸。一个BoxTrigger如果尺寸设得比视觉模型小一圈,玩家走到边缘看着已经进去了,但实际没触发。反过来设大了,还没碰到就触发了。我的习惯是给Trigger加一个半透明的Gizmo可视化(在Scene视图里能看到绿色线框),调尺寸的时候对着视觉边界微调,确保触发范围和玩家感知一致。

3.3 Rigidbody的关键参数:质量、阻力与检测模式

Rigidbody上几个参数直接影响碰撞和触发行为,逐个说:

Mass(质量):影响碰撞时的动量交换。两个物体碰撞,质量大的推质量小的。但注意,Trigger检测跟质量无关,只跟重叠有关。所以做触发检测时不用纠结质量设置。

Drag(阻力)和Angular Drag(角阻力):影响物体运动衰减。做子弹时如果Drag设太大,子弹飞一半就停了,看起来像"射程不够"。一般子弹Drag设0,靠脚本控制生命周期。

Use Gravity:是否受重力。做漂浮的检测区域时记得关掉,不然Trigger区域会往下掉。

Is Kinematic:勾上后不受物理力,但能参与触发检测。适合"跟着动画或脚本移动的检测体"。注意,isKinematic的刚体之间不会产生碰撞回调,但可以和普通刚体产生碰撞回调(如果对方不是kinematic)。

Collision Detection(碰撞检测模式):

模式适用场景性能开销
Discrete(离散)普通慢速物体最低
Continuous(连续)快速移动物体中等
Continuous Dynamic(连续动态)高速子弹、快速角色最高
Continuous Speculative(连续推测)高速但可接受轻微误差中等

高速子弹必须用Continuous Dynamic,否则一帧位移超过目标厚度就穿透了。我实测过:一颗速度50m/s的子弹,60帧下每帧移动约0.83米,如果目标碰撞体厚度只有0.2米,Discrete模式下必然穿透。改成Continuous Dynamic后命中率从六成提升到接近百分之百。

Interpolate(插值):让物理更新和渲染帧率对齐,视觉上更平滑。做角色移动时建议开Interpolate,不然高速移动会有抖动感。

3.4 Layer碰撞矩阵:被忽视的过滤利器

Unity的Layer碰撞矩阵(Edit > Project Settings > Physics > Layer Collision Matrix)决定了哪些层的物体之间会发生碰撞和触发。这个功能用好了能大幅减少无效检测。

举个实际例子:玩家子弹层和玩家层之间的碰撞应该关掉,不然子弹一出膛就撞到自己。敌人层和敌人层之间的碰撞如果不需要互相推挤,也可以关掉来省性能。UI检测层和场景物体层之间通常也要隔离。

配置方法:给不同类别的物体分配Layer,然后在矩阵里取消勾选不需要交互的组合。注意,Trigger检测同样受Layer矩阵控制——两个层如果在矩阵里没勾选,它们的Trigger也不会触发。这个点很多人不知道,排查"触发不生效"时经常是这里的问题。

4. 实操流程:从零搭一套可用的碰撞触发系统

4.1 场景搭建与基础配置

假设我们要做一个最小可用的演示:一个玩家角色(CapsuleCollider + Rigidbody),一面墙(BoxCollider),一个传送门区域(BoxCollider + Is Trigger),一个可拾取的金币(SphereCollider + Is Trigger)。

第一步,创建玩家。新建Capsule,挂CapsuleCollider,再挂Rigidbody。Rigidbody设置:Mass 1,Drag 0,Angular Drag 0.05,Use Gravity 勾上,Is Kinematic 不勾,Interpolate 选Interpolate,Collision Detection 选Continuous。这样角色移动平滑,撞墙有物理反馈。

第二步,创建墙。新建Cube,缩放成墙的形状,挂BoxCollider(Cube默认自带)。墙不需要Rigidbody,作为静态碰撞体即可。

第三步,创建传送门。新建Cube,调整到门的大小,挂BoxCollider,勾选Is Trigger。传送门不需要Rigidbody,因为玩家有Rigidbody,满足"至少一方有刚体"的条件。

第四步,创建金币。新建Sphere,缩小,挂SphereCollider,勾选Is Trigger,Radius设为0.3左右(比视觉模型略大一点,方便拾取)。金币同样不需要Rigidbody。

这里有个关键点:金币的Trigger半径要比视觉模型大一圈。玩家操作有误差,视觉上"擦边"的时候应该能捡到,所以触发范围适当放宽是合理的体验优化。我一般设成视觉半径的1.2到1.5倍。

4.2 脚本编写:三个回调的完整实现

给玩家挂一个脚本,处理碰撞和触发:

using UnityEngine; public class PlayerInteraction : MonoBehaviour { private void OnCollisionEnter(Collision collision) { // 撞到墙等实体,可以播放撞击音效 Debug.Log($"撞到了: {collision.gameObject.name},接触点数量: {collision.contactCount}"); } private void OnTriggerEnter(Collider other) { if (other.CompareTag("Coin")) { Debug.Log("拾取金币"); Destroy(other.gameObject); } else if (other.CompareTag("Portal")) { Debug.Log("进入传送门"); // 传送逻辑 } } private void OnTriggerStay(Collider other) { if (other.CompareTag("DamageZone")) { // 持续伤害区域,每帧扣血 Debug.Log("受到持续伤害"); } } private void OnTriggerExit(Collider other) { if (other.CompareTag("Portal")) { Debug.Log("离开传送门"); } } }

几个要点说明:

OnCollisionEnter的参数是Collision,它包含接触点(contacts)、相对速度(relativeVelocity)、碰撞体信息(collider)。做撞击特效时用collision.contacts[0].point取接触点位置,用collision.relativeVelocity.magnitude判断撞击强度。

OnTriggerEnter的参数是Collider,只有对方碰撞体的信息,没有接触点。因为Trigger不做物理求解,自然没有接触点数据。需要接触点的话得自己算,或者改用Collision。

Tag判断是必须的。Trigger区域里可能进来各种东西,不判断Tag直接处理逻辑,很容易出bug。比如传送门区域里飞进来一颗子弹,不判断Tag就会把子弹也传送走。

4.3 高速子弹的命中判定方案

前面提到高速子弹用Collider会穿透,这里给一个完整方案。子弹用Trigger + Rigidbody + Continuous Dynamic:

using UnityEngine; public class Bullet : MonoBehaviour { public float speed = 50f; public float lifeTime = 2f; private void Start() { GetComponent<Rigidbody>().velocity = transform.forward * speed; Destroy(gameObject, lifeTime); } private void OnTriggerEnter(Collider other) { if (other.CompareTag("Enemy")) { Debug.Log($"命中敌人: {other.name}"); // 伤害逻辑 Destroy(gameObject); } else if (other.CompareTag("Wall")) { // 打到墙,销毁 Destroy(gameObject); } } }

子弹的Rigidbody配置:Mass 0.01,Use Gravity 关掉,Collision Detection 选Continuous Dynamic,Interpolate 选Interpolate。Trigger的Collider用SphereCollider,半径设小一点(0.1左右),减少误判。

如果子弹速度再快(比如100m/s以上),Continuous Dynamic也可能漏检。这时候改用射线检测更稳:

private void FixedUpdate() { float moveDistance = speed * Time.fixedDeltaTime; if (Physics.Raycast(transform.position, transform.forward, out RaycastHit hit, moveDistance)) { if (hit.collider.CompareTag("Enemy")) { Debug.Log($"射线命中: {hit.collider.name}"); } Destroy(gameObject); } else { transform.position += transform.forward * moveDistance; } }

射线检测的原理是"从当前位置向前发射一条长度为本帧位移的射线",只要射线碰到东西就算命中,不存在穿透问题。代价是射线检测不感知物理形状的厚度,只判断射线与碰撞体的交点,所以对薄片状目标反而更准。

4.4 触发区域的尺寸校准与可视化

Trigger的尺寸校准是个细致活。我的做法是:

  1. 在Scene视图里选中Trigger物体,Collider的绿色线框会显示出来
  2. 把视觉模型调成半透明(或者在Inspector里临时隐藏MeshRenderer)
  3. 对比绿色线框和视觉边界,用Collider的Center和Size参数微调
  4. 对于需要"提前感知"的区域(如敌人警戒范围),线框比视觉大20%到30%
  5. 对于需要"精确判定"的区域(如拾取),线框和视觉基本重合或略大

另外,给Trigger加一个调试用的Gizmo脚本,运行时也能看到范围:

using UnityEngine; public class TriggerGizmo : MonoBehaviour { private void OnDrawGizmos() { Gizmos.color = new Color(0, 1, 0, 0.3f); var box = GetComponent<BoxCollider>(); if (box != null) { Gizmos.matrix = transform.localToWorldMatrix; Gizmos.DrawCube(box.center, box.size); } } }

这个脚本在Scene视图里画一个半透明绿色方块,运行时也能看到,调尺寸的时候非常直观。

5. 常见问题排查与避坑实录

5.1 触发不生效的排查清单

OnTriggerEnter不执行,按这个顺序排查,九成问题能定位:

排查项检查方法常见错误
是否有Rigidbody看两个物体是否至少一方有Rigidbody两边都只有Collider
Is Trigger是否勾选看Collider组件忘了勾,走的是Collision
Layer矩阵Project Settings > Physics两个层之间没勾选
脚本挂载位置看脚本挂在哪个物体上挂在没有Rigidbody的物体上
Collider尺寸Scene视图看绿色线框尺寸太小,实际没重叠
物体是否激活看GameObject的active状态父物体被禁用
刚体isKinematic看Rigidbody设置两个都是kinematic,不触发

我遇到最多的两个坑:一是脚本挂错物体。OnTriggerEnter要挂在有Rigidbody的那个物体上,或者挂在Trigger物体上(如果Trigger物体有Rigidbody)。如果两边都没Rigidbody,脚本挂哪都没用。二是Layer矩阵。新建的Layer默认和所有层都勾选,但如果你手动改过矩阵,很容易漏掉某个组合。

5.2 碰撞穿透的三种成因与对策

穿透(tunneling)是高速物体常见问题,成因有三种:

成因一:Collision Detection模式不对。Discrete模式下,物理引擎只在每帧末尾检测一次位置,高速物体一帧跨过目标就漏了。对策:改成Continuous Dynamic。

成因二:目标碰撞体太薄。即使开了连续检测,如果目标厚度小于物理引擎的最小检测阈值(默认约0.01米),依然可能漏。对策:给薄物体加厚碰撞体,或者用射线检测。

成因三:Fixed Timestep太大。Project Settings > Time > Fixed Timestep默认0.02秒(50Hz),如果子弹速度是100m/s,每物理帧移动2米,很容易跨过薄目标。对策:把Fixed Timestep调到0.01或更小,代价是物理计算频率翻倍,性能开销增加。我的经验是0.0167(60Hz)是个平衡点,配合Continuous Dynamic基本够用。

5.3 OnTriggerStay的性能陷阱

OnTriggerStay是每物理帧都调用的,如果Trigger区域里有很多物体,或者Stay里做了复杂计算,性能会明显下降。我见过一个项目在OnTriggerStay里做射线检测和UI更新,帧率直接腰斩。

优化思路:能不用Stay就不用。持续伤害可以用计时器在Enter时启动、Exit时停止,而不是每帧在Stay里扣血。如果必须用Stay,把逻辑做轻量判断,重计算放到协程或定时器里。另外,Stay的调用频率跟Fixed Timestep绑定,调小Timestep会让Stay调用更频繁,这点要心里有数。

5.4 触发器与物理材质的配合

Trigger本身不参与物理求解,所以物理材质(Physic Material)对Trigger无效。但Collider的物理材质会影响碰撞行为:摩擦力(Dynamic Friction/Static Friction)决定物体在表面滑动的难易,弹性(Bounciness)决定反弹强度。

做冰面效果时,给地面Collider挂一个低摩擦的Physic Material;做弹跳球时,给球挂高Bounciness的材质。注意,物理材质只对Collider生效,Trigger上挂材质没有任何效果,别白费功夫。

5.5 触发器的嵌套与层级问题

一个常见需求是"Trigger里面再套Trigger",比如一个大的检测区域里包含多个小的交互点。这里要注意:子物体的Collider默认会合并到父物体的碰撞检测里(如果父物体有Rigidbody)。如果不想合并,给子物体单独挂Rigidbody并设isKinematic,或者调整层级结构。

另外,禁用父物体会导致子物体的Trigger全部失效。做UI面板或可开关的检测区域时,用SetActive(false)会连带禁用子物体上的所有Collider和脚本。如果只想临时关闭检测,应该禁用Collider组件而不是整个GameObject。

6. 进阶技巧:让碰撞触发系统更稳更快

6.1 用Physics.Overlap系列做主动检测

除了被动的回调,Unity还提供了主动查询API:Physics.OverlapSphere、Physics.OverlapBox、Physics.CheckSphere等。这些方法在调用时立即返回重叠的碰撞体列表,适合做"范围攻击""视野检测"这类需要即时结果的场景。

Collider[] hits = Physics.OverlapSphere(transform.position, 5f, LayerMask.GetMask("Enemy")); foreach (var hit in hits) { Debug.Log($"范围内敌人: {hit.name}"); }

注意第三个参数LayerMask,只检测指定层,能大幅减少返回结果数量。Overlap系列的开销跟场景里碰撞体总数相关,调用频率高的话建议加LayerMask过滤,或者用NonAlloc版本避免GC。

6.2 触发器事件与事件系统的解耦

项目大了之后,直接在OnTriggerEnter里写业务逻辑会导致脚本臃肿、耦合严重。我的做法是用C#事件或UnityEvent把触发事件抛出去,业务逻辑在别处订阅:

public class TriggerZone : MonoBehaviour { public event System.Action<Collider> OnEnter; public event System.Action<Collider> OnExit; private void OnTriggerEnter(Collider other) => OnEnter?.Invoke(other); private void OnTriggerExit(Collider other) => OnExit?.Invoke(other); }

这样Trigger区域只负责"感知",具体做什么由订阅方决定。同一个区域可以被多个系统复用,比如既触发剧情又触发音效,互不干扰。

6.3 碰撞层与查询层的分离配置

Unity的Layer矩阵控制的是"碰撞层"(哪些层之间发生物理交互),但射线检测和Overlap查询用的是"查询层"(通过LayerMask参数指定)。这两者是独立的:一个物体可以在碰撞矩阵里和某层不交互,但射线依然能检测到它。

利用这个特性可以做精细控制:比如敌人的碰撞体和玩家子弹不产生物理碰撞(避免子弹被弹开),但射线检测能命中敌人(用于瞄准辅助)。配置方法是把敌人放到Enemy层,子弹的Collider和Enemy层在矩阵里取消勾选,但射线检测的LayerMask包含Enemy层。

6.4 触发器在2D项目中的差异

如果做2D项目,用的是BoxCollider2D、CircleCollider2D等,回调是OnTriggerEnter2D,参数是Collider2D。2D物理(Box2D)和3D物理(PhysX)在触发检测上的逻辑基本一致,但有几个差异要注意:

  • 2D的Rigidbody2D有Body Type(Dynamic/Kinematic/Static),Static类型不参与触发检测
  • 2D的Layer矩阵在Physics2D设置里,和3D的分开配置
  • 2D的Trigger检测精度受Collider2D的Edge Radius影响,圆角边缘会影响触发范围

做2D平台游戏时,角色的地面检测通常用一个小BoxCollider2D做Trigger,配合OnTriggerStay判断是否着地。这个方案比射线检测更宽容,角色站在边缘时也能正确判定。

6.5 物理更新与渲染更新的时序问题

Unity的物理更新(FixedUpdate)和渲染更新(Update)是分开的,物理回调(OnCollision/OnTrigger)在FixedUpdate之后、Update之前执行。这意味着在OnTriggerEnter里修改Transform位置,可能会和渲染插值产生冲突,表现为物体"抖动"或"瞬移"。

解决方案:在触发回调里只记录状态,实际的位置修改放到Update或协程里做。或者给Rigidbody开Interpolate,让物理位置和渲染位置平滑过渡。我做过一个传送门项目,在OnTriggerEnter里直接改position会导致角色瞬移后画面撕裂,改成"标记待传送、下一帧执行"后就正常了。

7. 我踩过的几个真实坑

说几个印象深刻的。有一次做拾取系统,金币的Trigger死活不触发,排查了半天发现金币的Layer被设成了"Default",而玩家的检测脚本里LayerMask只包含了"Interactable"层,Overlap查询根本没扫到金币。这个问题的隐蔽之处在于:金币的Trigger本身是正常的,玩家走过去物理上确实重叠了,但脚本用的是主动查询而不是被动回调,查询的LayerMask漏了Default层。教训是:主动查询和被动回调的过滤条件要分开检查,别以为Trigger配好了就万事大吉。

还有一次做敌人警戒范围,用了一个大SphereTrigger,结果敌人一多,OnTriggerStay每帧调用几百次,帧率掉得厉害。后来改成在Enter时启动一个协程做周期性检测,Exit时停止协程,Stay回调直接删掉,性能立刻回来了。这个经验让我养成了一个习惯:OnTriggerStay能不用就不用,持续性的逻辑用计时器或协程替代。

最后一个关于MeshCollider的。给一个动态破碎的物体挂MeshCollider,勾了Convex,结果破碎后的小块形状复杂,Convex简化后碰撞体和视觉严重不符,碎片悬空或者穿地。后来改成每个碎片用BoxCollider近似,虽然精度低了点,但稳定性和性能都好得多。动态物体用简单碰撞体近似,这个原则在大多数项目里都成立。

Trigger的尺寸校准也值得多说一句。我现在的习惯是给所有Trigger加一个运行时可视化的调试开关,按一个键就显示所有Trigger的线框,调场景的时候一目了然。这个习惯帮我省掉了大量"为什么没触发"的排查时间——很多时候就是Trigger尺寸差了一点点,肉眼看不出来,线框一显示就清楚了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/26 6:33:42

程序员接私活全攻略:渠道选择与实战技巧

1. 程序员接私活的现状与挑战十年前我刚入行时&#xff0c;程序员想接私活基本只能靠熟人介绍或者本地小广告。现在随着互联网平台的发展&#xff0c;接私活的渠道已经丰富了很多&#xff0c;但同时也带来了新的问题。最近帮团队里几个年轻同事梳理私活渠道时&#xff0c;发现很…

作者头像 李华
网站建设 2026/10/26 6:33:24

磁编码器精度解析:噪声、有效分辨率与INL实战指南

简介&#xff1a;磁性角度编码器芯片是闭环控制系统中实现角度检测的关键传感器&#xff0c;常配合磁铁、磁环等磁路组件工作。文档内容面向电机控制、手持云台等应用开发者&#xff0c;系统梳理噪声、分辨率与积分非线性&#xff08;INL&#xff09;三项核心指标&#xff1a;从…

作者头像 李华
网站建设 2026/10/26 6:33:09

Zynq-7020核心板硬件启动链路原理图深度拆解

简介&#xff1a;这份资源为Xilinx Zynq-7020芯片开发板原理图&#xff0c;面向嵌入式系统、FPGA及硬件设计方向的工程师与学习者&#xff0c;可用于参考Zynq-7000平台的板级设计思路与接口电路实现。压缩包内共1个PDF文件&#xff0c;约417KB&#xff0c;以原理图图纸形式呈现…

作者头像 李华
网站建设 2026/10/26 6:32:32

基于计算机视觉的地下排水管道智能检测技术解析

1. 项目背景与核心价值地下排水管道作为城市基础设施的"血管"&#xff0c;其健康状态直接关系到城市防洪排涝能力和居民生活质量。传统管道检测主要依赖人工目视或CCTV摄像&#xff0c;不仅效率低下&#xff08;平均每人每天仅能检测1-2公里&#xff09;&#xff0c;…

作者头像 李华
网站建设 2026/10/26 6:32:18

USACO卡牌游戏策略:贪心算法与双指针实战

1. 题目背景与核心逻辑拆解P4816 [USACO15DEC] High Card Low Card G 是USACO竞赛中经典的卡牌策略问题。题目设定两名玩家&#xff08;Bessie和Elsie&#xff09;各有N张卡牌&#xff0c;每张牌有一个唯一数字。游戏进行2N轮&#xff0c;每轮双方各出一张牌比大小&#xff0c;…

作者头像 李华
网站建设 2026/10/26 6:32:04

Python+活体识别:电子遗嘱存证数据工程改造实践

遗嘱这类文件&#xff0c;牵扯的东西比普通合同重得多。人没了&#xff0c;财产怎么分&#xff0c;意愿怎么证明&#xff0c;每一环都容不得半点含糊。这几年电子存证平台越来越多&#xff0c;技术本身不是瓶颈&#xff0c;但有两个问题始终绕不开&#xff1a;一个是身份核验的…

作者头像 李华