[HOWTO] How To: Connect C# Variables to Dialogue System's Lua

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
User avatar
Tony Li
Posts: 22124
Joined: Thu Jul 18, 2013 1:27 pm

[HOWTO] How To: Connect C# Variables to Dialogue System's Lua

Post by Tony Li »

You can define Dialogue System variables in the Dialogue Editor's Variables section. At runtime, these Dialogue System variables will be accessible in the Dialogue System's Lua environment. You can also access them in your own C# code using the DialogueLua class.

However, sometimes you might want to the other way -- define variables in your C# code and make those C# variables accessible to the Dialogue System's Lua environment.

To do this, you'll need to create "getter" and/or "setter" C# methods that get and set the variable's value. For example, say we define a C# variable named numCoins:

Code: Select all

public int numCoins;
The getter and setter functions can be:

Code: Select all

public int GetNumCoins() { return numCoins; }
public void SetNumCoins(double value) { numCoins = (int)value; }
(Note: This is a numeric variable, so we'll use a 'double' number type because that's what Lua uses internally.)

The GetNumCoins() method returns the value of numCoins. SetNumCoins(value) sets the value of numCoins.

You might define this in a script named CoinTracker, such as:

Code: Select all

public class CoinTracker : MonoBehaviour
{
    public int numCoins;

    public int GetNumCoins() { return numCoins; }
    public void SetNumCoins(double value) { numCoins = (int)value; }
}
The final step is to register your methods with Lua. You can find a starter template script in Assets / Plugins / Pixel Crushers / Dialogue System / Templates / Scripts / TemplateCustomLua.cs. Below is a script based on the template that incorporates the info above:

Code: Select all

using UnityEngine;
using PixelCrushers.DialogueSystem;

public class CoinTracker : MonoBehaviour
{
    public int numCoins;

    public int GetNumCoins() { return numCoins; }
    public void SetNumCoins(double value) { numCoins = (int)value; }

    [Tooltip("If this script is on your Dialogue Manager, leave unticked so temporary Dialogue Managers don't unregister your functions.")]
    public bool unregisterOnDisable = false;

    void OnEnable() // Register the getter and setter methods with Lua.
    {
        Lua.RegisterFunction(nameof(GetNumCoins), this, SymbolExtensions.GetMethodInfo(() => GetNumCoins()));
        Lua.RegisterFunction(nameof(SetNumCoins), this, SymbolExtensions.GetMethodInfo(() => SetNumCoins(0)));
    }

    void OnDisable() // Unregister the getter and setter methods.
    {
        if (!unregisterOnDisable) return;
        Lua.UnregisterFunction(nameof(GetNumCoins));
        Lua.UnregisterFunction(nameof(SetNumCoins));
    }
}
Once your functions are registered, you can use them in dialogue entries' Conditions and Script fields.

You can also use the [lua(code)] markup tag to show them in dialogue text, such as:
  • Dialogue Text: "I see you have [lua(GetNumCoins())] coins."
simplepleasuresdxy
Posts: 73
Joined: Tue Jul 25, 2023 1:34 am

Re: [HOWTO] How To: Connect C# Variables to Dialogue System's Lua

Post by simplepleasuresdxy »

So what if I already have a code for it? Where do I fit it without breaking the code?

Code: Select all

public class DataContainer : MonoBehaviour
{
    public static DataContainer Instance;
    [SerializeField] private int magicPower;
    [SerializeField] private List<StoreSceneData> savedSceneDataList = new List<StoreSceneData>();

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
        }
        else
        {
            Destroy(this.gameObject);
        }
        DontDestroyOnLoad(this.gameObject);
    }

    public void StoreData(List<string> _revealObjectsList)
    {
        string _sceneName = SceneManager.GetActiveScene().name;
        if (savedSceneDataList.Exists(x => x.sceneName == _sceneName))
        {
            int saveIndex = savedSceneDataList.FindIndex(x => x.sceneName == _sceneName);
            savedSceneDataList[saveIndex].AddRevealedObjects(_revealObjectsList);
        }
        else
        {
            savedSceneDataList.Add(new StoreSceneData { sceneName = _sceneName, revealedObjectsList = _revealObjectsList });
        }
    }

    public string GetRevealedObjectData(string _objectName)
    {
        string _sceneName = SceneManager.GetActiveScene().name;
        if (savedSceneDataList.Exists(x => x.sceneName == _sceneName))
        {
            int saveIndex = savedSceneDataList.FindIndex(x => x.sceneName == _sceneName);
            string revealedObject = savedSceneDataList[saveIndex].revealedObjectsList.Find(x => x == _objectName);
            return revealedObject;
        }
        return "";
    }
    public int GetMagicPower()
    {
        return magicPower;
    }
    public void AddMagicPower(int _magicPower)
    {
        magicPower += _magicPower;
    }
    public void DecreaseMagicPower(int _magicPower)
    {
        magicPower -= _magicPower;
    }
}
User avatar
Tony Li
Posts: 22124
Joined: Thu Jul 18, 2013 1:27 pm

Re: [HOWTO] How To: Connect C# Variables to Dialogue System's Lua

Post by Tony Li »

In that case, use the version below. I made changes to the Awake() method and added some lines at the bottom of the script.

Code: Select all

using PixelCrushers.DialogueSystem;

public class DataContainer : MonoBehaviour
{
    public static DataContainer Instance;
    [SerializeField] private int magicPower;
    [SerializeField] private List<StoreSceneData> savedSceneDataList = new List<StoreSceneData>();

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(this.gameObject);
            Lua.RegisterFunction(nameof(GetMagicPower), this, SymbolExtensions.GetMethodInfo(() => GetMagicPowerLua()));
            Lua.RegisterFunction(nameof(AddMagicPower), this, SymbolExtensions.GetMethodInfo(() => AddMagicPowerLua(0)));
            Lua.RegisterFunction(nameof(DecreaseMagicPower), this, SymbolExtensions.GetMethodInfo(() => DecreaseMagicPowerLua(0)));
        }
        else
        {
            Destroy(this.gameObject);
        }
    }

    public void StoreData(List<string> _revealObjectsList)
    {
        string _sceneName = SceneManager.GetActiveScene().name;
        if (savedSceneDataList.Exists(x => x.sceneName == _sceneName))
        {
            int saveIndex = savedSceneDataList.FindIndex(x => x.sceneName == _sceneName);
            savedSceneDataList[saveIndex].AddRevealedObjects(_revealObjectsList);
        }
        else
        {
            savedSceneDataList.Add(new StoreSceneData { sceneName = _sceneName, revealedObjectsList = _revealObjectsList });
        }
    }

    public string GetRevealedObjectData(string _objectName)
    {
        string _sceneName = SceneManager.GetActiveScene().name;
        if (savedSceneDataList.Exists(x => x.sceneName == _sceneName))
        {
            int saveIndex = savedSceneDataList.FindIndex(x => x.sceneName == _sceneName);
            string revealedObject = savedSceneDataList[saveIndex].revealedObjectsList.Find(x => x == _objectName);
            return revealedObject;
        }
        return "";
    }
    public int GetMagicPower()
    {
        return magicPower;
    }
    public void AddMagicPower(int _magicPower)
    {
        magicPower += _magicPower;
    }
    public void DecreaseMagicPower(int _magicPower)
    {
        magicPower -= _magicPower;
    }
    
    public double GetMagicPowerLua()
    {
        return magicPower;
    }
    public void AddMagicPowerLua(double _magicPower)
    {
        AddMagicPower((int)_magicPower);
    }
    public void DecreaseMagicPowerLua(double _magicPower)
    {
        DecreaseMagicPower((int)_magicPower);
    }
}
(Note: I didn't include the other "using" lines at the top of the script since your post didn't include them. Make sure to keep those lines in your actual script.)
simplepleasuresdxy
Posts: 73
Joined: Tue Jul 25, 2023 1:34 am

Re: [HOWTO] How To: Connect C# Variables to Dialogue System's Lua

Post by simplepleasuresdxy »

Whoa okay ... so if i get this right you added the lua stuff in the awake and then did the (double) amounts for the magic number down below.

If its possible could you explain the logic behind that and how that helps link the "magic power" to the lua stuff in the dialogue variable?
User avatar
Tony Li
Posts: 22124
Joined: Thu Jul 18, 2013 1:27 pm

Re: [HOWTO] How To: Connect C# Variables to Dialogue System's Lua

Post by Tony Li »

Hi,

Lua is a programming language. It's similar to the C# programming language that Unity uses, but it's not exactly C#. For various reasons, the Dialogue System uses Lua to handle variables and decision-making in conversations. (See the Conversation Conditions tutorial for more info on decision-making in conversations.)

A variable in C# has a specific type such as a string, bool, int, float, double, etc. Examples:

Code: Select all

string myString = "Hello world";
bool myBool = true;
int myInt = 3;
float myFloat = 3.1415926;
double myDouble = 3.1415926;
In the Dialogue System's Lua, all number variables are doubles. There's no int or float. So I added small methods GetMagicPowerLua(), AddMagicPowerLua(), and DecreaseMagicPowerLua() to your script that all use doubles to make them compatible with Lua. These methods just convert doubles to ints and then call your original methods (e.g., GetMagicPower()).

The Lua.RegisterFunction() calls in your Awake() method connect the script's GetMagicPowerLua(), AddMagicPowerLua(), and DecreaseMagicPowerLua() methods to the Dialogue System's Lua.
Post Reply