2012年3月8日 星期四

Unreal編輯器的兩個世界

UE的程式碼使用一個全域變數GWorld指向遊戲世界,其型別為UWorld。開發者可以透過這個全域指標呼叫UWorld的函式SpawnActor()來產生Actor,或者呼叫SingleLineCheck()進行射線檢查看看有沒有打中物件。

從Actor:Spawn()不需指定世界可以看得出UE是假設世界只有一個,Actor也沒有提供得知自己身處於哪個世界的方法。或者至少可以退一步說,就算有複數個世界,在呼叫UE前得先把GWorld設定好。

PIE的另一個世界


然而編輯器的PIE(Play in Editor)功能需要有另一個世界以供試玩,才不會在試玩過程中破壞了編輯到一半的關卡。PIE是採用偷天換日的寫法來達成,在同一個frame中適時切換GWorld指向編輯世界和試玩世界,讓兩者輪流更新。主要的相關變數或函式有:
  • UEditorEngine::PlayWorld [UWorld*]:PIE中指向試玩世界,PIE結束時清為NULL。
  • GIsPlayInEditorWorld [UBool]:指示目前是否在試玩世界中。
  • SetPlayInEditorWorld(PIEWorld):設定GWorld為指定的試玩世界,及設定GIsPlayInEditorWorld為TRUE。
  • RestoreEditorWorld(EditorWorld):設定GWorld為指定的編輯世界,及設定GIsPlayInEditorWorld為FALSE。

在其他PIE相關函式中大都會先呼叫SetPlayInEditorWorld()切換到試玩世界,更新試玩世界後再呼叫RestoreEditorWorld()切回編輯世界。所以除了在世界切換間,GWorld是指向原本的編輯世界。
  • PlayInEditor():複製原先的編輯世界建立試玩世界,然後在世界切換間建立PlayerController和ViewportClient,並且呼叫試玩世界的BeginPlay()。
  • EndPlayMap():先設定GWorld為試玩世界,清除試玩世界的相關物件後,再設回GWorld為編輯世界。
  • Tick(DeltaSeconds) :先呼叫GWorld->Tick()更新編輯世界。PIE中會切換三次世界來對試玩世界更新。三次切換間分別呼叫:
    • PlayWorld->Tick():更新試玩世界。
    • GameViewport->Viewport->Draw():繪製畫面。
    • Client->GetAudioDevice()->Update():更新音效系統 。

或許有人會想:那可以用這個方法再建立另一個試玩世界嗎?甚至更多個?然而並不是所有物件都放在UWorld裡,有些是放在GEngine裡,像是LocalPlayer,而LocalPlayer下包含了PlayerController,光是複製世界是不會複製LocalPlayer,這樣PlayerController就不能正確的對應到各別的世界。UE之所以沒問題是因為編輯世界用不到LocalPlayer。若想要建立多個試玩世界,也得一併處理這些需要對應各別世界,卻沒放在UWorld裡的物件。

沒有留言:

張貼留言