2025년, 코딩은 선택이 아닌 필수!

2025년 모든 학교에서 코딩이 시작 됩니다. 먼저 준비하는 사람만이 기술을 선도해 갑니다~

응용프로그래밍/유니티기초

[유니티기초] 2-02. 다형성과 인터페이스

파아란기쁨1 2022. 5. 31. 16:17
반응형
목표

1. 다형성이 무엇인지 알아보고 구현하는 방법을 살펴 보자.

2. 인터페이스 사용법을 알아 보자

 

이론

1. 다형성

플레이어와 적이 있다면 공통적으로 생명체로 동작하게 되며 생명력과 누군가에게 데미지를 입히거나 다른 생명체로 부터 데미지를 얻을 수 있다.

이러한 생명체 클래스는 부모의 구현을 재사용 가능하며 부모클래스 타입으로 일괄 처리가 가능하다.

 

1. 상속관계에서의 다형성

몬스터가 있고 몬스터의 종류에는 오크와 드래곤이 있다고 가정해 보자.

몬스터의 속성으로는 데미지가 있고 공격을 할 수 있는 능력이 있다고 하면 몬스터 클래스를 다음과 같이 구현 할 수 있다.

public class Monster : MonoBehaviour{
    public void Attack(){
        Debug.Log("공격");
    }
}

테스트 하기 위해 Dragon Warrior를 에셋에서 다운받아서 캐릭터를 하나 추가하자.

2022.05.31 - [응용프로그래밍/유니티기초] - [유니티기초]2-01.에셋스토어에서 2D 이미지 다운받아 적용하기

orc 도 다운받아 캐릭터를 추가하자.(Orc Warrior Cartoon Character)

다음으로 Orc 와 Dragon 을 다음과 같이 Monster 를 상속 받아서 스크립트를 작성하자.

public class Orc : Monster{
    
    public void WarCry(){
        Debug.Log("전투함성");
    }
}

Orc 는 몬스터를 상속 받아서 WarCry() 메서드를 추가하자

public class Dragon : Monster{
    public void Fly(){
        Debug.Log("날기");
    }
}

 Dragon 에는 Fly() 메서드를 추가하자.

 

각각의 객체에 스크립트를 추가하자.

 

이렇게 만들게 되면 오크와 드래곤은 Monster를 상속하므로 Monster 타입으로 취급 할 수 있다.

 

GameManager 에서 다음과 같이 Orc 씬을 찾아서 Monster의 Attack() 을 실행 해 보자.

Orc orc = FindObjectOfType<Orc>(); //씬에서 오크를 찾음
Monster monster = orc; //몬스터 타입의 변수에 오크를 할당
monster.Attack(); //실행가능
monster.WarCry(); //실행 불가능

이 때 monster 의 Attack 는 실행 가능하지만 WarCry 는 실행이 불가능하다. 이것은 Monster 에는 WarCry 가 없기 때문이다.

 

유니티에서는 객체는 MonoBehaviour 를 상속 받아야 이벤트 처리가 가능 하므로 다중상속을 해야 하는데 C#에서는 다중상속을 지원하지 않는다.

따라서 위의 코드를 유니티에서 실행해 보기 위해서는 Monster 를 인터페이스 형태로 만든 후에 Orc와 Dragon 이 인터페이스를 상속 받을 수 있다.

public interface IMonster 
{
    public void Attack()
    {
        Debug.Log("공격");
    }

}
public class Orc : MonoBehaviour, IMonster
{
    public void WarCry()
    {
        Debug.Log("전투함성");
    }
}
public class Dragon : MonoBehaviour, IMonster
{
    public void Fly()
    {
        Debug.Log("날기");
    }
}

위와 같이 코드를 변경 후 게임매니저에서 다음과 같이 호출을 하면 monster의 Attack() 이 호출 되는 것을 확인 할 수 있다.

        Orc orc = FindObjectOfType<Orc>(); //씬에서 오크를 찾음
        IMonster monster = orc; //몬스터 타입의 변수에 오크를 할당
        monster.Attack(); //실행가능

2. 인터페이스

인터페이스로 정의한 메서드는 추상클래스와 비슷한 개념을 가지게 된다.

인터페이스에서 정의한 메서드는 상속 받은 객체 클래스에서 구현을 해 주어야 한다.

위의 예에서 Monster 는 Attack 하는 기능과 Say하는 기능이 있다고 하면 Attack 은 인터페이스에서 구현을 했지만 Say 는 상속 받은 객체에서 구현을 해야 한다고 하면 다음과 같이 구현할 수 있다.

public interface IMonster 
{
    public void Attack();
    public void Say(); //여기서는 정의만 한다.
}
public class Orc : MonoBehaviour,IMonster
{
    public void WarCry()
    {
        Debug.Log("전투함성");
    }

    public void Attack(){
        Debug.Log("Orc가 공격을 합니다.");
    };
    
    public void Say(){
        Debug.Log("Orc가 말을 합니다.");
    }; 
}
public class Dragon : MonoBehaviour,IMonster
{
    public void Fly()
    {
        Debug.Log("날기");
    }

    public void Attack(){
        Debug.Log("Dragon이 공격을 합니다.");
    }

    public void Say(){
        Debug.Log("Dragon이 말을 합니다.");
    } 

}

이렇게 하면 IMonster 를 상속 받은 경우 무조건 Attack 과 Say 메서드가 구현 되어 있음이 보장 된다.

 

그렇다면 Player 와 드래곤이나 오크가 부딪혔을때 몬스터의 기능인 Say() 하는 것을 구현해 봅시다.

 

PlayMovement 를 다음과 같이 구현 합니다.

    private void OnCollisionEnter2D(Collision2D other) {
        if(other.gameObject.tag=="bottom"){
            //Die(); 
        }
        IMonster monster = other.gameObject.GetComponent<IMonster>();
        if(monster!=null) monster.Say();
    }

이동하여 가까이 갔을때 말을 하는 것을 확인 할 수 있다.

반응형