报错:
Uncaught TypeError: Cannot read properties of null (reading 'SetActive') at b2RigidBody2D.setActive (rigid-body.ts:231:21) at b2RigidBody2D.onEnable (rigid-body.ts:78:14) at RigidBody2D.onEnable (rigid-body-2d.ts:551:24) at OneOffInvoker.invokeOnEnable [as _invoke] (component-scheduler.ts:332:18) at OneOffInvoker.invoke (component-scheduler.ts:162:14) at NodeActivator.activateNode (node-activator.ts:163:31) at Node._onHierarchyChangedBase (node.ts:1371:46) at Node._onHierarchyChanged (node.ts:1878:14) at Node.setParent (node.ts:509:14) at PoolManager.getNode (PoolManager.ts:45:14)
主要需要关闭预制体组件的默认勾选:
你这个报错
javascript
复制编辑
Uncaught TypeError: Cannot read properties of null (reading 'SetActive')
是在 Cocos Creator 物理系统(RigidBody2D)里发生的,意思是它在调用 SetActive()
时,底层 Box2D 物理对象还没创建好(null
),或者已经被销毁。
结合报错栈
复制编辑
b2RigidBody2D.setActive → b2RigidBody2D.onEnable → RigidBody2D.onEnable
可以推断出问题发生在**节点刚被激活(onEnable)**时,RigidBody2D
尝试操作物理对象,但它引用的底层 b2Body
是 null
。
常见触发原因
节点被放回对象池后,RigidBody2D 组件没被重置
如果你用
PoolManager.getNode
取节点时直接node.setParent(...)
激活它,RigidBody2D
会立刻执行onEnable()
,但这时物理世界还没准备好它的 body。
物理世界已销毁,节点还在激活
例如场景切换或物理系统关闭后又激活节点。
RigidBody2D 组件被禁用/启用的时机不对
在还没加到物理世界就手动调用了
setActive()
。
解决思路
方案 1:对象池复用时重置物理组件
当从池里取出节点时,先禁用再启用 RigidBody2D
,保证重新注册到底层物理世界:
ts
复制编辑
import { RigidBody2D } from 'cc'; const node = this.poolManager.getNode(this.prefab, parent); const rigid = node.getComponent(RigidBody2D); if (rigid) { rigid.enabled = false; rigid.enabled = true; // 强制重新创建底层 b2Body }
方案 2:取出节点前先放到物理世界
如果你的 PoolManager.getNode
是这样写的:
ts
复制编辑
node.setParent(parent);
改成:
ts
复制编辑
parent.addChild(node); // 确保物理系统能感知节点层级变化
并且确保 parent 节点已经在物理世界中激活。
方案 3:避免 onEnable 时调用 setActive
如果你在 onEnable
或构造逻辑里手动调用了:
ts
复制编辑
rigidBody.setActive(true);
改为延迟一帧再调用:
ts
复制编辑
this.scheduleOnce(() => { rigidBody.setActive(true); }, 0);
这样可以等物理系统初始化完成。
方案 4:彻底销毁再创建
如果不需要复用节点,直接 node.destroy()
,重新 instantiate(prefab)
,就不会有旧的 b2Body
残留。
我怀疑你现在的 PoolManager.getNode
是直接 setParent 导致 RigidBody2D.onEnable()
调用太早。
我可以帮你改 PoolManager.ts
里的复用逻辑,让物理组件恢复正常再上场,你要我直接帮你改那部分代码吗?这样可以根治这个报错。