[Unity] 다형성 이용하기

ChangBeom·2024년 9월 23일
0

Unity

목록 보기
6/8


객체 지향 언어의 큰 장점 중 하나인 다형성에 대해 알아보자.

다형성은 문자 그대로 해석하면 '여러가지 형태'라는 뜻이다. C#에서 다형성은 자식 클래스를 부모 클래스로 다룰 수 있게 하는 것이다. 조금 더 자세히 설명하자면, 부모 클래스를 상속받아 새로운 메소드도 만들고 기존 부모 클래스의 메소드를 오버라이드하여 다양한 자식클래스를 만드는 것이다.

간단한 예를 들면 몬스터라는 카테고리에는 좀비, 드래곤 등이 포함될 수 있다. 공격한다, 죽는다 등 같이 여러부분 공통점이 있을 것이다. 이럴 때 굳이 좀비와 드래곤에 공통된 부분을 반복해서 작성하는 것이 아니라 부모클래스인 몬스터에 작성하여 효율적으로 코딩하는 것이 다형성을 이용하는 것이다.

<예시> : Monster 다형성 예시

//	Monster.cs
public calss Monster : MonoBehaviour {
	public float damage = 100;
    
    public void Attack() {
    	Debug.Log("공격");
    }
    
   	public void Die() {
    	Debug.Log("죽음");
    }
}

//	Zombie.cs
public class Zombie : Monster {
	public void Revive() {
    	Debug.Log("부활");
    }
}

//	Dragon.cs
public class Dragon : Monster {
	public void Breath() {
    	Debug.Log("불 뿜기")
    }
}

이제 다형성을 활용해서 여러가지 아이템을 만들어보자!

먼저 부모클래스에 작성할 아이템의 공통점에 대해 생각해보자.

  1. 플레이어가 획득하면 사라진다.
  2. 생성되고 시간이 지나면 사라진다.
  3. 획득시 플레이어에게 이로운 효과가 발생한다.

내가 생각했을 땐 이정도가 있는 것 같다. 이제 스크립트로 만들어보자.


// Item.cs

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

public class Item : MonoBehaviour
{
    public virtual void Use()
    {
        Debug.Log("사용");
    }
    public virtual void GetItem()
    {
        Use();
        Destroy(gameObject);
    }

    public virtual void DisappearItem()
    {
        Destroy(gameObject, 10f);
    }
}

Use() -> 해당 아이템의 효과가 즉시 적용된다.
GetItem() -> 아이템을 먹으면 즉시 사용되며 아이템 오브젝트는 사라진다.
DisappearItem() -> 아이템이 생성된지 10초가 지나면 사라진다.

이제 이 부모 클래스를 토대로 회복, 보호막, 맵 전체 총알 없애기 아이템을 만들어보자. 다형성을 이용해 구현하려면 부모클래스에서 구현하는 공통적인 부분에는 virtual이라는 키워드를 사용해서 함수를 만들어야한다. virtual은 자식 클래스에서 해당 함수를 재정의 할 수 있도록 하용한다는 의미이다.

따라서 부모클래스에서 virtual로 만든 함수를 자식클래스에서 override를 이용해서 재정의하면 된다.


//	HealItem.cs

using UnityEngine;

public class HealItem : Item
{
    private void Start()
    {
        DisappearItem();
    }

    // 체력이 최대가 아닐경우 1회복
    public override void Use()
    {
        SoundManager.instance.Heal_Play();

        PlayerHealth playerhealth = GameObject.Find("Player").GetComponent<PlayerHealth>();

        if (playerhealth.Health < 5)
        {
            playerhealth.Health++;
        }
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.tag == "Player")
        {
            GetItem();
        }
    }
}


//	BarrierItem.cs

using UnityEngine;

public class BarrierItem : Item
{
    BarrierRange barrier;
    private void Start()
    {
        barrier = GameObject.Find("Player").transform.Find("barrierRange").gameObject.GetComponent<BarrierRange>();
        DisappearItem();
    }

    //  베리어 생성 (5초간 무적)
    public override void Use()
    {
        SoundManager.instance.Barrier_Play();

        barrier.BarrierStart();
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.tag == "Player")
        {
            GetItem();
        }
    }
}

//	DestroyItem.cs

using UnityEngine;

public class DestroyItem : Item
{
    private void Start()
    {
        DisappearItem();
    }

    // 맵에 있는 모든 총알 제거
    public override void Use()
    {
        SoundManager.instance.Destroy_Play();

        GameObject.Find("Canvas").transform.Find("DestroyImage").gameObject.SetActive(true);
        GameObject.Find("DestroyParent").transform.Find("DestroyRange").gameObject.SetActive(true);
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.tag == "Player")
        {
            GetItem();
        }
    }
}

모든 아이템은 Use 메소드를 오버라이드하여 아이템마다 고유 효과를 만들어줬고, DisappearItem와 GetItem메소드는 부모클래스인 Item의 메소드를 그대로 사용하였다.

[완성]

0개의 댓글