Unity使用IL2CPP打包移动端时Collider2D检测失效异常求助
IL2CPP打包后Physics2D.OverlapPoint无法检测特定碰撞体的异常问题
场景说明
- 场景内存在多个名为
BlockRoot的2D对象,层级设置为Block - 父对象仅挂载
BoxCollider2D组件,子对象通过SpriteRenderer渲染图像 - 触摸点击逻辑通过
Physics2D.OverlapPoint检测碰撞体,获取挂载的Block脚本并触发DeleteByPlayer()方法
核心代码
public void UpdateState(TetrisStateMachine stateMachine) { if (Input.touchCount > 0) { Touch touch = Input.GetTouch(0); if (touch.phase == TouchPhase.Began) { int layerMask = LayerMask.GetMask("Block"); Vector2 mousePosition = Camera.ScreenToWorldPoint(touch.position); Collider2D hitCollider = Physics2D.OverlapPoint(mousePosition, layerMask); Log.Info("Touch Start "+ mousePosition + " , "+ layerMask); if (hitCollider != null) { Log.Info("Touch hitCollider "+ hitCollider.name); Block block = hitCollider.GetComponent<Block>(); if (block != null) { block.DeleteByPlayer(); } else { Log.Info("Touch no Block"); } } else { Log.Info("Touch no hitCollider"); } } } }
异常现象
- 在Unity编辑器、Mono打包的APK中,触摸点击
BlockRoot对象可正常触发block.DeleteByPlayer()逻辑 - 使用IL2CPP打包APK时,无法检测到碰撞体,日志输出
Touch no hitCollider
测试验证
- 添加一个新的、挂载
BoxCollider2D且层级为Block的2D正方形对象后,IL2CPP打包的APK可正常点击原BlockRoot和新增对象 - 删除该测试对象,再次用IL2CPP打包后,原
BlockRoot又无法被点击,日志仍显示Touch no hitCollider
原因分析
这是IL2CPP的代码裁剪(Linker)优化导致的问题:
- IL2CPP打包时会自动裁剪未被直接引用的代码或组件类型。当场景中只有
BlockRoot这类父对象仅挂载BoxCollider2D、且Block脚本未被其他代码直接显式引用时,IL2CPP可能误判BoxCollider2D属于未被使用的类型,或裁剪了与碰撞检测相关的依赖逻辑 - 新增测试对象后,相当于强制保留了
BoxCollider2D和Block层的碰撞检测逻辑,避免了被裁剪
解决方案
- 添加Linker保留规则:在项目
Assets目录下创建link.xml文件,添加以下内容强制保留相关类型:
<linker> <assembly fullname="UnityEngine"> <type fullname="UnityEngine.BoxCollider2D" preserve="all"/> </assembly> <assembly fullname="[你的程序集名称]"> <!-- 替换为包含Block脚本的程序集名 --> <type fullname="Block" preserve="all"/> </assembly> </linker>
- 显式引用Block脚本:在其他初始化逻辑中添加对
Block类型的直接引用(比如var temp = typeof(Block);),避免被裁剪 - 调低IL2CPP优化等级:在PlayerSettings中,将IL2CPP的优化等级从"High"改为"Medium"或"Low",验证是否为裁剪问题
内容的提问来源于stack exchange,提问作者Jean
相关产品推荐
相关产品推荐

