using System.Collections; using System.Collections.Generic; using System.Timers; using UnityEngine; using System.Diagnostics; public class testdestroy : MonoBehaviour { GameObject cubeGo; Transform rootTrans; // Use this for initialization Stopwatch timer; void Start () { cubeGo = GameObject.Find("Cube"); rootTrans = GameObject.Find("root").transform; timer = new Stopwatch(); } // Update is called once per frame void Update () { if (Input.GetKey(KeyCode.LeftControl)) { var go = Instantiate(cubeGo); go.transform.SetParent(rootTrans); } else if (Input.GetKey(KeyCode.A)) {//11111111111 for (int i = 0; i < rootTrans.GetChildCount(); ++i) { timer.Reset(); timer.Start(); Destroy(rootTrans.GetChild(i).gameObject); timer.Stop(); UnityEngine.Debug.Log("1:time elipsed===:" + timer.Elapsed); } rootTrans.DetachChildren(); } else if (Input.GetKey(KeyCode.D)) {//2222222222 while (true) { var cc = rootTrans.childCount; //UnityEngine.Debug.Log("cc============================" + cc); if (cc == 0) break; timer.Reset(); timer.Start(); DestroyImmediate(rootTrans.GetChild(0).gameObject); timer.Stop(); UnityEngine.Debug.Log("2:time elipsed===:" + timer.Elapsed); } } else if (Input.GetKey(KeyCode.F)) { DestroyImmediate(cubeGo.transform); } } }
1,DestroyImmediate立即銷毀目標,並將目標置為null,且將目標的所有上層引用置空,如用DestroyImmediate銷毀OBJ下的所子物體后 OBJ.childcount將變為0,見代碼//22222222222
2,Destroy則在本幀結束前,渲染之前銷毀目標和上層引用。不會立即銷毀,Destroy調用后,目標數據仍然存在,不為null,上層引用也正常。見代碼//111111111處,因為銷毀物體后,childcount
仍然保持不變,這常會造成其它地方的邏輯出錯,子結點已經銷毀了卻還能取到,因此,我們應該將子結點從父物體摘除,rootTrans.DetachChildren();這樣其它地方代碼再獲取子結點及其數量時就不導致邏輯出錯了。
3,基於上述原理,測試Destroy和DestroyImmediate的時間占用,發現后者幾乎是前者的10倍。
補充:
void Start () { var root = gameObject.transform; for (var i = 0; i < root.childCount; ++i) {//方式一,正確刪除所有子結點 var c = root.GetChild(i).gameObject; GameObject.Destroy(c); } for (var i = 0; i < root.childCount; ++i) {//方式二,刪不干凈,會有一些剩余節點 var c = root.GetChild(0).gameObject; GameObject.DestroyImmediate(c); } for (var i = 0; i < root.childCount; ++i) {//方式三,刪不干凈,會有一些剩余節點,只刪除了偶數節點0,2,4,6,剩余奇數節點1,3,5,7 var c = root.GetChild(i).gameObject; GameObject.DestroyImmediate(c); } while (root.childCount > 0) {//方式四,正確刪除所有子結點 var c = root.GetChild(0).gameObject; GameObject.DestroyImmediate(c); }
for (int i = go.childCount - 1; i >= 0; i--) {//方式五,正確刪除所有子結點
GameObject.DestroyImmediate(go.GetChild (i).gameObject);
}
}
