added dialogue manager and radar

This commit is contained in:
2026-02-18 13:53:02 +00:00
parent e1df65bce2
commit 23362e7bdd
11 changed files with 915 additions and 3 deletions

View File

@@ -0,0 +1,135 @@
using UnityEngine;
/// <summary>
/// Attach this to any world object (NPC, terminal, sign, corpse, etc.)
/// to make it interactable. The player presses E when looking at it
/// from within interactRange to start the dialogue.
///
/// The component draws a small world-space "[E]" prompt via OnGUI
/// when the player is close enough and looking at the object.
/// </summary>
public class DialogueNPC : MonoBehaviour
{
[Header("Dialogue")]
public DialogueLine[] lines = new DialogueLine[]
{
new DialogueLine { speakerName = "STRANGER", pages = new[] { "Hey." } }
};
[Header("Interaction")]
[Tooltip("Maximum distance from which the player can interact.")]
public float interactRange = 3.5f;
[Tooltip("Maximum angle (degrees) between player forward and direction to this object.")]
public float interactAngle = 45f;
[Tooltip("Layer mask used for the line-of-sight raycast.")]
public LayerMask occlusionMask = ~0;
[Header("Prompt Style")]
public string promptText = "[E] Talk";
public Color colPrompt = new Color(0.20f, 0.95f, 0.40f, 1f);
public Color colPromptBg = new Color(0f, 0f, 0f, 0.70f);
// ── Private ──────────────────────────────────────────────────────
private Transform _playerTransform;
private Camera _playerCamera;
private bool _promptVisible;
private Texture2D _white;
// ─────────────────────────────────────────────────────────────────
void Start()
{
_white = Texture2D.whiteTexture;
// Find the player by component
var player = FindObjectOfType<FirstPersonController>();
if (player != null)
{
_playerTransform = player.transform;
_playerCamera = player.GetComponentInChildren<Camera>();
}
else
{
Debug.LogWarning($"[DialogueNPC] '{name}': Could not find FirstPersonController in scene.");
}
}
void Update()
{
if (_playerTransform == null || DialogueManager.Instance == null) return;
if (DialogueManager.Instance.IsOpen) { _promptVisible = false; return; }
_promptVisible = CanInteract();
if (_promptVisible && Input.GetKeyDown(KeyCode.E))
DialogueManager.Instance.StartDialogue(lines);
}
// ─────────────────────────────────────────────────────────────────
bool CanInteract()
{
if (_playerTransform == null || _playerCamera == null) return false;
// Distance check
float dist = Vector3.Distance(_playerTransform.position, transform.position);
if (dist > interactRange) return false;
// Angle check — is the player roughly facing this object?
Vector3 dir = (transform.position - _playerCamera.transform.position).normalized;
float dot = Vector3.Dot(_playerCamera.transform.forward, dir);
if (dot < Mathf.Cos(interactAngle * Mathf.Deg2Rad)) return false;
// Line-of-sight (optional — fire a ray toward us)
if (Physics.Raycast(_playerCamera.transform.position, dir, out RaycastHit hit, interactRange, occlusionMask))
{
// Allow if the hit object is us or a child of us
if (!hit.transform.IsChildOf(transform) && hit.transform != transform)
return false;
}
return true;
}
// ─────────────────────────────────────────────────────────────────
void OnGUI()
{
if (!_promptVisible || _playerCamera == null) return;
// Project to screen
Vector3 worldPos = transform.position + Vector3.up * 0.5f; // slightly above pivot
Vector3 screenPos = _playerCamera.WorldToScreenPoint(worldPos);
if (screenPos.z <= 0f) return; // behind camera
// Flip Y (GUI vs screen coords)
float sx = screenPos.x;
float sy = Screen.height - screenPos.y;
GUIStyle style = new GUIStyle();
style.fontSize = 13;
style.fontStyle = FontStyle.Bold;
style.normal.textColor = colPrompt;
style.alignment = TextAnchor.MiddleCenter;
Vector2 size = style.CalcSize(new GUIContent(promptText));
float padX = 8f;
float padY = 4f;
float bgW = size.x + padX * 2f;
float bgH = size.y + padY * 2f;
Rect bgRect = new Rect(sx - bgW * 0.5f, sy - bgH * 0.5f, bgW, bgH);
Rect txRect = new Rect(sx - size.x * 0.5f, sy - size.y * 0.5f, size.x, size.y);
// Background
Color prev = GUI.color;
GUI.color = colPromptBg;
GUI.DrawTexture(bgRect, _white);
GUI.color = prev;
GUI.Label(txRect, promptText, style);
}
void OnDrawGizmosSelected()
{
Gizmos.color = new Color(0f, 1f, 0.4f, 0.25f);
Gizmos.DrawWireSphere(transform.position, interactRange);
}
}