

상속은, 객체지향에서도 다뤘듯이, 부모의 성질을 자식이 물려 받아 구현하는 방식이다. (여기서의 성질은 필드, 메소드 둘다를 의미한다.)
따라서 부모가 갖고 있는 내용에 대한 재정의, 혹은 자식만이 갖고 있는 성질을 덧붙이며 특정 계열에 대한 정의하는데 유리하다.
반면에 인터페이스는 각 클래스가 갖고 있을 기능 만을 떼어내어 해당 기능을 갖고 있어야 할 클래스를 생성할 수 있어 클래서 정의가 유연하다.
뿐만 아니라, 해당 기능을 갖고 있는 클래스에 대한 필터링 역할도 할 수 있어 유용하게 사용할 수 있다.

위에 언급했듯, 상속과 인터페이스 모두 유용하지만, 게임 프로그래밍 적으로 상속의 깊이가 너무 깊어지는 경향이 발생할 수 있다.
이럴 경우 자식클래스에서는 어떤 상속이 되었는지 확인이 어려울 뿐 아니라, 중간 혹은 부모 클래스의 변동에 의해 자식 클래스의 변경이 심할 경우도 발생한다.
또한, 아무래도 상하 관계, 그것도 Top-down 방식의 계승이다보니 확장성이 조금 떨어진다는 문제점도 있다.
인터페이스는 그에 반해 확장성이 매우 뛰어나기 때문에 이를 활용하는 것이 조금 더 유리할 수 있다.
유니티는 기본적으로 컴포넌트 기반의 설계를 권고하고 있다. (에디터 자체도 그렇게 생겼다.)
때문에 인터페이스 기반 디자인인 컴포넌트 패턴을 활용한 설계가 조금 더 유리 할 수 있다.
public interface IMove
{
public void Invoke(Vector2 input);
}
public class PlayerController : MonoBehaviour
{
IMove move;
private void Start()
{
move = GetComponent<IMove>(); // 컴포넌트로 인터페이스를 불러올 수 있다! (꿀기능!!)
}
private void Update()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector2 input = new Vector2(h, v);
move?.Invoke(input);
}
}
싱글톤은 실행되는 프로세스 내 전역적으로 관리되는 유일 무이한 객체를 이용하는 디자인을 말한다.
개인적으로
Python은 기본적으로싱글톤 인터프리터 형식이었기 때문에 이 점에 대해 이해하는 데는 큰 어려움은 없었다.
공유된 메모리내 데이터 및 기능을 사용하기 때문에 접근이 쉽고 관리도 쉽다.
생명주기와 책임을 통제 가능할 때만 사용.DontDestoryOnLoad(gameObject); 지정된 객체가 사라지지 않도록 한다.// GameManager.cs
public class GameManager : MonoBehaviour
{
private static GameManager _instance; // static 주의
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
GenerateManager<SomeManager>();
}
private void GenerateManager<T>() where T: Component
{
if (FindObjectOfType<T>() != null) return;
var go = new GameObject(typeof(T).Name); // 컴포넌트 이름으로 게임 object 인스턴스화
go.AddComponent<T>(); // 컴포넌트 추가 -> Awake 발생
DontDestroyOnLoad(go); // 싱글톤화
}
}
// SomeManager.cs
public class SomeManager : MonoBehaviour
{
public static SomeManager Instance { get; private set; } // static 주의
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
}