Files
2025TapTapGameJam/Assets/Script/Gameplay/Player/PlayerDialogueController.cs

155 lines
5.3 KiB
C#
Raw Normal View History

using System;
using System.Collections;
using System.Collections.Generic;
using Core;
using UnityEngine;
using UnityEngine.Events;
using Script.Gameplay.Interface;
using Script.Gameplay.Input;
using UI;
namespace Script.Gameplay.Player
{
public class PlayerDialogueController : MonoBehaviour
{
[SerializeField] private bool isEnablePlayerDialogue = true; // 是否启用玩家对话功能
[SerializeField] private FirstPersonRaycaster firstPersonRaycaster; // 第一人称射线检测器
private bool isReadingDialogue = false;
public event Action OnPlayerBeginDialogue;
public event Action OnPlayerEndDialogue;
public event Action<GameObject> OnGazeEnterDialogue;
public event Action<GameObject> OnGazeExitDialogue;
private Queue<string> dialogueQueue = new Queue<string>();
private PlayerDialogueViewer playerDialogueViewer;
private IDialogue previousDialogue;
private IDialogue currentDialogueTarget;
public IDialogue CurrentDialogueTarget
{
get => currentDialogueTarget;
set
{
previousDialogue = currentDialogueTarget;
currentDialogueTarget = value;
if (previousDialogue != currentDialogueTarget)
{
if (currentDialogueTarget != null)
{
OnGazeEnterDialogue?.Invoke((currentDialogueTarget as MonoBehaviour)?.gameObject);
}
if (previousDialogue != null)
{
OnGazeExitDialogue?.Invoke((previousDialogue as MonoBehaviour)?.gameObject);
}
}
}
}
void Start()
{
if (firstPersonRaycaster == null)
firstPersonRaycaster = GetComponent<FirstPersonRaycaster>() ??
GetComponentInChildren<FirstPersonRaycaster>();
if (firstPersonRaycaster == null)
firstPersonRaycaster = FindObjectOfType<FirstPersonRaycaster>();
if (firstPersonRaycaster == null)
Debug.LogWarning("FirstPersonRaycaster not found! Please assign or add it to the player.");
var input = InputManager.Instance.Input;
input.Player.Interact.performed += ctx =>
{
if (!isEnablePlayerDialogue) return;
if (CurrentDialogueTarget == null) return;
if (isReadingDialogue) return;
BeginDialogue();
};
input.Player.ShowNextDialogue.performed += ctx =>
{
if (!isEnablePlayerDialogue) return;
if (CurrentDialogueTarget == null) return;
if (!isReadingDialogue) return;
PassNextDialogue();
};
ControllerLocator.Instance.Register(this);
}
void Update()
{
DetectDialogue();
}
private void DetectDialogue()
{
if (!isEnablePlayerDialogue || firstPersonRaycaster == null) return;
GameObject lookAtObj = firstPersonRaycaster.CurrentLookAtObject;
IDialogue hitDialogue = lookAtObj != null ? lookAtObj.GetComponent<IDialogue>() : null;
CurrentDialogueTarget = hitDialogue;
}
private void BeginDialogue()
{
if (CurrentDialogueTarget != null)
{
isReadingDialogue = true;
OnPlayerBeginDialogue?.Invoke();
CurrentDialogueTarget.OnBeginDialogue?.Invoke(true);
dialogueQueue = SplitDialogue(CurrentDialogueTarget.DialogueContent);
PassNextDialogue();
}
}
private void PassNextDialogue()
{
if (CurrentDialogueTarget != null)
{
if (dialogueQueue.Count == 0)
{
EndDialogue();
return;
}
string nextDialogue = dialogueQueue.Dequeue();
if (playerDialogueViewer != null)
{
playerDialogueViewer.ReceiveDialogue(nextDialogue);
}
}
}
private void EndDialogue()
{
if (CurrentDialogueTarget != null)
{
isReadingDialogue = false;
OnPlayerEndDialogue?.Invoke();
CurrentDialogueTarget.OnEndDialogue?.Invoke(true);
if (playerDialogueViewer != null)
{
playerDialogueViewer.ClosePanel();
}
// 可扩展隐藏UI、恢复输入等
}
}
private Queue<string> SplitDialogue(string content)
{
// 按换行分段
return new(content.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries));
}
public void RegisterDialogueViewer(PlayerDialogueViewer viewer)
{
playerDialogueViewer = viewer;
}
public void SetPlayerDialogueEnabled(bool isEnabled)
{
isEnablePlayerDialogue = isEnabled;
if (!isEnabled)
{
CurrentDialogueTarget = null;
}
}
}
}