인터랙션 및 액션 구조 생성
기본 채광 인터랙션 생성 채광 인터랙션을 위한 인터랙션 대상인 광산 생성 Kaykit Resource 애셋 추가
This commit is contained in:
115
Assets/Scripts/AttackAction.cs
Normal file
115
Assets/Scripts/AttackAction.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// 액션 - 공격 (대상 없이도 실행 가능)
|
||||
/// </summary>
|
||||
public class AttackAction : NetworkBehaviour, IAction
|
||||
{
|
||||
[Header("Attack Settings")]
|
||||
public float attackRange = 2f;
|
||||
public int attackDamage = 10;
|
||||
public float attackCooldown = 0.5f;
|
||||
public LayerMask attackableLayer = ~0;
|
||||
|
||||
[Header("Animation")]
|
||||
public string attackAnimationTrigger = "Attack"; // 공격 애니메이션 트리거
|
||||
|
||||
[Header("Visual")]
|
||||
public GameObject attackEffectPrefab;
|
||||
public Transform attackPoint;
|
||||
|
||||
private float _lastAttackTime;
|
||||
private Animator _animator;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_animator = GetComponent<Animator>();
|
||||
}
|
||||
|
||||
public bool CanExecute(ulong playerId)
|
||||
{
|
||||
return Time.time - _lastAttackTime >= attackCooldown;
|
||||
}
|
||||
|
||||
public void Execute(ulong playerId)
|
||||
{
|
||||
if (!CanExecute(playerId))
|
||||
return;
|
||||
|
||||
_lastAttackTime = Time.time;
|
||||
|
||||
// 애니메이션 재생
|
||||
PlayAttackAnimation();
|
||||
|
||||
// 범위 내 적이 있으면 데미지
|
||||
Vector3 attackOrigin = attackPoint != null ? attackPoint.position : transform.position;
|
||||
Collider[] hits = Physics.OverlapSphere(attackOrigin, attackRange, attackableLayer);
|
||||
|
||||
foreach (Collider hit in hits)
|
||||
{
|
||||
// 자기 자신은 제외
|
||||
if (hit.transform.root == transform.root)
|
||||
continue;
|
||||
|
||||
// 적에게 데미지
|
||||
var enemy = hit.GetComponent<IDamageable>();
|
||||
if (enemy != null)
|
||||
{
|
||||
var netObj = hit.GetComponent<NetworkObject>();
|
||||
if (netObj != null)
|
||||
{
|
||||
AttackServerRpc(playerId, netObj.NetworkObjectId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"플레이어 {playerId} 공격! (적중: {hits.Length}개)");
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
private void AttackServerRpc(ulong playerId, ulong targetNetworkId)
|
||||
{
|
||||
if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(targetNetworkId, out NetworkObject targetObj))
|
||||
{
|
||||
var damageable = targetObj.GetComponent<IDamageable>();
|
||||
damageable?.TakeDamage(attackDamage, playerId);
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayAttackAnimation()
|
||||
{
|
||||
// 애니메이션 트리거
|
||||
if (_animator != null && !string.IsNullOrEmpty(attackAnimationTrigger))
|
||||
{
|
||||
_animator.SetTrigger(attackAnimationTrigger);
|
||||
}
|
||||
|
||||
// 이펙트 생성
|
||||
if (attackEffectPrefab != null && attackPoint != null)
|
||||
{
|
||||
GameObject effect = Instantiate(attackEffectPrefab, attackPoint.position, attackPoint.rotation);
|
||||
Destroy(effect, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetActionName()
|
||||
{
|
||||
return "Attack";
|
||||
}
|
||||
|
||||
public string GetActionAnimation()
|
||||
{
|
||||
return attackAnimationTrigger;
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
Vector3 attackOrigin = attackPoint != null ? attackPoint.position : transform.position;
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawWireSphere(attackOrigin, attackRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user