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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 21:02:40