Call custom method in Dialogue System

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
nikot93
Posts: 6
Joined: Thu May 25, 2023 1:33 pm

Call custom method in Dialogue System

Post by nikot93 »

Hello everyone,

I am currently working on a Pokémon game in Unity and I am encountering some difficulties with the Dialogue System plugin. I was wondering if anyone could offer some guidance and support on this matter.

Let me provide some context. My game consists of a main scene and several additional scenes that are asynchronously loaded based on the player's movements within the map. The player character is present in the main scene, while the non-player characters (NPCs) are scattered throughout the various scenes.

Specifically, I have NPCs with scripts that are designed to give a Pokémon to the player character. I would like to incorporate this interaction into the Dialogue System conversations. I have attempted to modify my script and applied the changes within the Unity editor, but the process has proven to be quite complex, and unfortunately, it is not functioning as intended.

To provide further assistance, I have attached my script and screenshots of the settings I have adjusted within the editor.

Any help, advice, or suggestions on how I could properly implement this functionality would be greatly appreciated. Thank you in advance for your support.

Code: Select all

public class PokemonGiver : MonoBehaviour 
{
    [Tooltip("Typically leave unticked so temporary Dialogue Managers don't unregister your functions.")]
    public bool unregisterOnDisable = false;

    [SerializeField] Pokemon pokemonToGive;
    [SerializeField] public string uniqueID;

    bool used = false;


    void OnEnable()
    {
        Lua.RegisterFunction(nameof(GivePokemon), this, SymbolExtensions.GetMethodInfo(() => GivePokemon((PlayerController)null)));
        Lua.RegisterFunction(nameof(CanBeGiven), this, SymbolExtensions.GetMethodInfo(() => CanBeGiven()));
    }

    void OnDisable()
    {
        if (unregisterOnDisable)
        {
            Lua.UnregisterFunction(nameof(GivePokemon));
            Lua.UnregisterFunction(nameof(CanBeGiven));
        }
    }

    public IEnumerator GivePokemon(PlayerController player)
    {
        pokemonToGive.Init();
        player.GetComponent<PokemonParty>().AddPokemon(pokemonToGive);

        used = true;

        AudioManager.i.PlaySfx(AudioId.PokemonObtained, pauseMusic: true);

        yield return null;
    }

    public bool CanBeGiven()
    {
        return pokemonToGive != null && !used;
    }

    
}
Screenshot_2.png
Screenshot_2.png (28.93 KiB) Viewed 2805 times
Screenshot_3.png
Screenshot_3.png (40.93 KiB) Viewed 2805 times
Nicolò
User avatar
Tony Li
Posts: 21681
Joined: Thu Jul 18, 2013 1:27 pm

Re: Call custom method in Dialogue System

Post by Tony Li »

Hi Nicolò,

Lua functions are registered globally. This means you can only register one instance of PokemonGiver.GivePokemon at a time. They also should not be coroutines, although you can start another coroutine from inside a C# method that's registered with Lua.

If the conversation conversant always gives the Pokémon, you could move the C# method/Lua function to a new script on the Dialogue Manager. Example C# methods:

Code: Select all

public void GivePokemon()
{
    var player = FindObjectOfType<PlayerController>();
    var pokemonGiver = DialogueManager.currentConversant.GetComponent<PokemonGiver>();
    if (player == null || pokemonGiver == null) return;
    pokemonGiver.pokemonToGive.Init();
    player.GetComponent<PokemonParty>().AddPokemon(pokemonGiver.pokemonToGive);
    pokemonGiver.used = true;
    AudioManager.i.PlaySfx(AudioId.PokemonObtained, pauseMusic: true);
}

public bool CanBeGiven()
{
    var pokemonGiver = DialogueManager.currentConversant.GetComponent<PokemonGiver>();
    return pokemonGiver != null && pokemonGiver.pokemonToGive != null && !pokemonGiver.used;
}
nikot93
Posts: 6
Joined: Thu May 25, 2023 1:33 pm

Re: Call custom method in Dialogue System

Post by nikot93 »

Hi Tony,

Thank you for your response, and I apologize for the delay in getting back to you.

Based on your suggestions, I have created a new script. Here's the updated code:

Code: Select all

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PixelCrushers.DialogueSystem;

public class DialogueManagerExtension : MonoBehaviour
{
    void OnEnable()
    {
        // Make the functions available to Lua: 
        Lua.RegisterFunction("GivePokemon", this, SymbolExtensions.GetMethodInfo(() => GivePokemon()));
        Lua.RegisterFunction("CanBeGiven", this, SymbolExtensions.GetMethodInfo(() => CanBeGiven()));
    }

    void OnDisable()
    {
        // Remove the functions from Lua:
        Lua.UnregisterFunction("GivePokemon");
        Lua.UnregisterFunction("CanBeGiven");
    }

    public void GivePokemon()
    {
        
        var player = FindObjectOfType<PlayerController>();

        if (DialogueManager.currentConversant == null)
        {
            Debug.Log("Current Conversant is null");
            return;
        }

        var pokemonGiver = DialogueManager.currentConversant.GetComponent<PokemonGiver>();
        var pokemonParty = player.GetComponent<PokemonParty>();

        pokemonGiver.pokemonToGive.Init();
        pokemonParty.AddPokemon(pokemonGiver.pokemonToGive);
        pokemonGiver.used = true;
        AudioManager.i.PlaySfx(AudioId.PokemonObtained, pauseMusic: true);
        
    }

    public bool CanBeGiven()
    {
        var pokemonGiver = DialogueManager.currentConversant.GetComponent<PokemonGiver>();
        return pokemonGiver != null && pokemonGiver.pokemonToGive != null && !pokemonGiver.used;
    }
}
However, I am encountering a problem. The DialogueManager.currentConversant is null when I press the spacebar to interact with the NPC, and it doesn't work as expected. Strangely, if I don't close the conversation and press the spacebar again, the NPC gives me a Pokémon for every press of the spacebar.

Image

Could you please help me understand why DialogueManager.currentConversant is null at the start of the conversation? Additionally, is it possible to configure the dialogue to start before the Lua function and have the Pokémon given at the end of the conversation?

Thank you for your assistance.

Best regards,
Nicolò
Attachments
Screenshot_4.png
Screenshot_4.png (40.95 KiB) Viewed 2779 times
User avatar
Tony Li
Posts: 21681
Joined: Thu Jul 18, 2013 1:27 pm

Re: Call custom method in Dialogue System

Post by Tony Li »

Hi,

Where are you calling GivePokemon()? If it's in the Script field of a dialogue entry in a conversation, DialogueManager.currentConversant should already be set -- assuming the conversation uses a conversant GameObject. For more info, see: Character GameObject Assignments

If you want to give the pokemon at the end, you can add a blank node to the end of the conversation. Call GivePokemon() in the Script field, and set the Sequence field to: Continue()
nikot93
Posts: 6
Joined: Thu May 25, 2023 1:33 pm

Re: Call custom method in Dialogue System

Post by nikot93 »

Tony Li wrote: Tue May 30, 2023 6:55 pm Hi,

Where are you calling GivePokemon()? If it's in the Script field of a dialogue entry in a conversation, DialogueManager.currentConversant should already be set -- assuming the conversation uses a conversant GameObject. For more info, see: Character GameObject Assignments

If you want to give the pokemon at the end, you can add a blank node to the end of the conversation. Call GivePokemon() in the Script field, and set the Sequence field to: Continue()
Hi,

Thank you so much for your prompt response and valuable support. Your suggestion to call GivePokemon() in the Script field of a blank node at the end of the conversation, with the Sequence field set to "Continue()", worked perfectly! Now the Pokémon is given at the end of the conversation, as desired.

Previously, I was calling the GivePokemon() function directly in the Dialogue System trigger before the conversation started. Integrating it within the conversation itself has resolved the issue, and everything is functioning flawlessly.

The only thing left for me to do is to implement the logic that prevents the Pokémon from being given multiple times. I will work on that aspect. If you have any advice or recommendations on how to approach this implementation, I would greatly appreciate it.

Once again, thank you for your swift assistance and the effective solution you provided.

Best regards,
Nicolò
User avatar
Tony Li
Posts: 21681
Joined: Thu Jul 18, 2013 1:27 pm

Re: Call custom method in Dialogue System

Post by Tony Li »

Hi,

I'd check the CanBeGiven() Lua function in a preceding dialogue entry node's Conditions field. If it's true, go down one branch of the conversation tree that ends in the node that calls GivePokemon(). If it's not true, go down another branch that doesn't call GivePokemon().
nikot93
Posts: 6
Joined: Thu May 25, 2023 1:33 pm

Re: Call custom method in Dialogue System

Post by nikot93 »

Tony Li wrote: Tue May 30, 2023 7:58 pm Hi,

I'd check the CanBeGiven() Lua function in a preceding dialogue entry node's Conditions field. If it's true, go down one branch of the conversation tree that ends in the node that calls GivePokemon(). If it's not true, go down another branch that doesn't call GivePokemon().
It works really really well.

Thanks you so much
User avatar
Tony Li
Posts: 21681
Joined: Thu Jul 18, 2013 1:27 pm

Re: Call custom method in Dialogue System

Post by Tony Li »

Glad to help!
mamaji77111
Posts: 1
Joined: Wed May 31, 2023 10:45 am

Re: Call custom method in Dialogue System

Post by mamaji77111 »

Call custom method in Dialogue Systemhttps://pikashow.fyi/
https://ppssppgold.one/
Post Reply