Difference between revisions of "Persistent References"
(One intermediate revision by the same user not shown) | |||
Line 105: | Line 105: | ||
== When should you use Persistent References? == | == When should you use Persistent References? == | ||
For what we've said above, it's pretty clear that Persistent References would cover the case where you may want to edit an AI State even if the Player has never met the AI in the first place. So if your quest requires that, you should go ahead and make it a Persistent Reference. | |||
''Note: even this case could be covered with non-persistent AI, for example, you could have different version of the same NPC and spawn them in base of what you need to do, but it's probably not worth the hassle.'' | |||
The Looting Point example above is another good example of Persistent Reference usage, and also the [[mutable]] used for the demo (''Mutable_TheyShallFall_FireAndSmoke).'' | |||
A case where you absolutely need Persistent References is when you need to have AI that exists regardless of the player and that are '''not confined to a Cell''', like the Wanderer Merchant example. Without the Persistent References, the AI would not walk its path unless the Player is close to it. | |||
Persistent References are great, if you've had the impression that I'm somewhat against them, I'm not. There is obviously a cost in making a reference persistent, but unless you abuse them, it will not be noticeable. |
Latest revision as of 23:21, 25 August 2023
Persistent References are a special kind of GameObjects in the RCK that are always loaded and present while the game is running.
Generally, a GameObject such as an AI, a chest or an item in world exists in a scene, such as an Interior cell, and is accessible only if that Interior cell is loaded. This can be the intended behavior for many situations, but there are others where you may want to access or modify GameObjects that are not in a loaded cell.
This is where Persistent References take place, they are GameObject present in the _PersistentReferences_ scene - which is always loaded, therefore every object inside the _PersistentReferences_ scene will always be present while the game is running.
You can easily access the _PersistentReferences_ scene by loading the _WorldLoader_ in the Cell View via the button.
Types of Persistent References
There are several types of Persistent References defined for the purposes of the RPG Creation Kit, but it is important to notice that you can at anytime add new objects and they will effetely be Persistent References, although you may have to define a way of quickly accessing them.
- AI: Defines a special kind of AI which is a Persistent Referenced AI.
- AIPaths: Contains AI Paths mainly used by Persistent Referenced AI.
- LootingPoint: Contains LootingPoints that for a need have to be Persistent Referenced.
- Door: Contains special kinds of Doors that needs to be accessible anytime, for example even when the AI that wants to use it is far away from the Door's transform.
- Other: You can insert your own kind of PRefs in here.
- Unregistered: If for a reason a Persistent Reference happens to be unregistered, it will be a child of this game object.
- Quest Markers: contains the persistent positions of the locations that the compass have to point to while doing a quest.
- QUEST_RELATED: Contains persistent references to Quest Related objects, such as the fire particles that is used in the City during the quest "They Shall Fall".
Creating a New Persistent Reference - Looting Point
In this section, we are going to create a new Persistent Reference to see how they are composed and why you may want to use them.
Here we are going to create a persistent Looting Point, the process is pretty much the same for any other references except for the AI, for creating an AI Persistent Reference, refer to this tutorial: Creating a New Persistent Reference AI
If you don't know how Looting Points work, read this first.
Let's load up the _WorldLoader_ in the Cell View via the button and let's focus on the _PersistentReferences_ scene.
Drag and drop a Looting Point prefab such as "ClosedChestLootingPoint_Prefab" from the Project Window to the LootingPoint GameObject in the Persistent References scene. Next, in the "Looting Point" component, let's set a unique ID and Name, I'll set mine to:
ID: MyPersistentChest001
Name: Persistent Chest
Next up, you may want to place it somewhere. I'm going to place it in the exterior worldspace, near the shack in the cell "Virrihael (0, -2)". Doing it from the _WorldLoader_ scene alone may be a bit complex, because there is nothing in there. What you can do is to quickly load the said cell additively in the Cell View.
Just with that you have a working Looting Point that always exists while the game is running, but currently we do not have a way to quickly access it, for example from a script.
Registering the Persistent Reference
To complete the creation of the Persistent Reference we need to do two things:
1) Add a "Persistent Reference" component to the Looting Point and set it up:
- Show Handle always shows the cyan RefID in the Editor, so that you can quickly see it.
- Ref ID: is the UNIQUE ID that we will use to access this reference. I've used "PREF_MyPersistentChest001".
- Is Loaded: is a flag that states whether this Persistent Reference is loaded or not, for Looting Points it should always be true.
- Type: the Type of the Persistent Reference.
2) Register the Persistent Reference - in the _PersistentReferences_ scene the root GameObject "PersistentReferences" contains a component called "PersistentReferenceManager": We need to register our new Persistent Reference there.
To do so, click on the + button in the "Refs" dictionary, type the same RefID of the Persistent Reference you've set earlier (mine is PREF_MyPersistentChest001) and drag and drop the Looting Point object to the Persistent Reference field.
GIF, click on the image to view it.
Make sure to save the scene, you now have successfully created a new Persistent Reference.
Accessing the Persistent Reference
Now that we have a Persistent Referenced Looting Point, we might as well use it for something. What I will do is the following:
The looting point will start empty by default, when a new character is created, if it is a male, the chest will contain a sword, if it is a female, the chest will contain 100 golds.
This is a pretty good use of the Persistent References, because when the Player creates a new character the chest will always be unloaded (it is too far away), so how could we add new items to the chest if it is not loaded? Now that the chest is a Persistent Reference, we can.
We know that when the game starts for the first time the QuestStage script "JustAnotherDeliverStage10QuestScript" runs, so it is the perfect candidate to our edit.
After setting the Equipment, we can access our persistent reference by its RefID (PREF_MyPersistentChest001), check our gender and call the AddItem() method to add an item to the LootingPoint:
You can download the edited script here.
This should put in perspective the power of the Persistent References, once a reference has been created, you can have complete access over it and do whatever you want with it.
Persistent References vs SaveFile Edits
For what we discussed so far, it seems like almost everything should be a Persistent Reference. In reality, you may have noticed that there are very few of them for the whole demo, and none for the AI (except from the WandererMerchant001 example).
While designing the RPG Creation Kit, I envisioned a mess of Persistent References that would definitely hit not only the performances of the game, but also the efficiency and development time of the toolset itself.
For that reason, most of the times you can edit non-loaded objects even if they are not persistent. You can do this thanks to the SaveFile.
Generally speaking, every time the Player meets or interacts with something (meets an AI or interacts with a Looting Point), the state of that object is saved. When an Object such as a Door, a LootingPoint or an AI is fully-loaded (means the player is near to it), the first thing that happens is that the Object will look in the SaveFile for existing data about its state. If this data exists, the Object will be loaded from the saved state, otherwise it will stay at its default state.
That means if we edit the SaveFile the next time an Object is loaded its state will reflect our change. This is how edits to non-loaded objects are made throughout the Demo, and it is the approach that I do recommend.
For example, when you play the Demo and speak to the King, his Dialogue Graph changes in base of the actions you take, and these changes are made while the King is clearly not loaded.
However, there is an edge-case that regards the physical existence of the data in the save file that refers the object we want to edit. If we want to unlock a door we've never interacted with, that door does not exist in the SaveFile, therefore there is nothing for us to edit.
Luckily, a Door is a simple Object and its saved state is represented by few variables, mainly "DoorID and IsLocked" therefore creating the data to edit the door state is pretty convenient. This is what happens in the RCKFunctions method "UnlockDoor()".
Unfortunately, returning to the King example, the state of an AI is not simple at all, and there isn't a simple way to create from any point of the game the saved state of an AI while retaining the default settings you've set for it. Therefore, it is not possible to edit an AI state if the player hasn't meet it before.
And this brings us to a question:
When should you use Persistent References?
For what we've said above, it's pretty clear that Persistent References would cover the case where you may want to edit an AI State even if the Player has never met the AI in the first place. So if your quest requires that, you should go ahead and make it a Persistent Reference.
Note: even this case could be covered with non-persistent AI, for example, you could have different version of the same NPC and spawn them in base of what you need to do, but it's probably not worth the hassle.
The Looting Point example above is another good example of Persistent Reference usage, and also the mutable used for the demo (Mutable_TheyShallFall_FireAndSmoke).
A case where you absolutely need Persistent References is when you need to have AI that exists regardless of the player and that are not confined to a Cell, like the Wanderer Merchant example. Without the Persistent References, the AI would not walk its path unless the Player is close to it.
Persistent References are great, if you've had the impression that I'm somewhat against them, I'm not. There is obviously a cost in making a reference persistent, but unless you abuse them, it will not be noticeable.