I have a simple dialogue system: dialogue manager and multiple scriptable objects which contain data for the respected dialogue piece (sentences, names, etc). Scriptable objects are fed to the dialogue manager which runs them and when all sentences are played in just ends the dialogue.
I need to somehow implement proper event system to drive the gameplay using dialogues. For example add/remove an object from the inventory, spawn something, change stats and many more.
As for now I have a very tedious implementation: each dialogue scriptable object have a string variable which contains a name of a function that needs to be executed. Then I use Invoke function to call the needed function. But it has some major flaws. First, I can only pass a very limited variety of arguments because of how Invoke works. Second, since scriptable objects can’t have references to the scene, I need to specific functions for almost each dialogue event
This kind of stuff is tough, because, as you’ve experienced, it requires referencing things ‘the wrong way’ in Unity.
Firstly, I would look at node editor tools like xNode for dialogue. Node data structures fit very well will dialogue systems, and you’d be hard pressed to make a versatile system without them. Though, in these same node structures, you can have nodes that perform events as well, and the flow of logic just executes these events. So you can make nodes for modifying inventories and just interleave these with the dialogue nodes.
As for ‘bridging the gap’, there are a number of ways to do this and I would go for the one that suits the scale and complexity of your game.
For example you can use an ID system, with a manager intermediary that provides references via these ID’s. You can have a component that registers these ID’s on Awake, and your nodes can try and find a reference via said ID’s. Naturally a reasonably amount of editor support is required to make this comfortable to edit.
You can avoid having to bridge the gap by moving more things out of the scene level too. For example, inventories can be scriptable objects. Thus inventory manipulation nodes only need to reference said scriptable object.
If it was a small scale project you could bake this data into the scenes itself, thus referencing scene objects is no longer a problem. Again would require plenty of editor work, and imposes its own restrictions.
i looked at node-based solutions, but they were an overkill for my needs (my dialogues are linear, the max branching you’d get is different lines depending on relationship). Plus none of them had some specific feature that I needed. I barely figured out how to code it myself to work with my localization system.
I thought about converting scriptable object to a component script and attaching it multiple times for each dialogue on some gameobject, but hesitated to to it this way. Now considering the small scale of my project it seems to be the way of least resistance
Not wrong. No need to design an elaborate system if your project is on the small side.
Though as mentioned it won’t hurt to develop some editor tools for this nonetheless. Rather than a series of components, you could just bake all the information as pure C# data into the one component (this is where SerializeReference’s polymorphic serialisation will be useful). Then said component may just have a button that can open an editor window that lets you add/remove and manipulate the event and dialogue steps.