인터페이스씨와 상속씨는 나랑 별로 친하지 않은것같다.
다들 좋다는데 왜 나랑 안친한지 모르겠다
그래서 친해져보려고 두분에 대해서 알아보기로 했다
항상 그렇게 하듯 예제를 통해서 앞으로 이런 개발과정이 있을 때
인터페이스씨 혹은 상속씨가 생각이라도 나도록 게임개발에 쓰일만한 예제들을 찾아서 작성해봐야겠다.
인터페이스(님)
인터페이스는 공통된 기능을 구현할때 사용하면 좋다.
강의에서 사용했던 것 처럼 상호작용, 공격, 데미지 처리 이런곳에 좋은 인터페이스(님) 이다.
이렇게 적고나니 조금은 친한거같기도 하다. 친해질 기회가 별로 없었나보다.
첫번째 인터페이스 예제는 상호작용이다.
// IInteractable 인터페이스를 구현해주고
// 상호작용을 원하는 녀석들에게 달아주자
// 여긴 없지만 인터렉트뿐이 아니라 프롬프트 등으로 텍스트 출력하는것도 매우 좋다
public interface IInteractable
{
void Interact();
}
// 문에 달아주기
public class Door : MonoBehaviour, IInteractable
{
public void Interact()
{
// 문이 열리는 로직
}
}
// 창문에 달아주기
public class Window : MonoBehaviour, IInteractable
{
public void Interact()
{
// 창문이 열리는 로직
}
}
// 플레이어에서 인터페이스를 이용하여 쉽게 상호작용을 구현하자
public class Player : MonoBehaviour
{
void Update()
{
if (Input.GetKeyDown(KeyCode.E)) // 예제라서 이렇게 구현한것 인풋시스템 애용하길
{
RaycastHit hit;
// 레이캐스트에 감지되면
if (Physics.Raycast(transform.position, transform.forward, out hit, 3f))
{ // IInteractable을 TryGetComponent로 예외처리 및 가져오기 시도
if (hit.collider.TryGetComponent<IInteractable>(out IInteractable interactable))
{
interactable.Interact(); // 상호작용 가능한 객체라면 Interact() 호출
}
}
}
}
}
다음은 데미지 처리도 한번 해보자 오늘은 친해지기로 약속했기때문에 고봉밥이다.
// IDamageable 인터페이스 정의
public interface IDamageable
{
void TakeDamage(int amount);
}
// 플레이어
public class Player : MonoBehaviour, IDamageable
{
public int health = 100;
public void TakeDamage(int amount)
{
health -= amount;
if (health <= 0)
{
// 죽었습니다.
}
}
}
// 적
public class Enemy : MonoBehaviour, IDamageable
{
public int health = 100;
public void TakeDamage(int amount)
{
health -= amount;
if (health <= 0)
{
Destroy(gameObject);
}
}
}
// 총알 (무기류) IDamageable이 구현되어있으면 구분없이 각자에게 구현된 TakeDamage를 호출한다
// 너무 좋지 않은가 벌써 심장이 두근거린다
// 나는 이런 재밌는걸 배울때마다 도파민이 분비된다 변태인가보다
public class Bullet : MonoBehaviour
{
public int damage = 10;
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.TryGetComponent<IDamageable>(out IDamageable damageable))
{
damageable.TakeDamage(damage);
}
else
{
Destroy(collision.gameObject);
}
}
}
상속씨에대해서는 아이템을 예로 들어서 한번 보겠다.
아이템은 공통적으로 이름이 있고, 사용할 수 있다.
포션과 무기에 아이템 클래스를 상속시켜보겠다.
// 아이템
public abstract class Item
{
public string itemName;
public abstract void Use(Character character);
}
// 포션에 아이템을 상속시킴
public class HealthPotion : Item
{
public int healAmount = 10;
public HealthPotion()
{
itemName = "체력 포션";
}
public override void Use(Character character)
{
// 사용시 체력회복 로직을 적용시킴
character.Heal(healAmount);
}
}
// 무기에도 아이템을 상속시킴
public class Weapon : Item
{
public int damage = 10;
public Weapon()
{
itemName = "기본 무기";
}
public override void Use(Character character)
{
// 사용 시 공격을 함
character.AttackWithWeapon(damage);
}
}
이런식으로도 사용이 가능하다. 이거는 사실 좀 잘못된 예제인것같다 미안하다
쓰고나니 이럴거면 인터페이스를 쓰는게 맞나 이렇게 하는게 아니라
음.. 이전에 배웠던 상태패턴을 사용한것처럼 상태패턴에 적용하는게 더 친해지기 쉬울것같다.
코드로 얘기하자
// 기본 상태 클래스
public abstract class CharacterState
{
public abstract void EnterState(Character character);
public abstract void UpdateState(Character character);
public abstract void ExitState(Character character);
}
// 대기 상태 클래스
public class IdleState : CharacterState
{
public override void EnterState(Character character)
{
// 아이들 전처리
}
public override void UpdateState(Character character)
{
// 아이들 상태에서 진행할 행동
}
public override void ExitState(Character character)
{
// 후처리
}
}
// 이동 상태 클래스
public class MoveState : CharacterState
{
public override void EnterState(Character character)
{
// 전처리 ex) 애니메이션켜기
}
public override void UpdateState(Character character)
{
// 움직이기 로직 ?
}
public override void ExitState(Character character)
{
// 후처리
}
}
// 공격 상태 클래스
public class AttackState : CharacterState
{
public override void EnterState(Character character)
{
// 전처리
}
public override void UpdateState(Character character)
{
// 공격 로직 ?
}
public override void ExitState(Character character)
{
// 딜레이 끝나면 다른 상태로 전환 ?
}
}
// 캐릭터 클래스
public class Character : MonoBehaviour
{
public CharacterState IdleState = new IdleState();
public CharacterState MoveState = new MoveState();
public CharacterState AttackState = new AttackState();
private void Start()
{
TransitionToState(IdleState); // 초기설정 대기로
}
private void Update()
{
currentState.UpdateState(this); // 현재 상태를 지속적으로 업데이트
}
}
아 나는 상속이랑도 조금은 친했었구나 !