Persistence (Papyrus)
Overview
Persistence is the act of making an Object Reference stick around in the game and not be unloaded. This applies to all references in the game, including things like actor references. Because they continue to stick around, they consume processor time and memory when other references in the same area will have disappeared and unloaded.
What makes objects persistent?
The following things keep an object around:
Functions
When a function is run on an object, the object will stick around until the function exits. This also includes long-running latent functions.
Examples
Function MyFunction()
; We have entered a function on this script - the object we are attached to is now persistent
Util.Wait(300) ; We now wait for 5 minutes - our object will still be persistent!
; Now as we leave the function we will no longer be persistent (unless someone else is keeping us alive)
EndFunction
Properties
When a script property is pointed at a reference in the editor, the target reference will be flagged as "permanently persistent". In other words, nothing you do during runtime will unload the object. This means that, if possible, you should not use properties to point at references directly. If you can, pull references in from events or other locations to avoid permanently keeping them around. Even if you reassign a value to your property while the game is running, the original reference will stick around.
Examples
; This property is set to something in the editor - it will load when the game does and stick around forever!
ObjectReference Property OtherReference auto
Function MyFunction()
; I may do things with OtherReference with the assurance that it will stick around
OtherReference.Activate(Game.GetPlayer())
; However, even if I clear or re-assign the property, the original object will stick around!
OtherReference = None ; Original object doesn't die!
EndFunction
Variables
When any variable in a currently loaded script points at a reference, that reference is temporarily persistent. It will stay persistent until no variables are pointing at it any more, at which point it will unload. (This assumes no other game system is keeping the object alive) This means that you should try not to have variables holding on to objects any longer then you need them. You can clear variables by assigning "None" to them.
Examples
ObjectReference myScriptVariable
Function MyFunction(ObjectReference myArg1, ObjectReference myArg2, ObjectReference myArg3)
; myArg1, myArg2, and myArg3 are persistent as long as this function is running
myArg1.Activate(myArg2)
; if I assign another object to one of them, the original object may disappear
myArg1 = None ; Original reference may die!
; if I assign one of them to a script variable, the object will stick around!
myScriptVariable = myArg2 ; Will now stick around until myScriptVariable is cleared or re-assigned
; myArg3 will stop being persistent as we leave the function as we didn't assign it to any other variables
EndFunction
Registered events
Any reference that is registered to receive various events will be persistent until it unregisters for the events. This applies to any event you explicitly register for which include (but are not limited to) OnUpdate, OnLOS, OnSleep, and OnAnimationEvent.
Examples
; The object we are attached to will now be persistant until we unregister
RegisterForUpdate(5.0)
; The object we are attached to will no longer be persistent (assuming no one else is keeping it alive)
UnregisterForUpdate()
Conclusion
So there are a few things to keep in mind when trying to keep things from sticking around too long:
- Avoid long-running functions
- Avoid properties to references if possible
- Variables to references should only be pointing at a reference for as long as they need to
- Only register for updates for as long as you need them