🎮Unreal4/Basic

[UE4] 액터의 생명 주기(Actor Life Cycle), 액터가 소멸될 수 있는 경우, End Play 사용

공대 컴린이 2023. 2. 9. 20:07
728x90

🚧 액터의 생명 주기(Actor Life Cycle)

액터가 스폰되고 나서부터 소멸될때까지의 수명 주기는 매우 중요한 내용이므로 정리해두는 것이 좋다.

 

액터의 수명 주기

🚩 Play in Editor (PIE)

1. 에디터에 있는 액터를 새 월드로 복제합니다.
2. PostDuplicate (복제 이후)를 호출합니다.
3. InitializeActorsForPlay (플레이용 액터 초기화)

Play in Editor는 사용자가 에디터에서 플레이 버튼을 누른 상황을 의미한다.

그러면 모든 액터들을 듀플리케이트해서 게임이 실행될 때 보이는 월드(Level)가 복제된다. 

게임을 실행시키고나서 Enemy의 위치를 옮겨놓으면 Level 상에서만 복제되어 이동된 결과이기 때문에 게임 실행을 끄면 다시 원위치로 돌아온다.

🚩 LoadMap / AddToWorld

1. 패키지/레벨에 있는 액터가 디스크에서 로드됩니다.
2. PostLoad 로드 이후 - 디스크에서의 로드 완료 후 serialize 된 액터에 의해 호출됩니다. 커스텀 버전이나 픽스 작업은 이 곳에 와야 합니다. PostLoadPostActorCreated 와 상호 배제됩니다.
3. InitializeActorsForPlay 플레이용 액터 초기화
4. RouteActorInitialize 액터 초기화 경로변경 - 초기화되지 않은 액터에 대해 호출됩니다 (심리스 트래블 전환 처리)
    a. PreInitializeComponents 컴포넌트 초기화 이전 - 액터의 컴포넌트에 InitializeComponent 를 호출하기 전 호출합니다.
    b. InitializeComponent 컴포넌트 초기화 - 액터에 정의된 각 컴포넌트 생성용 헬퍼 함수입니다.
    c. PostInitializeComponents 컴포넌트 초기화 이후 - 액터의 컴포넌트 초기화 완료 후 호출됩니다.
5. BeginPlay 플레이 시작 - 레벨이 시작되면 호출됩니다.

LoadMap은 맵을 연 상태이고, AddToWorld은 액터를 끌어다가 배치한 상태로, 이미 레벨에 있는 액터에 대해서 액터가 호출되었을 때 발생한다.

가장먼저, 맵을 열거나 액터를 끌어다 배치하고 나면, 디스크에서 액터/에셋들을 다 불러온다.  이후 로드가 끝나면 PostLoad 함수를 콜 하고 플레이용 액터를  초기화시킨다. 이후 컴포넌트들을 초기화하고 나서 Begin Play를 시작하게 된다.

🚩 SpawnActor

액터를 스폰할 때 실행되는 경로이다.

1. SpawnActor (액터 스폰)이 호출됩니다.
2. PostSpawnInitialize (스폰 초기화 이후)가 호출됩니다.
3. PostActorCreated 액터 생성 이후 - 스폰된 액터의 생성 이후에 호출됩니다. 생성자같은 것이 여기에 와야 합니다. PostActorCreated (액터 생성 이후)는 PostLoad (로드 이후)와 상호 배제적입니다.
4. ExecuteConstruction (생성 실행):
    - OnConstruction 생성시 - 액터의 생성 지점으로, 블루프린트 액터가 컴포넌트를 만들고 블루프린트 변수를 초기화시키는 곳입니다.
5. PostActorConstruction (액터 생성 이후):
    a. PreInitializeComponents 컴포넌트 초기화 이전 - 액터의 컴포넌트에서 InitializeComponent (컴포넌트 초기화)가 호출되기 전에 호출됩니다.
    b. InitializeComponent (컴포넌트 초기화) - 액터에 정의된 컴포넌트 각각의 생성을 돕는 함수입니다.
    c. PostInitializeComponents 컴포넌트 초기화 이후 - 액터의 컴포넌트 초기화가 완료된 이후 호출됩니다.
6. OnActorSpawned (액터가 스폰되었을 때)가 UWorld 에 방송됩니다.
7. BeginPlay (플레이 시작)이 호출됩니다.

💥 액터가 소멸될 수 있는 경우

Begin Play가 실행되면 Ticking이 시작되고, 이후에 종료를 시키면 액터가 소멸될 수 있다.

1. Destroy를 호출했을 때

2. Initial Life Time 시간이 끝났을 때

3. 다른 레벨로 액터를 옮겼을 때 기존의 액터들이 파기되는 경우

4. 에디터에서 플레이하고 종료를 눌렀을 때

5. Quit Game을 하여 게임을 끝냈을 때

6. 게임을 그냥 닫았을 때

 

액터가 소멸되고 나면 End Play 함수에 들어가게 된다.

End Play함수는 재정의가 가능하다.

 

이후에 Actor에 펜딩킬 모드에 들어왔다는 마킹을 한 뒤, U Level Array에서 제거한다.

U Level Array of Actors는 월드 아웃라이너에 존재하는 액터들을 배열로 가지고 있다. 아직 소멸된 것은 아니고, 해당 배열에서 소멸될 액터들을 지워준다.

 

이후 다음 사이클에서 가비지 컬렉터가 펜딩킬 마킹된 액터들을 삭제하여 Destroy가 시작되고, 끝나게 된다.

💡End Play 사용

플레이어가 화살을 쏘고 나면 설정된 Life Time 시간 후에 화살이 사라지게 된다.

이때, 사라진 화살을 화살 배열 변수인 Arrows에서 지워줘야 한다.

그 방법으로 재정의가 가능한 End Play 이벤트를 사용하였다. 

 

Skill_Arrow BP

End Play가 실행되면 이벤트 디스패처인 On Arrow Destroyed를 만들어 호출하였다.

 

가변 배열인 Arrows에서 손에 붙은 Arrow만 지워주고 싶다면 어떻게 해야할까?

0,1,2,3 이라는 배열 인덱스가 존재할 때 2번을 제거하고 싶어서 for문을 돌려 지우면

인덱스가 땡겨져서 0,1,3이 된다. 다음 탐색할 인덱스 번호는 3인데, 요소 2가 빠져서 인덱스 3을 찾을 수 없게되어 오류가 난다. 따라서 가변 배열의 요소를 지울 때는 배열의 뒤에서부터 순차적으로 검사해야 한다.

 

사실 언리얼의 Remove 함수를 호출하여 사용하면 매우 간단하게 되지만, 해당 함수의 원리를 아는 것도 좋을 것 같아 정리했다.

 

Weapon_Bow : Unequip

Reverse for Each Loop 함수를 통해 for문을 역순으로 돌리면서 존재하지 않는 즉, 펜딩 킬 상태인 액터를 검사하여 Destroy 해주었다. 


참조

https://docs.unrealengine.com/4.27/ko/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/Actors/ActorLifecycle/

 

액터의 수명 주기

액터가 로드 또는 스폰된 후 결국 죽을 때 벌어지는 일에 대해서입니다.

docs.unrealengine.com

 

728x90