/// <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(); });
        }
 /// <summary>
 /// Remove an object from the game object table.
 /// </summary>
 /// <param name="Obj">Supplies the object to remove.</param>
 public void RemoveGameObject(GameObject Obj)
 {
     GameObjectTable.Remove(Obj.ObjectId);
     ObjectsToDelete.Add(Obj);
 }