Hi, I’m currently experiencing an issue with programming NPC’s. I want NPC’s to change their sprite depending on where the player is positioned (example: if the Player is interacting with them and they’re facing right then the NPC faces left). However, while I do know that I’m on the right track, as soon as the Player interacts with the NPC, the NPC changes sprites but then immediately changes back to the idle sprite. If I try interacting with the NPC again, it no longer changes sprites at all and stays at the idle sprite. I’ve been trying to solve this on my own for way too long so I’m reaching out to see who can help.
I’ve linked a video representation of my issue if it helps. Also, if you believe that there’s any extra scripts you may need to see, I’ll show you the script.
https://1drv.ms/v/s!Akv6vtVraeC9mRoo--FF7JpJ0GkK?e=h3DL3P
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
public class NPCController : MonoBehaviour, Interactable
{
[SerializeField] Dialogue dialogue;
public void Interact()
{
StartCoroutine (DialogueManager.Instance.ShowDialogue(dialogue));
}
}
*/
public class NPCController : MonoBehaviour, Interactable
{
[SerializeField] Dialogue dialogue;
[SerializeField] Transform playerTransform; // Assign the player's transform in the inspector
private Animator animator; // Reference to the Animator component
private void Awake()
{
animator = GetComponent<Animator>();
}
public void Interact()
{
Debug.Log("Interact method called");
// Determine the direction to the player
Vector3 directionToPlayer = playerTransform.position - transform.position;
// Set the appropriate animation based on the player's position
if (Mathf.Abs(directionToPlayer.x) > Mathf.Abs(directionToPlayer.y))
{
// Player is primarily horizontal to NPC
if (directionToPlayer.x > 0)
{
animator.SetTrigger("FaceRight");
}
else if (directionToPlayer.x < 0)
{
animator.SetTrigger("FaceLeft");
}
}
else
{
// Player is primarily vertical to NPC
if (directionToPlayer.y > 0)
{
animator.SetTrigger("FaceUp");
}
else if (directionToPlayer.y < 0)
{
animator.SetTrigger("FaceDown");
}
}
// Start the dialogue and wait for it to finish before resetting the sprite
StartCoroutine(ShowDialogueAndReset());
}
private IEnumerator ShowDialogueAndReset()
{
yield return StartCoroutine(DialogueManager.Instance.ShowDialogue(dialogue));
// Reset the NPC sprite to idle after the dialogue is finished
animator.SetTrigger("ResetIdle");
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum GameState { FreeRoam, Dialogue, Battle }
public class GameController : MonoBehaviour
{
[SerializeField] PlayerMovement playerController;
GameState state;
private void Start()
{
DialogueManager.Instance.OnShowDialogue += () =>
{
state = GameState.Dialogue;
};
DialogueManager.Instance.OnHideDialogue += () =>
{
if (state == GameState.Dialogue)
state = GameState.FreeRoam;
};
}
void Update()
{
if (state == GameState.FreeRoam)
{
playerController.HandleUpdate();
}
else if (state == GameState.Dialogue)
{
DialogueManager.Instance.HandleUpdate();
}
else if (state == GameState.Battle)
{
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Dialogue
{
[SerializeField] List<string> lines;
public List<string> Lines
{
get { return lines; }
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DialogueManager : MonoBehaviour
{
[SerializeField] GameObject dialogueBox;
[SerializeField] Text dialogueText;
[SerializeField] int lettersPerSeconds;
public event Action OnShowDialogue;
public event Action OnHideDialogue;
public static DialogueManager Instance { get; private set; }
private void Awake()
{
Instance = this;
}
Dialogue dialogue;
int currentLine = 0;
bool isTyping;
public IEnumerator ShowDialogue(Dialogue dialogue)
{
yield return new WaitForEndOfFrame();
OnShowDialogue?.Invoke();
this.dialogue = dialogue;
dialogueBox.SetActive(true);
StartCoroutine(TypeDialogue(dialogue.Lines[0]));
}
public void HandleUpdate()
{
if (Input.GetKeyDown(KeyCode.F) && !isTyping)
{
++currentLine;
if (currentLine < dialogue.Lines.Count)
{
StartCoroutine(TypeDialogue(dialogue.Lines[currentLine]));
}
else
{
dialogueBox.SetActive(false);
currentLine = 0;
OnHideDialogue?.Invoke();
}
}
}
public IEnumerator TypeDialogue(string line)
{
isTyping = true;
dialogueText.text = "";
foreach (var letter in line.ToCharArray())
{
dialogueText.text += letter;
yield return new WaitForSeconds(1f / lettersPerSeconds);
}
isTyping = false;
}
}