Script Cycle(2)
Class Body, Class Scope
변수 = 필드(Field)라고도 부름
데이터 변수의 선언을 할 때는 클래스 본문에 선언을 함
변수를 선언하게 되면 public으로 할 시에 인스펙터 상에서 해당 변수에 대한 필드가 표시됨
유니티에서는 변수에 대문자가 있을 때마다 이름에 공백을 삽입하여 띄워서 표시함.
플레이모드에서는 변수의 값을 변경할 때 중지할 필요 없이 바로 효과를 확인할 수 있음
플레이 모드를 중지하게 되면 이전 값으로 재설정됨
데이터 변수가 아닌 객체(Object) 변수의 경우, 필드 선언부에서는 정의 및 인스턴스의 초기화가 불가능하다.
스크립트 사이클에서 필드 초기화 시점은 아직 유니티 게임 공간에서 오브젝트가 생성되지 않은 상태이기 때문에 이를 해당 변수의 메모리에 값을 초기화 해 줄 수가 없음
Default 값을 정의 할때는 이벤트 함수에서 초기화 하기 보다는 필드 전역에서 바로 정의 하는것이 좋다.
생성 즉시 메모리에 할당해주는 것이 가장 빠르고 정확함.
이벤트 함수에서 값을 초기화 하거나 정의하면 인스펙터창에서 설정한 값을 쓰는 것이 아니라 이벤트 함수에서 정의된 값으로 덮어 씌워져버림
Public float speed =10.0f;
가 직관적이지
Public float speed;
Void start()
{
Speed =10.0f;
}
는 직관적으로 값이 안보이고 코드를 직접 확인해봐야 되기 때문에 개발효율이 떨어진다.
또한 단순 기본값을 awake 등에서 정의하면 불필요하게 코드가 길어질 수 있음.
또한 이벤트 함수에 값을 정의하면 오브젝트 생성 타이밍과 안 맞아서 의도치 않은 결과가 나올수도 있음.
데이터는 필드 전역에서 저장 하고,
객체 초기화나 로직 처리 등은 이벤트 함수 등에서 구현
LifeCycle
초기화는
유니티 이벤트 함수들에서
특정 시점에서 해당 동작을 단계별로 수행하도록 되어 있으며
(이를 LifeCycle System 이라고 함, framework의 형태를 띄고 있다.)
해당 단계의 역할 및 용도에 맞게 변수들의 초기화 및 정의 해 주어야 함
CallBack
직접 해당 함수를 호출하는게 아닌 유니티 스크립트에서 c#으로 context를 작성하고 이를 유니티 내부의 native c++에 내용을 호출하여 처리함.
이를 CallBack 함수를 사용한다라고 얘기할 수 있음.
API
Getcomponent, Instantiate, lerp 등의 메서드 등을 사용할대는 API를 사용한다고 얘기할 수 있다.
메서드는 사용하는 것은 API 리스트 중에 하나를 사용한다고 얘기할 수 있다.
Unity Life Cycle - Event Function
공식 문서 주소 : https://docs.unity3d.com/kr/2023.2/Manual/ExecutionOrder.html
이벤트 함수의 실행 순서 - Unity 매뉴얼
Unity 스크립트를 실행하면 사전에 지정한 순서대로 여러 개의 이벤트 함수가 실행됩니다. 이 페이지에서는 이러한 이벤트 함수를 소개하고 실행 시퀀스에 어떻게 포함되는지 설명합니다.
docs.unity3d.com
유니티에서는 엔진에서 게임의 초기화, 생성과 파괴, 랜더링 처리 등을 각 단계별로 수행하는 함수들을 미리 정해진 필드에서 처리하도록 설계 되어 있고 LifeCycle의 순서에 따라서 처리된다.
1. 초기화 그룹 이벤트들
오브젝트준비를 위한 이벤트들, 실행 타이밍의 순서와 목적의 이해가 중요함
Awake: Start 함수 전 객체가 생성될 때 실행됨
용도: 인스턴스 캐싱등에 사용, 내부 데이터 구조 초기화, 상태 초기화
OnEnable: 객체가 활성화될 때마다 함수를 실행,
용도: 생성과 파괴 처리에서 몬스터 생성 등의 이벤트에 사용 가능
Start: 게임 프레임 시작 전에 실행됨
오브젝트가 활성화된 상태에서 start가 호출되므로 초기값 계산 등에 사용
인스턴스 객체 초기화 등에 사용, 런타임에서 업데이트 초기에 되어야 하는 순간 사용
용도: 플레이어 위치 값 찾기, 방향 찾기, 사이즈 크기 계산, 카메라 참조
Reset: 처음에 컴포넌트로 붙여져서 한번의 호출만 하고, 런타임에서는 실행되지 않음,
유니티 공식 문서에 awake -> reset -> start으로 되어 있는데 reset은 런타임에서 동작하는 것이 아닌 editor에서 동작하는 섹션이고, reset is called when the script is attached and not it playmode라 되어 있음
Reset함수를 만들어 두면 unity 인스펙터 창에서 여러 필드의 값들을 기본 default 값으로 초기화 해 줄수 있는 편리한 기능을 가지고 있음
클래스 바디에서는 객체를 초기화 할 때 객체가 생성되어 있지 않은 상태이기 때문에 초기화 하는 코드를 적용할수 없으나
Reset 함수에서는 클래스 인스턴스가 생성되는 시점에 사용하는 것이기에 이렇게 해서
default로 설정해 줄 수 있다.
용도: 스크립트를 오브젝트에 할당 했을 때 reset의 동작을 수행하도록 하여 일일이 값이나 객체를 할당하거나 바꾸지 않아도 바로 실행될 수 있도록 함
2. 프레임 기반 업데이트 이벤트들
FixedUpdate: 주로 물리 기반 로직을 처리할 때 delta frame에 따라서 결과가 바뀌는 것을 방지하기 위해 실행빈도를 고정 값으로 설정함. 매 호출 빈도가 고정되어 있기 때문에 deltatime을 처리할 필요가 없다.
용도: 물리 기반 연산에 필요한 업데이트(터널링, glitch, bullet through paper 효과 방지)
Update: 매 프레임마다 이벤트를 발생, 프레임마다 한번 호출 각 프레임이 생성되는 시간이 다를수 있고, 이에 따라서 이동기반 로직 처리시 프레임 생성 시간에 따라 결과값이 달라질 수 있으므로 deltatime을 통해 일정한 값으로 보간해 준다.
용도: 위치 기반 움직임(translation) 처리
LateUpdate: update의 계산이 완료된 이후에 실행함. update에서 이동에 대한 항목이 끝난 다음에 카메라를 회전시키거나 할 때 사용함
용도: 회전 기반 움직임(rotation) 처리
3. 소멸단계, 비활성화
OnDisable: 비활성화 됨, 오브젝트 씬에는 남아 있지만 렌더링, 물리, 업데이트가 되지 않음, 자주 사용하는 오브젝트라면 메모리 해제했다 다시 올렸다 하면 지연 등이 발생하므로 계속 메모리에 두고 사용하는게 좋음
용도: 자주 나오는 적 죽였을 때 제거(general mobs), UI 숨김,
OnDestroy: 아얘 게임 오브젝트 씬에서 제거되고 메모리도 해제, 코루틴의 종료 되므로 사용하지 않을 객체라면 destory를 사용하는게 맞다.
용도: 자주 나오지 않는 적 죽였을 때 제거(Main Enemy), 파일저장,
4. Scene 정지, 프로세스 종료
OnapplicationPause: 씬의 동작을 잠시 멈추거나 할 때 실행되는 함수, 일시 정지 상태
pc에서 현재 실행 창을 게임이 아닌 다른 창으로 바꿀 때, 휴대폰에서 홈버튼 눌러서 백그라운드 실행 상태가 될 때 실행됨
용도: 세이브 자동화, 게임 일시정지, 음악 사운드 중지, 서버 세션 연결
OnApplicationQuit: 씬을 파괴할 때, 프로세스가 종료 될 때 마지막으로 실행
모바일 환경에서는 백그라운드 실행도중 종료하면 비정상적 종료로 quit 함수 실행이 안되므로 세이브 등은 pause에서 구현하는게 옳다.(호출 보장이 안되기 때문)
용도: 마지막 로그, 세이브(pc환경 등에서)
이밖에도 사용되는 여러 이벤트 함수가 있으나
이는 추후 사용할 때가 되면 다시 정리하 걸로 함
Mainroutine: 프로그램의 시작점
Subroutine: 일반적인 함수의 동작과 동일,
메인루틴에서 호출되는 함수들, 혹은 서브루틴에서도 서브루틴 호출 가능(재귀함수 등)
스택 영역에서 처리되어 연산 다 끝나면 다음 서브루틴으로 넘김
Coroutine: 메인 루틴 안에서 동작하지만 실행 도중 일시 중단되어 다시 실행 될 수 있는 제어 흐름이(flow control) 이 가능한 루틴, 비동기 작업 등의 가능
연산을 한번 실행하면 다음 코루틴에게 제어가 넘어가서 다시 또 돌려받고 등의 비동기 작업 가능 -> 동시성의 역할을 수행
Unity GC(Garbage Collection)
유니티는 스크립트를 작성할 때 c#으로 작성하고 wrapper처리 함. 그리고 유니티 내부 처리는 native c++에서 동작되도록 marshalling 된다.
C#으로 스크립트가 작성되기 때문에 기본적으로 GC가 탑재되어 있으며 GC를 통해 메모리 allocation이 자동으로 해제되기도 하지만 이로 인한 GC 스파이크 등의 문제가 발생할 수 있다.
GC는 .NET 메모리 관리기, 엔진의 동작과는 별개로 동작하며
백그라운드에서 계속 실행되는건 아님,
동작 타이밍 등은 자동이며 힙 공간이 부족해지거나 native c++ 실행중이지 않을 때 등에서 실행되고 프로그래머가 해당 흐름을 제어할 수 없다.
기본적으로 GC가 동작할 때는 stop the world 방식이기(코드 실행을 잠시 멈춤) 때문에
게임실행을 잠시 멈춘 다음 cpu의 참조 상태 등을 그래프 순회함.
이 과정에서 GC spike가 발생하며 게임의 플레이 질을 떨어뜨림.
이를 해결하기 위한 방법으로 incremental GC(점진적 GC)라는 방식을 Unity에서 도입함.
Incremental gc는 메모리를 한번에 처리하지 않고 프레임마다 여러 번 나누어서 조금식 진행하게 되어 스파이크를 완화시킨다.
하지만 기본적으로 메모리 누수 등을 방지해야만 GC Spike를 막을 수 있다.
GC 스파이크를 막기 위해서는
스크립트에서 동적 할당, 혹은 객체 메모리 공간 생성시 반복 생성 조심 등의 많은 수의 객체에서 발생하는 로직 등에 조심을 하자.
Pooling
자주 사용하는 객체를 두고 destory하며 메모리에 지속적으로 할당하는 것이 아니라 비활성화 하여 계속 재사용하도록 함
è New로 생성을 한번 하고 이를 계속 재사용 하므로 GC 부하를 줄일 수 있다.
주의할 점.
C# 영역에 대해서만 gc가 작동하기에 texture, material, mesh, animation 데이터 등에 대해서는
내부 C++동작 , GPU 메모리에서 처리되므로 GC의 대상이 아니다.
'Unity Study' 카테고리의 다른 글
| 2025-12-17_SmoothDamp, Critical Damped Oscillation (1) | 2025.12.17 |
|---|---|
| 2025-12-08_TPS System Basic (0) | 2025.12.08 |
| 2025-12-02_Quaternion(3) (0) | 2025.12.02 |
| 2025-12-01_Parent + Child Hierarchy TRS (0) | 2025.12.01 |
| 2025-11-28 Quaternion(2) (0) | 2025.11.28 |