- Get link
- X
- Other Apps
Recommended Posts
- Get link
- X
- Other Apps
유니티 코어 스크립팅: MonoBehaviour · 이벤트 · 데이터 구조
목표: 유니티의 중심은 코드와 씬의 연결입니다. 본 장에서는 모든 유니티 스크립트의 기반이 되는 MonoBehaviour 클래스의 구조를 이해하고, 이벤트와 데이터 관리 패턴을 통해 게임 로직을 체계적으로 설계하는 방법을 다룹니다.
1. MonoBehaviour의 본질: 유니티의 실행 단위
MonoBehaviour는 유니티에서 모든 사용자 정의 스크립트가 상속받는 핵심 베이스 클래스입니다. 게임 오브젝트에 스크립트를 부착하면, 그 스크립트는 유니티의 이벤트 루프에 자동으로 포함됩니다. 즉, MonoBehaviour는 엔진과 코드 사이의 브리지(bridge) 역할을 수행합니다.
1.1 기본 생명주기 (Lifecycle)
MonoBehaviour에는 엔진이 자동으로 호출하는 일련의 메서드들이 존재합니다. 이를 이해하면, 코드 실행 시점을 명확히 예측할 수 있습니다.
- Awake() — 오브젝트가 처음 생성될 때 1회 호출. 초기화 코드 작성에 적합.
- Start() — 모든 Awake 이후, 씬 시작 시 1회 호출. 다른 오브젝트 의존 초기화에 사용.
- Update() — 매 프레임마다 호출. 입력 처리, 이동, 로직 갱신에 사용.
- FixedUpdate() — 물리 프레임(고정 간격)마다 호출. Rigidbody 연산용.
- LateUpdate() — 모든 Update 이후 호출. 카메라 추적 등 후처리 로직에 적합.
- OnDestroy() — 오브젝트가 제거되기 직전에 호출. 리소스 정리 코드 작성.
⚙️ 예시 코드:
public class PlayerController : MonoBehaviour { private Rigidbody rb;
void Awake() {
rb = GetComponent();
}
void Update() {
if (Input.GetKeyDown(KeyCode.Space)) Jump();
}
void Jump() {
rb.AddForce(Vector3.up * 5f, ForceMode.Impulse);
}
}
이 코드는 입력 이벤트 → 물리 반응 흐름을 MonoBehaviour의 생명주기 안에서 구현한 전형적인 구조입니다.
2. 이벤트 시스템: 객체 간 통신의 핵심
게임 개발에서 오브젝트들은 서로 독립적이지만, 동시에 상호작용이 필요합니다. 이를 해결하기 위한 방법이 바로 이벤트 기반 아키텍처입니다. 유니티는 C#의 delegate 및 event 키워드를 통해 느슨한 결합(loose coupling)을 구현할 수 있도록 설계되어 있습니다.
2.1 기본 C# 이벤트 구조
public class PlayerHealth { public event Action OnHealthChanged; private int health = 100;
public void TakeDamage(int damage) {
health -= damage;
OnHealthChanged?.Invoke(health);
}
}
이 코드는 체력 수치가 변경될 때마다 등록된 모든 리스너에게 알림을 보냅니다. ?.Invoke()
문법은 null-safe 호출을 의미합니다.
2.2 이벤트 구독 패턴
public class UIHealthBar : MonoBehaviour { [SerializeField] private PlayerHealth player;
void OnEnable() {
player.OnHealthChanged += UpdateBar;
}
void OnDisable() {
player.OnHealthChanged -= UpdateBar;
}
void UpdateBar(int currentHealth) {
Debug.Log("현재 체력: " + currentHealth);
}
}
이 방식은 UI와 로직이 서로를 직접 참조하지 않고, 이벤트를 통해 간접적으로 연결됩니다. 이는 유지보수와 디버깅 측면에서 매우 큰 이점을 제공합니다.
2.3 UnityEvent와 차이점
- System.Action 기반 이벤트 — 컴파일 타임 안정성, 코드 기반 연결.
- UnityEvent — 인스펙터에서 드래그로 연결 가능, 직관적이지만 느린 런타임 바인딩.
실무에서는 UI나 간단한 이벤트에는 UnityEvent를, 핵심 시스템 로직에는 Action 기반 이벤트를 권장합니다.
3. 데이터 관리: ScriptableObject와 상태 관리
게임에서는 수많은 데이터(체력, 경험치, 아이템 정보 등)가 존재합니다. 이를 효율적으로 관리하기 위해 유니티는 ScriptableObject라는 데이터 컨테이너 클래스를 제공합니다.
3.1 ScriptableObject의 개념
ScriptableObject는 메모리에 상주하는 데이터 자산(asset)으로, 오브젝트와 독립적으로 존재합니다. 즉, 여러 씬에서 공유 가능한 상태를 정의할 수 있습니다.
[CreateAssetMenu(fileName = "PlayerStats", menuName = "Data/PlayerStats")] public class PlayerStats : ScriptableObject { public int maxHealth = 100; public float moveSpeed = 5f; }
이렇게 생성된 ScriptableObject는 Assets/Data/ 폴더에 저장되며, 인스펙터에서 수정할 수 있습니다.
3.2 런타임에서의 데이터 참조
public class Player : MonoBehaviour { public PlayerStats stats;
void Start() {
Debug.Log($"이동 속도: {stats.moveSpeed}");
}
}
ScriptableObject는 씬과 독립적이기 때문에, 데이터 일관성을 유지하면서도 직렬화(serialization) 오버헤드를 줄입니다.
3.3 실무 활용 패턴
- 상수 데이터: 무기, 아이템, 스킬 설정 등 (CSV 대체용)
- 런타임 상태 저장: 플레이어 상태, 미션 진행 등 (Static 또는 Singleton 조합)
- 이벤트와 결합: 상태 변화 → UI 반영 트리거로 사용
💡 Tip: ScriptableObject를 “데이터 싱글톤”으로 사용하는 패턴은 강력하지만, 저장소와 런타임 상태가 혼동되지 않도록 주의해야 합니다.
4. 코어 스크립팅의 아키텍처적 접근
MonoBehaviour, 이벤트, 데이터 구조는 단순한 문법 요소가 아니라 유니티 아키텍처의 세 축입니다. 이 세 가지를 결합하면, 다음과 같은 구조적 개발이 가능합니다.
- MonoBehaviour — 로직의 실행 단위 (행동 중심)
- 이벤트 — 시스템 간 통신 채널 (반응 중심)
- ScriptableObject — 데이터의 저장소 (상태 중심)
이 조합은 흔히 데이터 기반 아키텍처(Data-Driven Architecture)라고 부르며, 대형 프로젝트에서 유지보수성을 극적으로 향상시킵니다.
정리: 스크립팅의 본질은 “흐름 제어”다
MonoBehaviour는 ‘언제’, 이벤트는 ‘누가’, 데이터는 ‘무엇을’ 제어하는가를 담당합니다. 이 세 가지가 조화를 이루면, 유니티 프로젝트는 단순한 기능 집합이 아니라 의미 있는 시스템으로 진화합니다.
즉, 스크립팅의 본질은 코드를 작성하는 것이 아니라, “게임의 흐름을 제어하는 사고”를 기르는 과정입니다.
✅ 다음 학습 추천:
- 콘텐츠 제작: 씬, 프리팹, UI, 입력 시스템
- 이벤트 기반으로 UI를 갱신하는 미니 프로젝트 실습
Comments
Post a Comment