상호작용이 불가능한 상태에서도 모달 UI가 나타나도록 변경
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,3 +14,4 @@ Assets/_Recovery
|
|||||||
Assets/_Recovery.meta
|
Assets/_Recovery.meta
|
||||||
GameData/Backups
|
GameData/Backups
|
||||||
.claude/settings.local.json
|
.claude/settings.local.json
|
||||||
|
AGENTS.md
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
|
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject
|
m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject
|
||||||
GlobalObjectIdHash: 4211758632
|
GlobalObjectIdHash: 1360081626
|
||||||
InScenePlacedSourceGlobalObjectIdHash: 4211758632
|
InScenePlacedSourceGlobalObjectIdHash: 4211758632
|
||||||
DeferredDespawnTick: 0
|
DeferredDespawnTick: 0
|
||||||
Ownership: 1
|
Ownership: 1
|
||||||
@@ -714,6 +714,18 @@ PrefabInstance:
|
|||||||
serializedVersion: 3
|
serializedVersion: 3
|
||||||
m_TransformParent: {fileID: 1710962577221812646}
|
m_TransformParent: {fileID: 1710962577221812646}
|
||||||
m_Modifications:
|
m_Modifications:
|
||||||
|
- target: {fileID: 1325989084779099817, guid: 274613c415998a647a86a5e09950ce41, type: 3}
|
||||||
|
propertyPath: m_Pivot.x
|
||||||
|
value: 0.5
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 1325989084779099817, guid: 274613c415998a647a86a5e09950ce41, type: 3}
|
||||||
|
propertyPath: m_Pivot.y
|
||||||
|
value: 0.5
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 1325989084779099817, guid: 274613c415998a647a86a5e09950ce41, type: 3}
|
||||||
|
propertyPath: m_AnchorMax.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 1325989084779099817, guid: 274613c415998a647a86a5e09950ce41, type: 3}
|
- target: {fileID: 1325989084779099817, guid: 274613c415998a647a86a5e09950ce41, type: 3}
|
||||||
propertyPath: m_AnchorMax.y
|
propertyPath: m_AnchorMax.y
|
||||||
value: 0
|
value: 0
|
||||||
@@ -724,7 +736,11 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 1325989084779099817, guid: 274613c415998a647a86a5e09950ce41, type: 3}
|
- target: {fileID: 1325989084779099817, guid: 274613c415998a647a86a5e09950ce41, type: 3}
|
||||||
propertyPath: m_SizeDelta.x
|
propertyPath: m_SizeDelta.x
|
||||||
value: 4
|
value: 500
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 1325989084779099817, guid: 274613c415998a647a86a5e09950ce41, type: 3}
|
||||||
|
propertyPath: m_SizeDelta.y
|
||||||
|
value: 50
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 1325989084779099817, guid: 274613c415998a647a86a5e09950ce41, type: 3}
|
- target: {fileID: 1325989084779099817, guid: 274613c415998a647a86a5e09950ce41, type: 3}
|
||||||
propertyPath: m_AnchoredPosition.x
|
propertyPath: m_AnchoredPosition.x
|
||||||
@@ -834,6 +850,10 @@ PrefabInstance:
|
|||||||
propertyPath: m_Name
|
propertyPath: m_Name
|
||||||
value: ModalPanel
|
value: ModalPanel
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7839034454177399683, guid: 274613c415998a647a86a5e09950ce41, type: 3}
|
||||||
|
propertyPath: m_fontStyle
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
@@ -878,6 +898,8 @@ MonoBehaviour:
|
|||||||
modalPanel: {fileID: 4694931302848755623}
|
modalPanel: {fileID: 4694931302848755623}
|
||||||
keyText: {fileID: 4193449683656256336}
|
keyText: {fileID: 4193449683656256336}
|
||||||
interactText: {fileID: 8795452566802714605}
|
interactText: {fileID: 8795452566802714605}
|
||||||
|
unavailablePanel: {fileID: 4694931302848755623}
|
||||||
|
unavailableText: {fileID: 8795452566802714605}
|
||||||
defaultKey: E
|
defaultKey: E
|
||||||
--- !u!114 &8795452566802714605 stripped
|
--- !u!114 &8795452566802714605 stripped
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ namespace Northbound
|
|||||||
[SerializeField] private GameObject modalPanel;
|
[SerializeField] private GameObject modalPanel;
|
||||||
[SerializeField] private TextMeshProUGUI keyText;
|
[SerializeField] private TextMeshProUGUI keyText;
|
||||||
[SerializeField] private TextMeshProUGUI interactText;
|
[SerializeField] private TextMeshProUGUI interactText;
|
||||||
|
[SerializeField] private GameObject unavailablePanel;
|
||||||
|
[SerializeField] private TextMeshProUGUI unavailableText;
|
||||||
|
|
||||||
[Header("Settings")]
|
[Header("Settings")]
|
||||||
[SerializeField] private string defaultKey = "E";
|
[SerializeField] private string defaultKey = "E";
|
||||||
@@ -27,6 +29,11 @@ namespace Northbound
|
|||||||
{
|
{
|
||||||
modalPanel.SetActive(false);
|
modalPanel.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unavailablePanel != null)
|
||||||
|
{
|
||||||
|
unavailablePanel.SetActive(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowModal(IInteractable interactable)
|
public void ShowModal(IInteractable interactable)
|
||||||
@@ -54,6 +61,11 @@ namespace Northbound
|
|||||||
{
|
{
|
||||||
modalPanel.SetActive(false);
|
modalPanel.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unavailablePanel != null)
|
||||||
|
{
|
||||||
|
unavailablePanel.SetActive(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateModalContent()
|
public void UpdateModalContent()
|
||||||
@@ -86,5 +98,48 @@ namespace Northbound
|
|||||||
|
|
||||||
return prompt;
|
return prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 상호작용 불가능 메시지를 표시합니다.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="interactable">상호작용 불가능한 대상</param>
|
||||||
|
public void ShowUnavailableMessage(IInteractable interactable)
|
||||||
|
{
|
||||||
|
if (interactable == null)
|
||||||
|
{
|
||||||
|
HideModal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unavailablePanel != null)
|
||||||
|
{
|
||||||
|
// unavailablePanel이 할당된 경우 전용 패널 사용
|
||||||
|
if (modalPanel != null)
|
||||||
|
{
|
||||||
|
modalPanel.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
unavailablePanel.SetActive(true);
|
||||||
|
|
||||||
|
if (unavailableText != null)
|
||||||
|
{
|
||||||
|
string prompt = interactable.GetInteractionPrompt();
|
||||||
|
unavailableText.text = ExtractInteractText(prompt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (modalPanel != null && interactText != null)
|
||||||
|
{
|
||||||
|
// unavailablePanel이 없는 경우 modalPanel을 사용하여 불가능 메시지 표시
|
||||||
|
modalPanel.SetActive(true);
|
||||||
|
|
||||||
|
if (keyText != null)
|
||||||
|
{
|
||||||
|
keyText.text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string prompt = interactable.GetInteractionPrompt();
|
||||||
|
interactText.text = ExtractInteractText(prompt);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace Northbound
|
|||||||
[SerializeField] private PlayerInteraction playerInteraction;
|
[SerializeField] private PlayerInteraction playerInteraction;
|
||||||
|
|
||||||
private IInteractable _currentInteractable;
|
private IInteractable _currentInteractable;
|
||||||
|
private IInteractable _previousUnavailableInteractable;
|
||||||
private bool _isEnabled = false;
|
private bool _isEnabled = false;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
@@ -33,14 +34,13 @@ namespace Northbound
|
|||||||
|
|
||||||
FindModalComponent();
|
FindModalComponent();
|
||||||
|
|
||||||
if (interactableModal != null)
|
if (interactableModal == null)
|
||||||
{
|
|
||||||
interactableModal.HideModal();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
Debug.LogError("[InteractableModalManager] InteractableModal is still null in Start!");
|
Debug.LogError("[InteractableModalManager] InteractableModal is still null in Start!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start()에서 HideModal()을 호출하지 않음 - 첫 번째 Update에서 Modal이 표시되지 않는 문제 방지
|
||||||
|
// modalPanel과 unavailablePanel은 InteractableModal.Start()에서 이미 false로 설정됨
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FindModalComponent()
|
private void FindModalComponent()
|
||||||
@@ -88,16 +88,26 @@ namespace Northbound
|
|||||||
_isEnabled = true;
|
_isEnabled = true;
|
||||||
|
|
||||||
IInteractable detectedInteractable = GetDetectedInteractable();
|
IInteractable detectedInteractable = GetDetectedInteractable();
|
||||||
|
IInteractable unavailableInteractable = playerInteraction.CurrentUnavailableInteractable;
|
||||||
|
|
||||||
if (detectedInteractable != _currentInteractable)
|
bool interactableChanged = detectedInteractable != _currentInteractable;
|
||||||
|
bool unavailableChanged = unavailableInteractable != _previousUnavailableInteractable;
|
||||||
|
|
||||||
|
if (interactableChanged || unavailableChanged)
|
||||||
{
|
{
|
||||||
_currentInteractable = detectedInteractable;
|
_currentInteractable = detectedInteractable;
|
||||||
|
_previousUnavailableInteractable = unavailableInteractable;
|
||||||
|
|
||||||
if (_currentInteractable != null)
|
if (_currentInteractable != null)
|
||||||
{
|
{
|
||||||
Debug.Log($"[InteractableModalManager] Show modal for interactable");
|
Debug.Log($"[InteractableModalManager] Show modal for interactable");
|
||||||
ShowModal(_currentInteractable);
|
ShowModal(_currentInteractable);
|
||||||
}
|
}
|
||||||
|
else if (unavailableInteractable != null)
|
||||||
|
{
|
||||||
|
Debug.Log($"[InteractableModalManager] Show unavailable message");
|
||||||
|
ShowUnavailableMessageModal(unavailableInteractable);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Log($"[InteractableModalManager] Hide modal");
|
Debug.Log($"[InteractableModalManager] Hide modal");
|
||||||
@@ -149,6 +159,14 @@ namespace Northbound
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ShowUnavailableMessageModal(IInteractable interactable)
|
||||||
|
{
|
||||||
|
if (interactableModal != null)
|
||||||
|
{
|
||||||
|
interactableModal.ShowUnavailableMessage(interactable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateModalContent()
|
private void UpdateModalContent()
|
||||||
{
|
{
|
||||||
if (interactableModal != null)
|
if (interactableModal != null)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ namespace Northbound
|
|||||||
|
|
||||||
private PlayerInputActions _inputActions;
|
private PlayerInputActions _inputActions;
|
||||||
private IInteractable _currentInteractable;
|
private IInteractable _currentInteractable;
|
||||||
|
private IInteractable _unavailableInteractable;
|
||||||
private Camera _mainCamera;
|
private Camera _mainCamera;
|
||||||
private Animator _animator;
|
private Animator _animator;
|
||||||
private EquipmentSocket _equipmentSocket;
|
private EquipmentSocket _equipmentSocket;
|
||||||
@@ -45,6 +46,7 @@ namespace Northbound
|
|||||||
|
|
||||||
public bool IsInteracting => _isInteracting;
|
public bool IsInteracting => _isInteracting;
|
||||||
public float WorkPower => workPower;
|
public float WorkPower => workPower;
|
||||||
|
public IInteractable CurrentUnavailableInteractable => _unavailableInteractable;
|
||||||
|
|
||||||
public override void OnNetworkSpawn()
|
public override void OnNetworkSpawn()
|
||||||
{
|
{
|
||||||
@@ -92,30 +94,42 @@ namespace Northbound
|
|||||||
{
|
{
|
||||||
Vector3 origin = rayOrigin.position;
|
Vector3 origin = rayOrigin.position;
|
||||||
Vector3 direction = useForwardDirection ? transform.forward : _mainCamera.transform.forward;
|
Vector3 direction = useForwardDirection ? transform.forward : _mainCamera.transform.forward;
|
||||||
|
|
||||||
Ray ray = new Ray(origin, direction);
|
Ray ray = new Ray(origin, direction);
|
||||||
|
|
||||||
if (showDebugRay)
|
if (showDebugRay)
|
||||||
{
|
{
|
||||||
Debug.DrawRay(ray.origin, ray.direction * interactionRange,
|
Debug.DrawRay(ray.origin, ray.direction * interactionRange,
|
||||||
_currentInteractable != null ? Color.green : Color.yellow);
|
_currentInteractable != null ? Color.green : Color.yellow);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Physics.Raycast(ray, out RaycastHit hit, interactionRange, interactableLayer))
|
if (Physics.Raycast(ray, out RaycastHit hit, interactionRange, interactableLayer))
|
||||||
{
|
{
|
||||||
IInteractable interactable = hit.collider.GetComponent<IInteractable>();
|
IInteractable interactable = hit.collider.GetComponent<IInteractable>();
|
||||||
|
|
||||||
if (interactable == null)
|
if (interactable == null)
|
||||||
interactable = hit.collider.GetComponentInParent<IInteractable>();
|
interactable = hit.collider.GetComponentInParent<IInteractable>();
|
||||||
|
|
||||||
if (interactable != null && interactable.CanInteract(OwnerClientId))
|
if (interactable != null)
|
||||||
{
|
{
|
||||||
_currentInteractable = interactable;
|
if (interactable.CanInteract(OwnerClientId))
|
||||||
return;
|
{
|
||||||
|
_currentInteractable = interactable;
|
||||||
|
_unavailableInteractable = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// CanInteract가 false인 경우 추적
|
||||||
|
_currentInteractable = null;
|
||||||
|
_unavailableInteractable = interactable;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentInteractable = null;
|
_currentInteractable = null;
|
||||||
|
_unavailableInteractable = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInteract(InputAction.CallbackContext context)
|
private void OnInteract(InputAction.CallbackContext context)
|
||||||
|
|||||||
Reference in New Issue
Block a user