[TIL] 77일차 - Skill 상속 구조 Refactor

김유원·2024년 4월 18일
0

📝 24.04.18

Skill 오브젝트에 들어갈 Skill이라는 클래스 스크립트를 Player Skill과 Enemy Skill이라는 자식 스크립트로 분리해야할 필요를 느껴서 수정했다.

기존의 Skill.cs

using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class Skill : MonoBehaviour
{
    public Animator anim;

    public SkillInfoData data {  get; set; }
    private Player player;

    private Vector3 leftDirection = new Vector3(2f, 2f, 1f);
    private Vector3 rightDirection = new Vector3(-2f, 2f, 1f);

    private void OnEnable()
    {
        player = GameManager.Instance.player;

        if(player != null)
        {
            SetTransform();
            CheckType();
        }
    }

    private void CheckType()
    {
        switch(player.Data.StatusData.JobType)
        {
            case JobType.Archer:
                StartCoroutine(ShootSkill());
                break;
            default:
                StartCoroutine(WaitForAnimationEnd());
                break;
        }
    }

    IEnumerator WaitForAnimationEnd()
    {
        do
        {
            yield return null;
        } while (anim.GetCurrentAnimatorStateInfo(0).normalizedTime < 1);

        gameObject.SetActive(false);
    }

    IEnumerator ShootSkill()
    {
        if(data != null)
        {
            Vector3 originalPosition = transform.position;
            Vector3 targetPosition = originalPosition + (player.Controller.isLeft ? new Vector3(data.Range * -1, 0, 0) : new Vector3(data.Range, 0, 0));

            do
            {
                transform.position = Vector3.MoveTowards(transform.position, targetPosition, Time.deltaTime * 7f);
                yield return null;
            } while (transform.position != targetPosition);

            gameObject.SetActive(false);
        }
    }

    private void SetTransform()
    {
        Vector3 plus = new Vector3(-0.5f, 0, 0);
        if (!player.Controller.isLeft)
        {
            plus.x *= -1f;
            Flip(false);
        }
        else Flip(true);
        transform.position = player.transform.position + plus;
    }

    private void Flip(bool isLeft)
    {
        transform.localScale = isLeft ? leftDirection : rightDirection;
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        IDamageable damageable = collision.gameObject.GetComponent<IDamageable>();

        if(damageable != null)
        {
            damageable.TakeDamage(player.Data.StatusData.Atk + data.Damage);
            gameObject.SetActive(false);
        }
    }
}

리팩토링 Skill.cs

using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class Skill : MonoBehaviour
{
    public Animator anim;

    [SerializeField]
    public SkillInfoData data;

    protected IDamageable damageable;

    protected void CheckType()
    {
        if(data.Range > 0)
        {
            StartCoroutine(ShootSkill());
        } else
        {
            StartCoroutine(WaitForAnimationEnd());
        }
    }

    IEnumerator WaitForAnimationEnd()
    {
        do
        {
            yield return null;
        } while (anim.GetCurrentAnimatorStateInfo(0).normalizedTime < 1);

        gameObject.SetActive(false);
    }

    IEnumerator ShootSkill()
    {
        if(data != null)
        {
            Vector3 originalPosition = transform.position;
            Vector3 targetPosition = originalPosition + GetTargetPosition();

            do
            {
                transform.position = Vector3.MoveTowards(transform.position, targetPosition, Time.deltaTime * 7f);
                yield return null;
            } while (transform.position != targetPosition);

            gameObject.SetActive(false);
        }
    }

    protected virtual void SetTransform() { }

    protected virtual Vector3 GetTargetPosition() { return Vector3.left; }

    protected virtual void OnCollisionEnter2D(Collision2D collision)
    {
        damageable = collision.gameObject.GetComponent<IDamageable>();
    }
}

대충 가상메서드로 여럿 변경한 것이 주요하고 GetTargetPosition()이라는 새로운 메서드를 만들어서 PlayerSkill과 EnemySkill이 각각 다른 설정을 할 수 있도록 수정했다.

PlayerSkill.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerSkill : Skill
{
    private Player player;

    private Vector3 leftDirection = new Vector3(2f, 2f, 1f);
    private Vector3 rightDirection = new Vector3(-2f, 2f, 1f);

    private void OnEnable()
    {
        player = GameManager.Instance.player;

        if (player != null)
        {
            SetTransform();
            CheckType();
        }
    }

    protected override void SetTransform()
    {
        Vector3 plus = new Vector3(-0.5f, 0, 0);
        if (!player.Controller.isLeft)
        {
            plus.x *= -1f;
            Flip(false);
        }
        else Flip(true);
        transform.position = player.transform.position + plus;
    }

    private void Flip(bool isLeft)
    {
        transform.localScale = isLeft ? leftDirection : rightDirection;
    }

    protected override void OnCollisionEnter2D(Collision2D collision)
    {
        base.OnCollisionEnter2D(collision);

        if (damageable != null)
        {
            damageable.TakeDamage(player.Data.StatusData.Atk + data.Damage);
            gameObject.SetActive(false);
        }
    }

    protected override Vector3 GetTargetPosition()
    {
        return player.Controller.isLeft ? new Vector3(data.Range * -1, 0, 0) : new Vector3(data.Range, 0, 0);
    }
}

아직 EnemySkill는 스킬 오브젝트 프리팹 작업이 더 급해서 못만들고 있지만 얼추 GetTargetPosition() 메서드를 적절하게 재정의하고, OnCollisionEnter2D() 메서드의 damage도 다르게 계산하도록 수정해야 할 듯 하다.

profile
개발 공부 블로그

0개의 댓글

Powered by GraphCDN, the GraphQL CDN