다양한 기록

[Fortress Craft] Damage System 본문

유니티 엔진/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();
         }
     }
 }

플레이어의 대미지 체크는 이런 구조

각 클래스에 맞게 구현해주면 됨