Persistence (Papyrus)

From the Fallout4 CreationKit Wiki
Revision as of 13:56, 10 August 2016 by imported>Misfit (→‎Registered events)
Jump to navigation Jump to search

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, OnGainLOS, 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()

Seeing Why Something is Persistent

If an object is persistent due to Papyrus, you can use the console command DumpPapyrusPersistenceInfo to print out everything holding onto the object to the script log.

Note that this command only knows about Papyrus and will be unable to tell you if something else is keeping the object persistent (like being in an alias).

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