報錯:
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
里的復用邏輯,讓物理組件恢復正常再上場,你要我直接幫你改那部分代碼嗎?這樣可以根治這個報錯。