/// <summary> /// Called before we return to the engine, after all work has been /// finished. This function runs down objects marked for pending /// deletion (ensuring timely handling in cases where the deleted half /// of the object was explicitly detected). /// </summary> public void ProcessPendingDeletions() { if (ObjectsToDelete.Count == 0) { return; } foreach (GameObject ObjectToRundown in ObjectsToDelete) { try { ObjectToRundown.OnRundown(); } catch (Exception e) { Script.WriteTimestampedLogEntry(String.Format( "GameObject.ProcessPendingDeletions(): Exception {0} running rundown for object {1} of type {2}.", e, ObjectToRundown.ObjectId, ObjectToRundown.ObjectType)); } } // // Now that we have ran through the object to delete list, clear it // out (the last reference that the underlying object system has to // these object ids). // ObjectsToDelete.Clear(); }
/// <summary> /// Periodically run as a DelayCommand continuation in order to scan /// the object table for objects whose engine parts have been deleted. /// /// Any such objects found are removed. /// /// It is necessary to periodically poll for deleted objects because /// not all object types provide script events that signify deletion. /// </summary> private void GarbageCollectObjects() { // // Scan the object table looking for objects that have had their // engine side counterpart deleted. Add these to the object to // delete list, but don't mark them as in rundown. This allows us // to differentiate between which objects were still in the // dictionary during the subsequent rundown loop (so that we can // remove them then, as we can't modify the dictionary during the // enumeration). // foreach (var Entry in GameObjectTable) { if (Script.GetIsObjectValid(Entry.Key) != CLRScriptBase.FALSE) { continue; } ObjectsToDelete.Add(Entry.Value); } // // For every object that is scheduled for rundown, call the // OnRundown notification and remove the object from the deletion // list. If the object was one we moved above, remove it from the // lookup table too (otherwise it was already removed from the // lookup table ahead of time). // foreach (GameObject ObjectToRundown in ObjectsToDelete) { if (ObjectToRundown.IsRundown == false) { GameObjectTable.Remove(ObjectToRundown.ObjectId); } try { ObjectToRundown.OnRundown(); } catch (Exception e) { Script.WriteTimestampedLogEntry(String.Format( "GameObject.GarbageCollectObjects(): Exception {0} running rundown for object {1} of type {2}.", e, ObjectToRundown.ObjectId, ObjectToRundown.ObjectType)); } } // // Now that we have ran through the object to delete list, clear it // out (the last reference that the underlying object system has to // these object ids). // ObjectsToDelete.Clear(); // // Schedule the next garbage collection. // Script.DelayCommand(60.0f, delegate() { GarbageCollectObjects(); }); }