Unity Chapter 7-5. C# 프로그래밍 [중급] (2/2) : 인터페이스
카테고리: Unity Lesson 1
태그: C Sharp Unity Game Engine
인프런에 있는 이제민님의 레트로의 유니티 C# 게임 프로그래밍 에센스 강의를 듣고 정리한 필기입니다. 😀
🌜 [레트로의 유니티 C# 게임 프로그래밍 에센스] 강의 들으러 가기!
Chapter 7. C# 프로그래밍 : 중급 (2/2)
🔔 인터페이스
모든 아이템의 공통적인 기능, 모든 직업의 공통적인 특징을 인터페이스
안에 구현함.
Interface
: 인터페이스를 상속받는 자식 클래스들은 인터페이스의 함수나 프로퍼티를 반드시 모두 재정의 해야 한다.
다형성을 통해 부모클래스인
Interface
로 여러 자식들을 한번에 관리할 수 있다.
인터페이스를 쓰지 않은 경우
- Player 가 아이템을 먹으면 Hp 혹은 Gold가 증가하게 하려 한다.
- 아이템들은 충돌 처리를 위해 Collider 컴포넌트에서 Is Trigger 체크를 해준다.
📜 GoldItem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GoldItem : MonoBehaviour
{
public int goldAmount = 100;
public void Use()
{
Debug.Log("골드를 얻었다!");
Player player = FindObjectOfType<Player>(); // 플레이어를 찾아
player.gold += goldAmount; // 플레이어의 골드를 100만큼 증가시킨다.
gameObject.SetActive(false); // 골드 아이템을 획득했으니 꺼준다.
}
}
📜 HealthKitItem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HealthKitItem : MonoBehaviour
{
public int restoreHealth = 100;
public void Use()
{
Debug.Log("체력을 회복했다!");
Player player = FindObjectOfType<Player>(); // 플레이어를 찾아
player.hp += restoreHealth; // 플레이어의 hp를 100만큼 증가시킨다.
gameObject.SetActive(false); // 헬스킷을 획득했으니 꺼준다.
}
}
📜Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float hp = 50;
public int gold = 1000;
private Rigidbody2D m_rigidbody;
private float speed = 3f;
private float jumpSpeed = 5f;
void Start()
{
m_rigidbody = GetComponent<Rigidbody2D>();
}
void Update()
{
Vector2 currentVelocity = m_rigidbody.velocity;
float horizontal = Input.GetAxis("Horizontal");
currentVelocity.x = horizontal * speed;
if(Input.GetButtonDown("jump"))
{
currentVelocity.y = jumpSpeed;
}
m_rigidbody.velocity = currentVelocity;
}
void OnTriggerEnter2D(Collider2D other)
{
GoldItem goldItem = other.GetComponent<GoldItem>();
if(goldItem != null)
{
goldItem.Use();
}
HealthKitItem healthKitItem = other.GetComponent<HealthKitItem>();
if(healthKitItem != null)
{
healthKitItem.Use();
}
}
}
인터페이스를 사용하는 이유
void OnTriggerEnter2D(Collider2D other)
{
GoldItem goldItem = other.GetComponent<GoldItem>();
if(goldItem != null)
{
goldItem.Use();
}
HealthKitItem healthKitItem = other.GetComponent<HealthKitItem>();
if(healthKitItem != null)
{
healthKitItem.Use();
}
// 아아템이 늘어날 수록 이 if문을 계속해서 추가해야한다.
}
- 문제는 실제 게임상에선 아이템 종류가 한 두개가 아니라는 것.
- 아이템이 수십개, 수백개일 경우 아이템마다 GetComponent 해 와서 if문 처리를 하면 코드가 길어지고 복잡해질 것이다.
- 한마디로 노가다다.
Use()
함수는 모든 아이템들이 가지는 공통된 기능이므로 아이템 용 인터페이스 를 만들어 이를 상속받는 모든 자식들이Use()
함수를 구현하게 한다면- 다형성을 사용하여 자식의 타입과 상관없이 부모(인터페이스) 타입 하나로 공통된
Use()
함수를 사용할 수 있다.
- 다형성을 사용하여 자식의 타입과 상관없이 부모(인터페이스) 타입 하나로 공통된
인터페이스를 사용한 경우
- 인터페이스 C# 스크립트의 이름은 무조건 앞에 대문자
I
를 붙여주어야 한다.- 인터페이스 스크립트 📜IItem.cs 를 만들어 주었다.
인터페이스를 상속받는 자식클래스들은 모든 함수 혹은 프로퍼티를 반드시 재정의 하여야한다.
인터페이스 작성하기
📜IItem.cs
public interface IItem
{
void Use();
}
- 스크립트 생성시 기본으로 적혀있는 using UnityEngine, 클래스 등등 전부 다 지워준 후
public interface 인터페이스이름
을 작성해준다.- void Use();
- 이 인터페이스를 상속받을 자식클래스에서 전부 재정의 하도록 함수는 껍데기(프로토타입)만 작성한다.
- 인터페이스는 자식 클래스들이 이를 어떻게 재정의할지는 신경쓰지 않지만 반드시 재정의 하여 이 함수를 가지도록 강제한다.
- 이 인터페이스를 상속받을 자식클래스에서 전부 재정의 하도록 함수는 껍데기(프로토타입)만 작성한다.
인터페이스 상속받고 재정의하기
📜 GoldItem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GoldItem : MonoBehaviour, IItem
{
public int goldAmount = 100;
public void Use() // 오버라이딩
{
Debug.Log("골드를 얻었다!");
Player player = FindObjectOfType<Player>();
player.gold += goldAmount;
gameObject.SetActive(false);
}
}
- public class GoldItem : MonoBehaviour , IItem
- 📜GoldItem 클래스는 부모클래스인 📜IItem 인터페이스도 상속받고 MonoBehaviour도 상속받는다. (다중상속)
- 📜IItem 인터페이스의 함수
Use()
을 반드시 재구현 해야한다.- 함수
Use()
을 오버라이딩 하지 않으면 에러가 난다.
- 함수
📜 HealthKitItem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HealthKitItem : MonoBehaviour, IItem
{
public int restoreHealth = 100;
public void Use()
{
Debug.Log("체력을 회복했다!");
Player player = FindObjectOfType<Player>();
player.hp += restoreHealth;
gameObject.SetActive(false);
}
}
- public class HealthKitItem : MonoBehaviour , IItem
- 📜HealthKitItem 클래스는 부모클래스인 📜IItem 인터페이스도 상속받고 MonoBehaviour도 상속받는다. (다중상속)
- 📜IItem 인터페이스의 함수
Use()
을 반드시 재구현 해야한다.- 함수
Use()
을 오버라이딩 하지 않으면 에러가 난다.
- 함수
정리
📜Player.cs
void OnTriggerEnter2D(Collider2D other) // 코드가 훨씬 깔끔해졌다!.
{
IItem item = other.GetComponent<IItem>();
if(item != null)
{
item.Use();
}
}
- 모든 아이템들은 📜IItem 인터페이스를 상속받기 때문에 Use() 함수를 가지고 있는 것이 보장되어 있다.
- 모든 아이템들은 공통적으로 Use()함수를 가지고 있다.
- 따라서 다형성에 의하여 부모 타입
IItem
하나로 한방에 모든 아이템들의 Use()함수를 실행시킬 수 있다.- IItem item = other.GetComponent<IItem>();
- 어떤 종류의 아이템이든
IItem
타입 하나로 받을 수 있다. - 인터페이스를 사용하니 아이템들을 각각 구별하여 if-else문 혹은 switch문을 사용하여 처리할 필요가 없어졌다.
- 어떤 종류의 아이템이든
- 코드가 훨씬 간결해짐
- 다만, 📜GoldItem 과 📜HealthKitItem 의 각자의 고유한 기능은
IItem
으로 접근할 수 없음.
- IItem item = other.GetComponent<IItem>();
모든 자식 클래스들이 1️⃣ 기본적으로 가지고 있어야 하며 2️⃣ 각자 다양한 방식으로 기능해야 하는 함수라면
인터페이스
에 이 함수를 구현하여 상속 받아 사용하자.
인터페이스만의 특징, 주의사항
- 인터페이스 스크립트는 컴포넌트로서 오브젝트에 붙일 수 없다.
- 그저 자식들이 꼭 구현해야할 함수 목록만 만들어 놓은 껍데기이기 때문이다.
- 찍어낼 수 없다.
- 멤버가 구현되어 있으면 안된다.
- 멤버 변수를 가질 수 없으며
- 함수 또한 전부 프로토타입만 있어야 한다. 구현된 함수를 가질 수 없음.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기