상세 컨텐츠

본문 제목

#15. 인터페이스(Interface)

유니티 학습/세미나 자료

by 남민우_ 2024. 8. 5. 15:50

본문

1. 인터페이스란?

상속 클래스에서 함수or프로퍼티 만들기를 강제한다

=> 공통적인 기능을 한번에 구현할 때 사용

더보기

프로퍼티(Property)는 part17에서 진행

 

2. 실습 : 아이템 만들기

기본 코드 상태 : PlayerCtrl  - 플레이어 이동 구현

 

에디터 내부 구현

3D가 아닌 2D로 개발을 진행한다

 

1. Player 오브젝트 만들고, '기본 코드 상태' 로 만들었던 PlayerCtrl 스크립트 추가.

더보기

플레이어 코드 

실습과 연결되는 내용은 아니니 따라써도 무

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

public class PlayerCtrl : MonoBehaviour
{
    public float playerSpeed = 10f;
    public float jumpSpeed = 5f;
    private Rigidbody2D rid2D;
		public int gold = 0;
    // Start is called before the first frame update
    void Start()
    {
        rid2D = GetComponent<Rigidbody2D>(); 
    }

    // Update is called once per frame
    void Update()
    {
        Move();
    }

	private void Move()
	{
        Vector2 currentVelocity = rid2D.velocity;
				float h = Input.GetAxisRaw("Horizontal");
        currentVelocity.x = h * playerSpeed;
        if(Input.GetButtonDown("Jump"))
        {
            currentVelocity.y = jumpSpeed;
        }
        rid2D.velocity = currentVelocity;
	}
}

2. Plane 오브젝트 만들고, 2D BoxCollider 컴포넌트 추가

 

여기까지 하면 바닥 위에 플레이어가 움직일 수 있는 코드가 작성된다.

이제 플레이어와 상호작용 할 아이템을 만들 것이다.

 

3. 'Gold Item' 추가

2DObject - Circle 생성

 

코드

public class GoldItem : MonoBehaviour
{
    public int goldAmount = 100;
    
    public void Use()
    {
        Debug.Log("골드 획득!");
        gameObject.SetActive(false);

        PlayerCtrl player = FindObjectOfType<PlayerCtrl>();
        player.gold += goldAmount;
    }
}

 

여기서 Use() 함수를 잠깐 기억해두자.

더보기

코드 설명

 

1. gameObject.SetActive(false)

자기 자신을 비활성화 하는 코드.

일반적으로 메모리 효율을 위해 Destroy를 사용하지만 이번 코드에서는 편의를 위해 간략하게 사용

 

2. PlayerCtrl player = FindObjectOfType<PlayerCtrl>();

PlayerCtrl 스크립트 컴포넌트가 추가된 객체를 찾아서 player 변수에 할당하는 코드.

 

코드 추가 : PlayerCtrl

private void OnTriggerEnter2D(Collider2D other)
{
        GoldItem goldItem = other.GetComponent<GoldItem>();
        if(goldItem != null ) 
        {
            goldItem.Use();
        }
}
더보기

코드 설명

 

1. GoldItem goldItem = other.GetComponent<GoleItem>();

OnTriggerEnter2D를 통해 자기 자신과 부딪힌 객체를 other에 할당한다 : 이번 실습에서는 GoldItem 이 이에 해당함.

이후 other에 할당된 객체의 'GoldItem'이라는 컴포넌트를 찾고, 그 컴포넌트가 할당되었다면 Use() 함수를 사용한다.

 

에디터 설정

색을 따로 노란색으로 바꿔주었다

아까 만든 GoldItem 에 해당하는 객체에 'GoldItem' 스크립트, Box Collider2D 컴포넌트를 추가한다.

 : 이때, Box Collider2D 컴포넌트의 'is Trigger'를 체크해야 한다.

더보기

isTrigger

해당 객체가 다른 객체와 충돌할 수 있는지 체크하는 기능

조금 빠른 속도로 준비과정을 밟았으니, 이제 플레이를 하면서 결과를 봐보자.

 

실행 결과

'골드 획득!' 이라는 디버그 로그 출력 모습

플레이 시 Player를 조작하여 Gold Item 에 닿으면 플레이어의 골드량이 늘어난다.

 

 2-1. 아이템은 하나가 아니다.

이렇게 GoldItem 자체는 만들었지만, 플레이를 하다보면 아이템은 한 종류가 아닐 수 있다.

만약 장비 아이템, 소비 아이템 등 다른 종류의 아이템을 추가하고자 한다면 어떡할까?

단순히 GoldItem 을 만들 때의 과정을 반복한다면 코드가 늘어나고 번거로울 것이다.

 

우리는 GoldItem을 만들면서 아이템을 사용하는 함수가 위에서 언급한 'Use()' 함수라는 것을 알고 있다.

따라서 이 Use() 함수만 동일하게 사용하고 그 내부 코드만 다르게 하면 되지 않을까? 라는 추측을 할 수 있고,

이때 인터페이스를 사용한다.

 

3. 인터페이스

어떠한 함수를 만들기를 강제할 뿐 그 내부의 기능에는 관여하지 않는다.

 

코드를 통해 알아보자

 

코드

public interface IItem
{
	void Use();
}

 

새로운 스크립트를 생성해서, class 대신 'interface' 를 적용한다.

또한 기존에 상속하던 MonoBehaviour 를 지우고 아무것도 상속하지 않는다.

코드 구현은 Use() 함수만 선언하고 그 내부 기능은 자식 클래스에서 맡길 것이다.

 

코드 변경 : GoldItem

public class GoldItem : MonoBehaviour, IItem 
{
	//기존과 동일
}

 

GoldItem 클래스를 MonoBehaviour 와 IItem 둘 모두 상속받는 '이중 상속' 상태를 만든다.

처음 언급한 인터페이스의 특징대로, IItem 을 상속받는 순간 Use() 함수를 강제적으로 구현해야 한다.

 

코드 변경 : PlayerCtrl

private void OnTriggerEnter2D(Collider2D other)
{
        IItem item = other.GetComponent<IItem>();
        if(item != null) 
        {
            item.Use();
        }
}

 

OnTriggerEnter2D 의 내부 코드를 수정할 것이다.

IItem 을 찾도록 하여, 아이템 각각의 Use() 가 아니라 IItem 의 Use() 함수를 사용하도록 변경한다.

따라서 코드가 더욱 간결해질 것이다.

 

더보기

Q. 왜 코드가 간결해지나?

아이템을 사용하는 것은 플레이어가 한다 : OnTriggerEnter2D 코드

아이템의 기능 구현은 각자의 내부에서 하되, 기능을 갖도록 강제하는 interface를 통해

플레이어는 자신이 닿은 아이템이 어떤 아이템인지도 모르는 상태에서도 기능 자체는 동작할 수 있도록 구현하는 것이다.

따라서 코드를 위처럼 작성하면, GoldItem, EXItem 등 하나하나 코드를 작성하는 것이 아니라 IItem 의 Use() 하나로 모든 아이템을 동작시킬 수 있게 된다.

그럼 실제 사용을 위해 다른 아이템을 추가해보자

 

코드 추가

public class HealthItem : MonoBehaviour, IItem
{
    public int healthAmount = 10;
	public void Use()
	{
		Debug.Log("체력바 획득!");
		gameObject.SetActive(false);

		PlayerCtrl player = FindObjectOfType<PlayerCtrl>();
		player.health += healthAmount;
	}
}

 

GoldItem 과 내부기능만 다를 뿐 Use() 함수를 동일하게 사용한다 : IItem 인터페이스 사용

 

에디터 설정

2DObject - Triangle

HealthItem 객체를 만들고 스크립트 추가 및 BoxCollider2D 컴포넌트 추가 - isTrigger 체크

 

 

실행 결과

'체력바 획득!' 디버그 로그 출력 모습

플레이어는 IItem의 Use() 만을 사용하지만 GoldItem 과 HealthItem 의 Use() 기능을 모두 사용 가능하다.

 

4. 정리

인터페이스

1. 함수 등 내부 기능을 갖지만 정의 없이 선언만 사용한다.

2. 상속받는 자식 클래스에세 내부 기능을 구현할 것을 강제한다.

3. 자식들은 자신의 용도에 맞게 내부 기능을 각자 구현한다.

4. 해당 기능을 사용하는 객체는 인터페이스에서 호출하도록 하여, 객체 호출의 편의성을 갖는다.

'유니티 학습 > 세미나 자료' 카테고리의 다른 글

#17. 프로퍼티(Property)  (0) 2024.08.05
#16. 추상 클래스(Abstract Class)  (0) 2024.08.05
#14. 오버라이드(Override)  (0) 2024.08.03
#13. 다형성  (0) 2024.08.03
#12. 상속 심화  (0) 2024.08.02

관련글 더보기