2026-06-22 캐릭터 영역별 스크립트
This commit is contained in:
@@ -5,17 +5,25 @@
|
||||
[RequireComponent(typeof(CharacterVoiceObject))]
|
||||
public class DialogPlayer : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private List<DialogGroup> _dialogGroups;
|
||||
[System.Serializable]
|
||||
public struct RegionGroup
|
||||
{
|
||||
public string Region; // 영역 이름 (NPC마다 자유롭게 지정 — 그룹 이름과 무관)
|
||||
public DialogGroup Group;
|
||||
}
|
||||
|
||||
[Tooltip("영역 이름 ↔ 그 영역에서 재생할 DialogGroup")]
|
||||
[SerializeField] private List<RegionGroup> _regionGroups;
|
||||
|
||||
[Header("Region")]
|
||||
[SerializeField] private string _currentRegion; // 현재 영역(DialogGroup 이름). DialogRegion 트리거가 갱신
|
||||
[SerializeField] private string _currentRegion; // 현재 영역 이름. DialogRegion 트리거가 갱신
|
||||
|
||||
[Header("Dialog HUD Placement")] // 씬에서 캐릭터 위치/주변(벽 등)에 맞춰 조절
|
||||
[SerializeField] private float _hudChestHeight = 1.2f; // 화자 발 기준 가슴 높이
|
||||
[SerializeField] private float _hudForwardOffset = 0.5f; // 화자→플레이어 방향으로 띄울 거리
|
||||
[SerializeField] private float _hudLateralOffset = 0f; // 좌우 오프셋 (+ 플레이어 시점 오른쪽)
|
||||
|
||||
private Dictionary<string, DialogGroup> _dialogGroupMap;
|
||||
private Dictionary<string, DialogGroup> _regionMap;
|
||||
private Animator _animator;
|
||||
private int _initialGestureHash;
|
||||
private int _initialExpressionHash;
|
||||
@@ -25,9 +33,9 @@ public class DialogPlayer : MonoBehaviour
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_dialogGroupMap = new Dictionary<string, DialogGroup>();
|
||||
foreach (var g in _dialogGroups)
|
||||
_dialogGroupMap[g.DialogGroupName] = g;
|
||||
_regionMap = new Dictionary<string, DialogGroup>();
|
||||
foreach (var e in _regionGroups)
|
||||
if (e.Group != null) _regionMap[e.Region] = e.Group;
|
||||
|
||||
_animator = GetComponentInChildren<Animator>();
|
||||
|
||||
@@ -44,17 +52,17 @@ private void Awake()
|
||||
|
||||
public async Awaitable Play()
|
||||
{
|
||||
var groupName = ResolveGroupName();
|
||||
if (groupName != null)
|
||||
await Play(groupName);
|
||||
var region = ResolveRegion();
|
||||
if (region != null)
|
||||
await Play(region);
|
||||
}
|
||||
|
||||
// 현재 영역에 맞는 그룹명. 영역이 없거나 매칭 그룹이 없으면 첫 그룹으로 폴백.
|
||||
private string ResolveGroupName()
|
||||
// 현재 영역. 영역이 없거나 매칭 그룹이 없으면 리스트 첫 항목으로 폴백.
|
||||
private string ResolveRegion()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_currentRegion) && _dialogGroupMap.ContainsKey(_currentRegion))
|
||||
if (!string.IsNullOrEmpty(_currentRegion) && _regionMap.ContainsKey(_currentRegion))
|
||||
return _currentRegion;
|
||||
return _dialogGroups.Count > 0 ? _dialogGroups[0].DialogGroupName : null;
|
||||
return _regionGroups.Count > 0 ? _regionGroups[0].Region : null;
|
||||
}
|
||||
|
||||
// 영역 전환 (DialogRegion 트리거가 호출). 다음 Play()부터 해당 영역 대화가 재생됨.
|
||||
@@ -62,12 +70,12 @@ private string ResolveGroupName()
|
||||
|
||||
public string CurrentRegion => _currentRegion;
|
||||
|
||||
public async Awaitable Play(string groupName)
|
||||
public async Awaitable Play(string region)
|
||||
{
|
||||
if (IsPlaying) return;
|
||||
if (!_dialogGroupMap.TryGetValue(groupName, out var group))
|
||||
if (!_regionMap.TryGetValue(region, out var group))
|
||||
{
|
||||
Debug.LogWarning($"[DialogPlayer] 그룹 없음: {groupName}");
|
||||
Debug.LogWarning($"[DialogPlayer] 영역 대화 없음: {region}");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fb6dce8c4da85e478d7da770f057cf3
|
||||
44
Assets/02_Scripts/Npcs/FollowObject.cs
Normal file
44
Assets/02_Scripts/Npcs/FollowObject.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
// 대상(보통 플레이어)을 NavMesh 위에서 따라다니는 간단한 동행 스크립트.
|
||||
// 속도/회전속도/가속/높이(Base Offset) 등은 NavMeshAgent 컴포넌트에서 설정한다.
|
||||
[RequireComponent(typeof(NavMeshAgent))]
|
||||
public class FollowObject : MonoBehaviour
|
||||
{
|
||||
[Header("Target")]
|
||||
[SerializeField] private Transform _target; // 비워두면 Camera.main 사용
|
||||
|
||||
[Header("Follow")]
|
||||
[SerializeField] private float _followDistance = 3.0f; // 이 거리 안이면 멈춤 (= Agent stoppingDistance)
|
||||
[SerializeField] private float _repathInterval = 0.2f; // 목적지 갱신 주기(초)
|
||||
|
||||
private NavMeshAgent _agent;
|
||||
private float _repathTimer;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_agent = GetComponent<NavMeshAgent>();
|
||||
_agent.stoppingDistance = _followDistance;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
var target = ResolveTarget();
|
||||
if (target == null || !_agent.isOnNavMesh) return;
|
||||
|
||||
_repathTimer -= Time.deltaTime;
|
||||
if (_repathTimer > 0f) return;
|
||||
|
||||
_repathTimer = _repathInterval;
|
||||
_agent.SetDestination(target.position); // NavMesh가 지면/경사/장애물을 알아서 처리
|
||||
}
|
||||
|
||||
private Transform ResolveTarget()
|
||||
{
|
||||
if (_target != null) return _target;
|
||||
return Camera.main != null ? Camera.main.transform : null;
|
||||
}
|
||||
|
||||
public void SetTarget(Transform target) => _target = target;
|
||||
}
|
||||
2
Assets/02_Scripts/Npcs/FollowObject.cs.meta
Normal file
2
Assets/02_Scripts/Npcs/FollowObject.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c34c05a7f0add5248b2c4aff05789f4b
|
||||
Reference in New Issue
Block a user