[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 14회차 미션 시작합니다.


저번에 이어 전투시스템 구현입니다.
IAttackable에 대한 인터페이스 함수 구현을 완료하였고, 이번에는 IDamageable에 대한 인터페이스 함수를 구현합니다.

구성되어 있던 IDamageable 인터페이스는 다음과 같았습니다.
public interface IDamageable
{
    bool IsAlive { get; }
    void TakeDamage(int damage, GameObject hitEffectPrefabs);
}


이를 EnemyController_New 스크립트에 구현을 해줍니다.

public class EnemyController_New : EnemyController, IAttackable, IDamageable
{
    // 데미지 관련 체력 변수 및, 초기화 등을 해줍니다.
    
    public Transform hitTransform; // Hit Effect가 발생했을 때의 위치값.
    public int maxHealth = 100; // 최대 체력. 레벨 올라감에 따른 최대 체력 증가 고려.
    public int health
    {
        get;
        private set;
    }
    
    protected override void Start()
    {
        // 기존 구현부..
        
        health = maxHealth;
    }
    

    // IDamageable 구현
    bool IsAlive => health > 0; // 체력 0이상으로 살아있음을 체크
    
    void TakeDamage(int damage, GameObject hitEffectPrefabs)
    {
        if (!IsAlive) return;
        
        health -= damage;
        if (hitEffectPrefabs)
        {
            Instantiate(hitEffectPrefabs, hitTransform);
        }
        
        if (IsAlive)
            animator?.SetTrigger(hitTriggerHash); // 피격 애니메이션 실행
        else
            stateMachine.ChangeState<DeadState>();
    }
}



AttackState_New.cs

public class AttackState_New : State<EnemyController>
{
    private Animator animator;
    private AttackStateController attackStateController;
    private IAttackable attackable;
    
    protected int attackTriggerHash = Animator.StringToHash("AttackTrigger");
    protected int attackIndexHash = Animator.StringToHash("AttackIndex");
    
    pubilc override void OnInitialized()
    {
        animator = context.GetComponent<Animator>();
        attackStateController = context.GetComponent<AttackStateController>();
        attackable = context.GetComponent<IAttackable>();
    }
    
    public override void OnEnter()
    {
        // IAttackable이 구현되어 있지 않았거나, 구현되어 있지만 CoolTime이 안되었다면..
        if (attackable == null || attackable.CurrentAttackBehaviour == null) {
            statemachine.ChangeState<IdleState>();
            return;
        }
        
        attackStateController.enterAttackStateHandler += OnEnterAttackState();
        attackStateController.exitAttackStateHandler += OnExitAttackState();

        animator?.SetInteger(attackIndexHash, attackable.CurrentAttackBehaviour.animationIndex);
        animator?.SetTrigger(attackTriggerHash);
    }
    
    public void OnEnterAttackState()
    {
        // 해당 애니메이션만 변경되므로 처리할 내용은 없음.
    }
    
    public void OnExitAttackState()
    {
        stateMachine.ChangeState<IdleState>();
    }
}




StateMachine이 구현된 상태입니다.




원거리 공격을 위한 projectilePoint이 설정한 화면입니다.

해당 적 캐릭터는 근거리, 원거리 공격 둘 다 가능하므로 Projectile Attack Behaviour와 Melee Attack Behaviour를 둘다 구현해 주면 됩니다.

내용이 완전 쉽지는 않고 캡슐화를 위해 여러 컴포넌트 스크립트와 클래스, 인터페이스들로 인해 좀 정신이 없기는 합니다. 사실 이런 부분은 해당 내용 및 코드를 완벽히 이해한 상태에서 직접 구현해봐야 이해할 수 있습니다.



근접 공격에 대한 내용입니다.
근접 공격에 대한 충돌은 ManualCollision 컴포넌트 스크립트로 자체 구현합니다.


ManualCollision_New.cs

public class ManualCollision_New : MonoBehaviour
{
    public Vector3 boxSize = new Vector3(3, 2, 2);
    
    public Collider[] CheckOverlapBox(LayerMask layerMask)
    {
        return Physics.OverlapBox(transform.position, boxSize * 0.5f, transform.rotation, layerMask);
    }
    
    private void OnDrawGizmos()
    {
        Gizmos.matrix = transform.localToWorldMatrix; // Gizmos의 상태 위치를 World 위치로..
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireCube(Vector3.zero, boxSize);
    }
}




MeleeAttackCollision을 Amphisbaena라는 적 캐릭터의 자식 컴포넌트로 등록하고, 그 안에서 "Manual Collision" 컴포넌트를 등록하여 사용합니다. 자식 노트로 한 이유는 캐릭터를 이동할 때 Collision 영역이 캐릭터를 따라다녀야 편하기 때문이지요.
이제 근접 공격 스크립트를 작성합니다.

AttackBehaviour_Melee.cs

public class AttackBehaviour_Melee : AttackBehaviour
{
    public manualCollision attackCollision;
    
    public override void ExecuteAttack(GameObject target = null, Transform startPoint = null)
    {
        Collider[] colliders = attackCollision?.CheckOverlapBox(targetMask);
        
        foreach (Collider collider in colliders)
        {
            collider.gameObject.GetComponent<IDamagable_Original>()?.TakeDamage(damage, effectPrefabs);
        }
    }
}




드디어 유니티 실행입니다. 플레이를 시작하면 적캐릭터가 따라오며 근접공격이 가능한 경우 근접 공격 애니메이션이 발생됨을 볼 수 있습니다.



실제 해당 공격이 발생되는 시점에 Manual Collision을 보면 캐릭터가 해당 영역 (boxSize)내에 있기 때문에 Damage를 받아 체력이 감소하는 처리를 하게 됩니다.

다음 번에는 원거리 공격을 구현할 예정입니다.



<위의 코드들은 제가 보면서 주요한 함수, 코드를 확인하기 위해 타이핑한 용도로, 전체 소스코드가 아님에 주의해 주세요. 전체 코드는 교육 수강을 하면 완벽하게 받으실 수가 있답니다 ^^>

패스트캠퍼스 - 올인원 패키지 : 유니티 포트폴리오 완성 bit.ly/2R561g0

 

유니티 게임 포트폴리오 완성 올인원 패키지 Online. | 패스트캠퍼스

게임 콘텐츠 프로그래머로 취업하고 싶다면, 포트폴리오 완성은 필수! '디아블로'와 '배틀그라운드' 게임을 따라 만들어 보며, 프로그래머 면접에 나오는 핵심 개념까지 모두 잡아 보세요!

www.fastcampus.co.kr

 

+ Recent posts