hi everyone,
I try to do a dialog system and for that I created those gameObject:
And the panel use this script to display the UI:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Ink.Runtime;
using TMPro;
using UnityEngine.UI;
public class DialogSystem : MonoBehaviour
{
public TextAsset inkFile; // Reference to the Inky file we want to use
private Story story; // Reference to the Ink story
public TextMeshProUGUI dialogText; // Reference to the UI text element that will display the dialog
public Button[] choiceButtons; // References to the UI button elements that will display the choices
private void Start()
{
// Initialize the Ink story using the Inky file
story = new Story(inkFile.text);
}
private void Update()
{
// If the player clicks a choice button, continue the dialog with the corresponding choice
for (int i = 0; i < choiceButtons.Length; i++)
{
if (choiceButtons[i].gameObject.activeSelf && Input.GetMouseButtonDown(0))
{
ChooseOption(i);
}
}
}
public void ContinueDialog()
{
Debug.Log("Continue dialog");
// Check if there's more dialog to display
if (story.canContinue)
{
// Get the next line of dialog
string dialog = story.Continue();
// Display the dialog on the UI text element
dialogText.text = dialog;
// Hide all choice buttons
foreach (Button button in choiceButtons)
{
button.gameObject.SetActive(false);
}
// Check if there are choices to display
if (story.currentChoices.Count > 0)
{
// Display the choices on the corresponding UI button elements
for (int i = 0; i < story.currentChoices.Count; i++)
{
Choice choice = story.currentChoices[i];
choiceButtons[i].gameObject.SetActive(true);
choiceButtons[i].GetComponentInChildren<TextMeshProUGUI>().text = choice.text;
}
}
}
else
{
this.gameObject.SetActive(false);
}
}
public void ContinueDialogFromExternal()
{
ContinueDialog();
}
private void ChooseOption(int optionIndex)
{
// Choose the corresponding option in the Ink story
story.ChooseChoiceIndex(optionIndex);
// Continue the dialog with the chosen option
ContinueDialog();
}
}
And I created those gameobject call NPC (for non playable character):
who contained this script and their dialog (inkFile) inside “TextAsset inkJSON” :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Interactions;
public class DialogueTrigger : MonoBehaviour
{
[Header("Visual Cue")]
[SerializeField] private GameObject visualCue;// "SerializeField" = show the variable in the inspector even if private
//visualcue is a game object for the text buble
[Header("Ink JSON")]
[SerializeField] private TextAsset inkJSON;
[Header("Dialog panel")]
[SerializeField] private GameObject dialPanel;
//new input system step 1
PlayerInputActions playerInputs;
private InputAction interact;
private bool playerInRange;
private void Awake()
{
playerInRange = false;
visualCue.SetActive(false);
//new input system step 2
playerInputs = new PlayerInputActions();
}
private void OnEnable()
{
playerInputs.Enable();
interact = playerInputs.Player.Interact;
interact.Enable();
interact.performed += Interact;
}
private void OnDisable()
{
interact.Disable();
playerInputs.Disable();
}
private void Update()
{
if (playerInRange)
{
visualCue.SetActive(true);
}
else
{
visualCue.SetActive(false);
}
}
private void Interact(InputAction.CallbackContext context)
{
if (playerInRange)
{
Debug.Log("start dialog");
dialPanel.SetActive(true);
// Get the DialogSystem component attached to the same GameObject as this DialogueTrigger component
DialogSystem dialogSystem = GetComponent<DialogSystem>();
// Start the dialogue
dialogSystem.ContinueDialog();
}
}
private void OnTriggerEnter2D(Collider2D collider)
{
if (collider.gameObject.tag == "Player")//if the gameobject touch another gameobject with the tag "Player"
{
playerInRange = true;
Debug.Log("enter trigger");
}
else
{
playerInRange = false;
Debug.Log("enter but wrong tag");
}
}
private void OnTriggerExit2D(Collider2D collider)
{
if (collider.gameObject.tag == "Player")
{
playerInRange = false;
Debug.Log("exit trigger");
}
else
{
playerInRange = true;
Debug.Log("exit but wrong tag");
}
}
}
But it doesn’t seems to display the dialog and show to me the following error:
“NullReferenceException: Object reference not set to an instance of an object
DialogueTrigger.Interact (UnityEngine.InputSystem.InputAction+CallbackContext context) (at Assets/Scripts/DialogueSystem/DialogueTrigger.cs:71)
UnityEngine.InputSystem.Utilities.DelegateHelpers.InvokeCallbacksSafe[TValue] (UnityEngine.InputSystem.Utilities.CallbackArray1[System.Action
1[TValue]]& callbacks, TValue argument, System.String callbackName, System.Object context) (at Library/PackageCache/com.unity.inputsystem@1.4.3/InputSystem/Utilities/DelegateHelpers.cs:46)
UnityEngine.InputSystem.LowLevel.<>c__DisplayClass7_0:<set_onUpdate>b__0(NativeInputUpdateType, NativeInputEventBuffer*)
UnityEngineInternal.Input.NativeInputSystem:NotifyUpdate(NativeInputUpdateType, IntPtr)”
and
"
NullReferenceException while executing ‘performed’ callbacks of ‘Player/Interact[/Mouse/leftButton,/Keyboard/e]’
UnityEngine.InputSystem.LowLevel.NativeInputRuntime/<>c__DisplayClass7_0:<set_onUpdate>b__0 (UnityEngineInternal.Input.NativeInputUpdateType,UnityEngineInternal.Input.NativeInputEventBuffer*)
UnityEngineInternal.Input.NativeInputSystem:NotifyUpdate (UnityEngineInternal.Input.NativeInputUpdateType,intptr)"
Which is weird because it seems to be related to the use of the iteract button and it’s doesn’t show when I simply test the Interact() like this :
private void Interact(InputAction.CallbackContext context)
{
if (playerInRange)
{
Debug.Log("start dialog");
dialPanel.SetActive(true);
}
}