- Home /
Large scale progress / event System - How to approach?,Large scale progress / Event System - How to approach?
Hi!,
I'm currently building a generic Progress System to track all that the player has done through multiple scenes and objects. I have an Event Manager and multiple Interactable Objects that upon interaction register a new Event.
Imagine that we have two different scenes with an NPC each. I can only speak to the NPC in scene 2 if I finish the conversation with the NPC in scene 1. What is the best way to do this?
Currently what I am doing is, when registering an event, saving also the Scene and Name of the object that I interacted with, and then when loading Scene2 I check if the object in Scene1 and with name X was interacted with, and hence unlock the conversation with the new NPC.
For one hand, for a large scale game, it seems that one needs to manually write all the unlocks and dependencies, so I can't use a 'randomly generated unique ID', or something of the sorts. But using something so volatile such as Scene or Object name doesn't seem ideal also. Is there any better solution? What am I missing? :)
Thank you so much ;)
Answer by oscarAbraham · Nov 03, 2021 at 10:37 PM
I don't know if I should dare to make suggestions about architecture or scalability, because those matters are a bit subjective, and they depend a lot on the specific project and the people behind it. I don't know what you're missing because I don't know the whole thing. I'm tempted to suggest that you could associate more than a boolean with each name/key; you could have a whole Global Blackboard to save all sorts of values as JSON, but it's possible it doesn't fit your game.
That said, if you want something less volatile, maybe you could use a string field in a component as the Key to the object's data? That could be less volatile than Object/Scene names, because it wouldn't be used for anything else. It would also allow you to separate GameObjects from your global data so, for example, multiple characters from multiple scenes can easily check if something has been interacted with.
A level up of that idea could be to use empty ScriptableObjects with their name as keys and store them all in the same folder or as subassets. That way, you'd avoid the risk of duplicate keys and you could use the Inspector's Object Picker to them. I'd advice against storing the data directly in the ScriptableObjects, though, because SOs don't reset after exiting PlayMode, and they don't get any callbacks you can use to reset them when entering PlayMode if Domain Reloading is disabled. Also, storing your data in a dedicated manager allows you to easily save/load the whole game data.
Another nice thing about using SOs as keys is that you can see all the different keys that your game uses in the same place, while also being able to right -> Find Reference In Scene, or even the new Dependency Viewer to know where they are being used.
@oscarAbraham , thank you so much for your answer!
Actually I save a wide array of values for each object to a global system that will eventually serialize them, so the storage and persistency of data seems to be working nicely.
Using a custom string as a unique ID for the object's data seems like a much better approach than using the object/scene. Something about what I understood about Scriptable Objects seems really tempting, but I'm not sure I comprehended it completely. You are suggesting that an object's unique ID is an empty ScriptableObject (where I'd then take it's name as the actual key), correct?
Also, I don't know if you have much experience with this, but do you think that the dependencies (A unlocks if B of a different object/scene happens) are more manageable if stored globally or locally? By globally I mean writing them all in a SO read by a global manager, and locally I mean adding them manually or via an SO as a component of the object whose state I want to unlock.