MoveTo, LookAt 타겟 지정 수정

This commit is contained in:
Jeonghyeon Ha 2025-08-27 19:43:08 +09:00
parent bf1fe51957
commit dfc4fa26d6
6 changed files with 50 additions and 78 deletions

View File

@ -9,7 +9,7 @@ namespace DDD
/// </summary>
public interface IAISharedBlackboard
{
void SetCurrentInteractionTarget(GameObject targetGameObject);
GameObject GetCurrentInteractionTarget();
void SetBlackboardGameObject(string key, GameObject inGameObject);
GameObject GetBlackboardGameObject(string key);
}
}

View File

@ -30,42 +30,43 @@ public interface ILookAtVisual
void EndLookAt();
}
private ILookAtVisual visual;
private GameObject cachedTarget;
private bool isLooking;
private Vector3 currentLookPosition;
private ILookAtVisual _visual;
private GameObject _cachedTarget;
private bool _isLooking;
private Vector3 _currentLookPosition;
public override void OnStart()
{
visual = gameObject.GetComponentInParent<ILookAtVisual>();
cachedTarget = null;
isLooking = false;
_visual = gameObject.GetComponentInParent<ILookAtVisual>();
_isLooking = false;
var blackboard = gameObject.GetComponent<IAISharedBlackboard>();
_cachedTarget = blackboard.GetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget));
}
public override TaskStatus OnUpdate()
{
var target = GetTarget();
if (target == null)
{
if (_cachedTarget == null)
{
if (isLooking)
if (_isLooking)
{
// 타겟이 사라졌다면 정리
visual?.EndLookAt();
isLooking = false;
_visual?.EndLookAt();
_isLooking = false;
}
return TaskStatus.Success;
}
currentLookPosition = CalculateLookPosition(target);
_currentLookPosition = CalculateLookPosition(_cachedTarget);
if (!isLooking)
if (!_isLooking)
{
visual?.TryBeginLookAt(currentLookPosition);
isLooking = true;
_visual?.TryBeginLookAt(_currentLookPosition);
_isLooking = true;
}
else
{
visual?.UpdateLookAt(currentLookPosition);
_visual?.UpdateLookAt(_currentLookPosition);
}
// 연속 업데이트면 Running, 아니면 1회만 시도 후 Success 반환
@ -74,33 +75,12 @@ public override TaskStatus OnUpdate()
public override void OnEnd()
{
if (isLooking)
if (_isLooking)
{
visual?.EndLookAt();
isLooking = false;
_visual?.EndLookAt();
_isLooking = false;
}
cachedTarget = null;
}
private GameObject GetTarget()
{
// 캐시된 타겟이 유효하면 재사용
if (IsValidTarget(cachedTarget))
return cachedTarget;
// 블랙보드에서 타겟 검색
cachedTarget = gameObject.GetComponent<IAISharedBlackboard>()
?.GetCurrentInteractionTarget();
if (IsValidTarget(cachedTarget))
return cachedTarget;
// Interactor의 포커스된 타겟 검색
var interactor = gameObject.GetComponent<IInteractor>();
var focusedInteractable = interactor?.GetFocusedInteractable();
cachedTarget = focusedInteractable?.GetInteractableGameObject();
return cachedTarget;
_cachedTarget = null;
}
private static bool IsValidTarget(GameObject target) => target != null && target;

View File

@ -23,32 +23,30 @@ public class MoveToInteractionTarget : Action
private float _repathTimer;
private Vector3 _currentDestination;
private bool _isMoving;
private GameObject _target;
public override void OnStart()
{
_movement = gameObject.GetComponent<IAiMovement>();
_repathTimer = 0f;
_isMoving = false;
Debug.Log($"MoveToInteractionTarget - GameObject: {gameObject.name}");
var blackboard = gameObject.GetComponent<IAISharedBlackboard>();
_target = blackboard.GetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget));
}
public override TaskStatus OnUpdate()
{
if (_movement == null)
return TaskStatus.Failure;
var target = GetTarget();
if (target == null)
if (_target == null)
{
return TaskStatus.Running; // If has no target, stuck in this state
return TaskStatus.Failure;
}
Debug.Log(target.name);
if (ShouldUpdateDestination())
{
_currentDestination = CalculateDestination(target);
_currentDestination = CalculateDestination(_target);
StartOrUpdateMovement();
}
@ -60,15 +58,6 @@ public override void OnEnd()
StopMovement();
}
private GameObject GetTarget()
{
// Interactor의 포커스된 타겟 검색
var interactor = gameObject.GetComponent<IInteractor>();
var focusedInteractable = interactor?.GetFocusedInteractable();
if (focusedInteractable != null) return focusedInteractable.GetInteractableGameObject();
return null;
}
private bool ShouldUpdateDestination()
{
_repathTimer -= Time.deltaTime;

View File

@ -12,6 +12,8 @@ public class StartRestaurantOrder : Action
[SerializeField] private bool _requireCanInteract = true;
[Tooltip("성공 시 블랙보드에 현재 인터랙션 대상을 등록합니다")]
[SerializeField] private bool _registerOnBlackboard = true;
[Tooltip("성공 시 블랙보드에 현재 인터랙션 대상을 등록합니다")]
[SerializeField] private bool _UnregisterOnBlackboard = false;
private IInteractor _interactor;
private bool _isGetInteractor;
@ -43,9 +45,14 @@ public override TaskStatus OnUpdate()
if (_registerOnBlackboard)
{
// 하위 호환: 고객 전용 블랙보드 지원
var customerBlackboard = gameObject.GetComponent<ICustomerBlackboard>();
customerBlackboard?.SetCurrentInteractionTarget(outInteractable.gameObject);
var customerBlackboard = gameObject.GetComponent<IAISharedBlackboard>();
customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), outInteractable.gameObject);
}
if (_UnregisterOnBlackboard)
{
var customerBlackboard = gameObject.GetComponent<IAISharedBlackboard>();
customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), null);
}
return TaskStatus.Success;

View File

@ -6,8 +6,7 @@ namespace DDD
public class CustomerBlackboardComponent : MonoBehaviour, ICustomerBlackboard, IAISharedBlackboard
{
private Subtree _subtree;
private GameObject _currentInteractionTarget;
public void InitializeWithBehaviorTree(Subtree subtree)
{
_subtree = subtree;
@ -22,18 +21,17 @@ public void SetCustomerData(CustomerData inCustomerData)
if (_subtree == null) return;
_subtree.SetVariableValue(nameof(RestaurantCustomerBlackboardKey.CustomerData), inCustomerData);
}
public void SetCurrentInteractionTarget(GameObject targetGameObject)
public void SetBlackboardGameObject(string key, GameObject inGameObject)
{
_currentInteractionTarget = targetGameObject;
if (_subtree == null) return;
_subtree.SetVariableValue(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), targetGameObject);
_subtree.SetVariableValue(key, inGameObject);
}
public GameObject GetCurrentInteractionTarget()
public GameObject GetBlackboardGameObject(string key)
{
// 캐시 우선 반환. 필요 시 Subtree에서 직접 조회하도록 확장 가능.
return _currentInteractionTarget;
if (_subtree == null) return null;
return _subtree.GetVariable<GameObject>(key)?.Value;
}
}
}

View File

@ -12,7 +12,5 @@ public enum RestaurantCustomerBlackboardKey
public interface ICustomerBlackboard
{
void SetCustomerData(CustomerData inCustomerData);
void SetCurrentInteractionTarget(GameObject targetGameObject);
GameObject GetCurrentInteractionTarget();
}
}