134 lines
4.2 KiB
C#
134 lines
4.2 KiB
C#
using Unity.Netcode;
|
|
using Unity.Netcode.Components;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Northbound
|
|
{
|
|
/// <summary>
|
|
/// 상호작용 대상 없이 실행 가능한 액션들을 관리
|
|
/// </summary>
|
|
public class PlayerActionSystem : NetworkBehaviour
|
|
{
|
|
[Header("Actions")]
|
|
public List<MonoBehaviour> actionComponents = new List<MonoBehaviour>();
|
|
|
|
[Header("Animation")]
|
|
public bool playAnimations = true;
|
|
|
|
private PlayerInputActions _inputActions;
|
|
private Dictionary<string, IAction> _actions = new Dictionary<string, IAction>();
|
|
private Animator _animator;
|
|
private NetworkAnimator _networkAnimator;
|
|
private NetworkPlayerController _networkPlayerController;
|
|
|
|
// 로컬 플레이어인지 확인
|
|
private bool IsLocalPlayer => _networkPlayerController != null && _networkPlayerController.IsLocalPlayer;
|
|
private ulong LocalPlayerId => _networkPlayerController != null ? _networkPlayerController.OwnerPlayerId : OwnerClientId;
|
|
|
|
private void Awake()
|
|
{
|
|
_animator = GetComponent<Animator>();
|
|
_networkAnimator = GetComponent<NetworkAnimator>();
|
|
_networkPlayerController = GetComponent<NetworkPlayerController>();
|
|
}
|
|
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
// 액션 컴포넌트들을 딕셔너리에 등록 (모든 클라이언트에서)
|
|
foreach (var component in actionComponents)
|
|
{
|
|
if (component is IAction action)
|
|
{
|
|
_actions[action.GetActionName()] = action;
|
|
}
|
|
}
|
|
|
|
// _ownerPlayerId 변경 이벤트 구독
|
|
if (_networkPlayerController != null)
|
|
{
|
|
_networkPlayerController.OnOwnerChanged += OnOwnerPlayerIdChanged;
|
|
}
|
|
|
|
// 이미 로컬 플레이어면 입력 초기화
|
|
TryInitializeInput();
|
|
}
|
|
|
|
private void OnOwnerPlayerIdChanged(ulong newOwnerId)
|
|
{
|
|
TryInitializeInput();
|
|
}
|
|
|
|
private void TryInitializeInput()
|
|
{
|
|
if (!IsLocalPlayer) return;
|
|
if (_inputActions != null) return;
|
|
|
|
_inputActions = new PlayerInputActions();
|
|
_inputActions.Player.Attack.performed += OnAttack;
|
|
_inputActions.Enable();
|
|
}
|
|
|
|
public override void OnNetworkDespawn()
|
|
{
|
|
if (_networkPlayerController != null)
|
|
{
|
|
_networkPlayerController.OnOwnerChanged -= OnOwnerPlayerIdChanged;
|
|
}
|
|
|
|
if (_inputActions != null)
|
|
{
|
|
_inputActions.Player.Attack.performed -= OnAttack;
|
|
_inputActions.Disable();
|
|
_inputActions.Dispose();
|
|
}
|
|
}
|
|
|
|
private void OnAttack(InputAction.CallbackContext context)
|
|
{
|
|
// UI가 열려있으면 액션 실행 안 함
|
|
if (UpgradeListPopup.IsOpen) return;
|
|
|
|
ExecuteAction("Attack");
|
|
}
|
|
|
|
public void ExecuteAction(string actionName)
|
|
{
|
|
if (_actions.TryGetValue(actionName, out IAction action))
|
|
{
|
|
if (action.CanExecute(LocalPlayerId))
|
|
{
|
|
string animTrigger = action.GetActionAnimation();
|
|
|
|
// 서버에서 애니메이션 실행 (동기화를 위해)
|
|
if (playAnimations && !string.IsNullOrEmpty(animTrigger))
|
|
{
|
|
PlayAnimationServerRpc(animTrigger);
|
|
}
|
|
|
|
action.Execute(LocalPlayerId);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Rpc(SendTo.Server)]
|
|
private void PlayAnimationServerRpc(string animTrigger)
|
|
{
|
|
if (_networkAnimator != null && !string.IsNullOrEmpty(animTrigger))
|
|
{
|
|
_networkAnimator.SetTrigger(animTrigger);
|
|
}
|
|
}
|
|
|
|
override public void OnDestroy()
|
|
{
|
|
if (_inputActions != null)
|
|
{
|
|
_inputActions.Dispose();
|
|
}
|
|
|
|
base.OnDestroy();
|
|
}
|
|
}
|
|
} |