유니티 엔진/Fortress Craft
[Fortress Craft] Damage System
라구넹
2025. 2. 5. 19:37
대미지를 주고 받는 건 AttackCollider, BodyCollider 두가지 스크립트의 상호작용으로 관리
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Fusion;
namespace Agit.FortressCraft
{
public class AttackCollider : NetworkBehaviour
{
public float Damage { get; set; }
public string TargetUnit { get; set; }
public string OwnType { get; set; }
}
}
어택 컬라이더에 설정된 대미지가 바디 컬라이더에 전달
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Fusion;
namespace Agit.FortressCraft
{
public class BodyCollider : NetworkBehaviour
{
public float Damaged { get; set; }
private void Awake()
{
Damaged = 0.0f;
}
[Rpc(RpcSources.All, RpcTargets.All)]
public void RPCSetDamage(float damage)
{
Damaged = damage;
// Debug.Log(transform.parent.name + ": " + damage);
}
public virtual void CallDamageCheck() { }
}
}
바디 컬라이더는 RPC로 대미지를 세팅할 수 있으며,
하위 클래스의 AttackCollider에서 CallDamageCheck()를 부름
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Agit.FortressCraft
{
public class ArrowAttackCollider : AttackCollider
{
private Arrow arrow;
private void Awake()
{
arrow = GetComponent<Arrow>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (TargetUnit == null) return;
if (collision.CompareTag(TargetUnit))
{
if (collision.TryGetComponent<BodyCollider>(out BodyCollider bodycoliider))
{
if (collision.transform.parent != null)
{
if (collision.transform.parent.TryGetComponent<NormalUnitRigidBodyMovement>(
out NormalUnitRigidBodyMovement normal))
{
Debug.Log("Hit! , " + normal.HP + ", " + Damage);
if (normal.HP - Damage * normal.Defense <= 0.0f && !normal.NoReward)
{
normal.NoReward = true;
RewardManager.Instance.Gold += normal.gold;
RewardManager.Instance.Exp += normal.exp;
}
}
}
bodycoliider.RPCSetDamage(Damage);
bodycoliider.CallDamageCheck();
arrow.Release();
}
}
}
}
}
유닛이 쏘는 화살의 AttackCollider를 보면 RPCSetDamage -> CallDamageCheck
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Agit.FortressCraft
{
public class CommanderBodyCollider : BodyCollider
{
Player player;
private void Awake()
{
player = transform.parent.GetComponent<Player>();
}
public override void CallDamageCheck()
{
player.RPCCheckDamaged();
}
}
}
커맨더의 Body Collider를 보면 플레이어의 RPCCheckDamaged를 호출함
[Rpc(RpcSources.All, RpcTargets.All)]
public void RPCCheckDamaged()
{
CheckDamaged();
}
public void CheckDamaged()
{
if (died) return;
if( bodyCollider.Damaged > 0.0f )
{
if( BuffDefenseTimer.Expired(Runner) )
{
life -= bodyCollider.Damaged * (1.0f - 0.01f * Defense);
}
else
{
life -= ( bodyCollider.Damaged * (1.0f - 0.01f * Defense) ) / coefDefense;
}
bodyCollider.Damaged = 0.0f;
if( life <= 0.0f )
{
Die();
}
}
}
플레이어의 대미지 체크는 이런 구조
각 클래스에 맞게 구현해주면 됨