Alright then, seems like I need to explain the whole thing. I've simplyfied my question above as I wanted to avoid writing horribly complex one and save you from reading a freaking novel and rather concentrate on the core of my issue, but your answer indicates I pretty much understand things from the API in a wrong way.
What I am trying to do:
I'm creating a global variables system - system that stores certain acomplishments in a game a allows other systems, such as dialogue system, to react accordingly.
Since I am a big fan of Scriptable Object-based architecture in Unity, I use a scriptable object called Globals, which contains an array of global variables. Single global variable itself is a scriptable object as well, so the array in Globals is an array of assets of type Global (maybe I should rename Global class to avoid confusing?).
For better understanding, this is how it looks.
Global (single global variable) scriptable object looks like this:
I have written a custom saver (based on your Saving system) to save a state of all these Global scriptable objects in Globals array so that they can be reloaded to the state they were saved in at any given time, and it works quite well now (was a though nut to crack as an array of scriptable objects can't be serialized so that it will serialize along with all their properties, but the workaround of copying this array into list of structs containing analogic fields, serializing it and after deserialization, copying each struct content into its respective counterpart in Global scriptable object seems to work alright).
The problematic part begins with linking these globals into Dialogue System. I have written a wrapper method what basically takes a Global variable scriptable object, takes its name and value properties and send them to the Dialogue System liek this:
Code: Select all
public void InsertGlobalVariableIntoDialogue(string name, string value, FieldType type)
{
var database = GameObject.Find("Dialogue Manager").GetComponent<DialogueSystemController>().initialDatabase;
var template = Template.FromDefault();
var variableID = template.GetNextVariableID(database);
var variable = template.CreateVariable(variableID, name, value, type);
bool add = true;
foreach (Variable dialogueVariable in database.variables)
{
if (dialogueVariable.Name == name)
{
add = false;
if (type == FieldType.Text)
{
if (dialogueVariable.InitialValue != value)
{
dialogueVariable.InitialValue = value;
}
}
if (type == FieldType.Boolean)
{
if (dialogueVariable.InitialBoolValue != ToBool(value))
{
dialogueVariable.InitialBoolValue = ToBool(value);
}
}
if (type == FieldType.Number)
{
if (dialogueVariable.InitialFloatValue.ToString() != value)
{
dialogueVariable.InitialFloatValue = float.Parse(value);
}
}
}
}
if (add)
{
database.variables.Add(variable);
}
}
Condition
Code: Select all
if (dialogueVariable.Name == name)
checks whether the variable already is present in Dialogue System variables, and if so, checks whether its value is different or not. If it is, it passes a new value from the scriptable object.
Then, there is an iterative method going through all Global variables and inserting them accordingly:
Code: Select all
foreach (Global variable in globals) {
InsertGlobalVariableIntoDialogue(variable.name, variable.value, FieldType.Text);
}
Note that
is the above mentioned array of Global scriptable objects (array displayed in picture No.1 above).
It seemed to do what it is supposed to do - after running this code, Dialogue System Variables tab shows exactly what it should:
Now, as I've mentioned before, I use a condition in this small dialogue tree:
to determine what line it should choose. Condition is as simple as:
Code: Select all
Variable["13_PCKnowsSantiago"] == "false"
or true respectivelly for the case our dear Mr. Santiago knows player character already. Also note that I use string variable type, it's much more flexible for other types of global variables (such as NPC attitude - say, negative, neutral, positive or similarily so), but of course, much more vulnerable to mistypes.
To actually change a variable after certain conversation line happens, I do not use any Lua code in Script field, as that would require to write a sort of unwrapper method that would pull changes variables from Dialogue System variables back into my code. I have tried to do so, although it did not work at all. And as you explained in your response above, I guess I can see why,
I instead use On Enable() event, in which I simply call a public method on Global scriptable object to set itself to certain value, like this:
Yes, this does not change a variable value inside Dialogue System. But I don't even have to do that. I don't need to use it anywhere else, I don't actually need any Global variable change to be present inside it in one converstion cycle, they always determine only one condition in one conversation.
So how do I expect to this value change to take effect then? Well, since this changed value is written to the scriptable object, I simply re-run wrapper(or let's call it sync)code showed above on every conversation start and end (well, even start alone would be enough). And it works. Only problem is, it does not take any effect during one runtime seasson. When the variable is set to true, it is synchronized with Dialogue System variables upon conversation ending and/or starting it again. It does take effect when the runtime is stopped and lanuched again,but it does not work in one runtime seasson.
It's really breaking for me to find out Variable tab does not show and actual state of these varables (as I've been relying on it all the time
). But it's my fault, I guess "Initial value" field name in Variables tab is quite explicit about what this field actually shows.
I recon all of my several-days-long attempt is quite wrongly performed.
Please, do you have any suggestion on how to approach on what I am trying to achieve? Either using any of above mentioned techniques or completely new approach.
Thank you very much for your help by the way.