-
Notifications
You must be signed in to change notification settings - Fork 8
Understanding Forms, Object References, Reference Aliases, and Persistence
A Form is a base type. Every single object that you see in the Object Window is a Form, including actors, spells, keywords, etc. In the game, these Forms are instantiated into ObjectReferences, which are subclasses of Form. An ObjectReference is simply a Form that has been loaded into memory. Because an ObjectReference exists only in memory, it is temporary. A specific ObjectReference and all of its details (AI packages, script properties, etc.) are not stored in a save file. Instead, nothing but the base Form of each temporary ObjectReference is stored in the save file, and then when the game is loaded, a new ObjectReference is created for each mention of each Form in the save file. That new ObjectReference will start off with a clean slate, without any of the modifications that may have taken place before the game was saved/loaded. This is great for memory management. Nothing sticks in memory too long. However, it's bad if you need to uniquely identify objects so that you can store information specific to each object and maintain that information between saves. For this, you'll need to make the ObjectReference persistent.
An object can be manipulated only while it's in memory. Objects are loaded into memory selectively for performance. It would be ridiculous if the entire game (All locations, dungeons, players, items, spells, visual effects, etc.) were in memory at the same time. No video game can operate like that. Most objects in the game are non-persistent. That is, objects are loaded into memory when you enter the cell that contains them. They are thrown out of memory when they are consumed, deleted, or the player moves out of that cell. A persistent object, on the other hand, will be thrown out of memory only when it is deleted or consumed. It will remain in memory even when the player moves to a different cell that doesn't contain that object.
There are two main ways to make an ObjectReference persistent:
- Create the
ObjectReferenceusing thePlaceAtMefunction and pass in true for its last parameter. This will return anObjectReferencejust like any other, but it will be forced to be persistent. - Fill a
ReferenceAliaswith theObjectReferenceyou want to become persistent. Think of aReferenceAliaslike a blanket. AReferenceAliasis attached on top of an existingObjectReferenceand it allows you to add scripts, AI packages, keywords, and other objects onto thatObjectReference. It's like editing the values of an object at runtime.ReferenceAliases can be cleared, thus disassociating them with theirObjectReference. This removes everything that was added by theReferenceAliasand leaves the originalObjectReferenceuntouched. While anObjectReferenceis filled in aReferenceAlias, thatObjectReferenceis persistent.ReferenceAliasesare created by filling Quest Aliases. Learn how to fill Quest Alises by learning more about the Story Manager. See also Quests. A filledReferenceAliaswill remain persistent for as long as itsQuestis running.
A persistent ObjectReference will have a unique ID that you can access with myObjectReference.GetFormID(). GetFormID is a function of the Form script, but when called on an ObjectReference, it returns the ID of that ObjectReference rather than its base form's ID.
Once you've made an ObjectReference persistent in one of the above two ways, you can rely on it being in memory, having the same unique ID, and maintaining all of its state information until you explicitly destroy it:
ObjectReference myObjectReference ; Some ObjectRefrence from anywhere
myObjectReference.Delete()
myObjectReference = None- When an item is destroyed, such as when a soul gem is removed from the player's inventory as its used up at the enchanting workbench, there will be an
OnItemRemovedevent sent to thePlayer. AlthoughObjectReference akItemReferenceis one of the parameters ofOnItemRemoved, it was alwaysNonein my tests with destroying soul gems at the enchanting table. Although it will always pass in the base form that was removed, there were times when it told me the base form that was removed, but it didn't tell me exactly whichObjectReferencewas removed. This makes it less useful for testing when a persistent object you're tracking is destroyed.