Refactor scene objects initialization to call OnAwake before all OnStart

#520
This commit is contained in:
Wojtek Figat
2022-07-17 17:05:59 +02:00
parent 9aff782907
commit 3239150a61
14 changed files with 59 additions and 114 deletions

View File

@@ -6,7 +6,7 @@ EditorScene::EditorScene(const SpawnParams& params)
: Scene(params) : Scene(params)
{ {
// Mock editor preview scene to be in gameplay // Mock editor preview scene to be in gameplay
EditorScene::PostSpawn(); InitializeHierarchy();
SceneBeginData beginData; SceneBeginData beginData;
EditorScene::BeginPlay(&beginData); EditorScene::BeginPlay(&beginData);
beginData.OnDone(); beginData.OnDone();

View File

@@ -1275,7 +1275,7 @@ void Foliage::OnTransformChanged()
// Update instances matrices and cached world bounds // Update instances matrices and cached world bounds
Vector3 corners[8]; Vector3 corners[8];
Matrix world, matrix; Matrix world;
GetLocalToWorldMatrix(world); GetLocalToWorldMatrix(world);
for (auto i = Instances.Begin(); i.IsNotEnd(); ++i) for (auto i = Instances.Begin(); i.IsNotEnd(); ++i)
{ {

View File

@@ -331,7 +331,7 @@ void Actor::SetParent(Actor* value, bool worldPositionsStays, bool canBreakPrefa
ASSERT(_parent != nullptr && GetScene() != nullptr); ASSERT(_parent != nullptr && GetScene() != nullptr);
// Fire events // Fire events
PostSpawn(); InitializeHierarchy();
{ {
SceneBeginData beginData; SceneBeginData beginData;
BeginPlay(&beginData); BeginPlay(&beginData);
@@ -778,13 +778,13 @@ void Actor::BreakPrefabLink()
} }
} }
void Actor::PostLoad() void Actor::Initialize()
{ {
// Cache scene ASSERT(!IsDuringPlay());
// Cache
if (_parent) if (_parent)
_scene = _parent->GetScene(); _scene = _parent->GetScene();
// Cache flag
_isActiveInHierarchy = _isActive && (_parent == nullptr || _parent->IsActiveInHierarchy()); _isActiveInHierarchy = _isActive && (_parent == nullptr || _parent->IsActiveInHierarchy());
// Use lazy creation for the managed instance, just register the object // Use lazy creation for the managed instance, just register the object
@@ -792,32 +792,6 @@ void Actor::PostLoad()
RegisterObject(); RegisterObject();
} }
void Actor::PostSpawn()
{
// Cache scene
if (_parent)
_scene = _parent->GetScene();
// Cache flag
_isActiveInHierarchy = _isActive && (_parent == nullptr || _parent->IsActiveInHierarchy());
// Create managed object
if (!HasManagedInstance())
CreateManaged();
// Init scripts
for (int32 i = 0; i < Scripts.Count(); i++)
{
Scripts[i]->PostSpawn();
}
// Init children
for (int32 i = 0; i < Children.Count(); i++)
{
Children[i]->PostSpawn();
}
}
void Actor::BeginPlay(SceneBeginData* data) void Actor::BeginPlay(SceneBeginData* data)
{ {
// Perform additional verification // Perform additional verification
@@ -853,13 +827,6 @@ void Actor::BeginPlay(SceneBeginData* data)
} }
// Fire events for scripting // Fire events for scripting
for (auto* script : Scripts)
{
CHECK_EXECUTE_IN_EDITOR
{
script->OnAwake();
}
}
if (IsActiveInHierarchy() && GetScene() && !_isEnabled) if (IsActiveInHierarchy() && GetScene() && !_isEnabled)
{ {
OnEnable(); OnEnable();
@@ -1229,6 +1196,17 @@ void Actor::UnregisterObjectHierarchy()
} }
} }
void Actor::InitializeHierarchy()
{
Initialize();
for (int32 i = 0; i < Scripts.Count(); i++)
Scripts[i]->Initialize();
for (int32 i = 0; i < Children.Count(); i++)
Children[i]->InitializeHierarchy();
}
void Actor::Draw(RenderContext& renderContext) void Actor::Draw(RenderContext& renderContext)
{ {
} }
@@ -1685,7 +1663,7 @@ bool Actor::FromBytes(const Span<byte>& data, Array<Actor*>& output, ISerializeM
} }
for (int32 i = 0; i < parents->Count(); i++) for (int32 i = 0; i < parents->Count(); i++)
{ {
parents->At(i)->PostSpawn(); parents->At(i)->InitializeHierarchy();
} }
for (int32 i = 0; i < parents->Count(); i++) for (int32 i = 0; i < parents->Count(); i++)
{ {

View File

@@ -650,6 +650,11 @@ public:
/// </summary> /// </summary>
void UnregisterObjectHierarchy(); void UnregisterObjectHierarchy();
/// <summary>
/// Calls Initialize for all objects in the actor hierarchy.
/// </summary>
void InitializeHierarchy();
public: public:
/// <summary> /// <summary>
/// Draws this actor. Called by Scene Rendering service. This call is more optimized than generic Draw (eg. geometry is rendered during all pass types but other actors are drawn only during GBufferFill pass). /// Draws this actor. Called by Scene Rendering service. This call is more optimized than generic Draw (eg. geometry is rendered during all pass types but other actors are drawn only during GBufferFill pass).
@@ -993,8 +998,7 @@ public:
void SetOrderInParent(int32 index) override; void SetOrderInParent(int32 index) override;
void LinkPrefab(const Guid& prefabId, const Guid& prefabObjectId) override; void LinkPrefab(const Guid& prefabId, const Guid& prefabObjectId) override;
void BreakPrefabLink() override; void BreakPrefabLink() override;
void PostLoad() override; void Initialize() override;
void PostSpawn() override;
void BeginPlay(SceneBeginData* data) override; void BeginPlay(SceneBeginData* data) override;
void EndPlay() override; void EndPlay() override;
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;

View File

@@ -514,10 +514,10 @@ void Spline::OnTransformChanged()
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
} }
void Spline::PostLoad() void Spline::Initialize()
{ {
// Base // Base
Actor::PostLoad(); Actor::Initialize();
auto& keyframes = Curve.GetKeyframes(); auto& keyframes = Curve.GetKeyframes();
const int32 count = keyframes.Count(); const int32 count = keyframes.Count();

View File

@@ -373,7 +373,7 @@ public:
void OnDebugDrawSelected() override; void OnDebugDrawSelected() override;
#endif #endif
void OnTransformChanged() override; void OnTransformChanged() override;
void PostLoad() override; void Initialize() override;
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
}; };

View File

@@ -178,7 +178,7 @@ bool LevelImpl::spawnActor(Actor* actor, Actor* parent)
if (actor->Is<Scene>()) if (actor->Is<Scene>())
{ {
// Spawn scene // Spawn scene
actor->PostSpawn(); actor->InitializeHierarchy();
actor->OnTransformChanged(); actor->OnTransformChanged();
{ {
SceneBeginData beginData; SceneBeginData beginData;
@@ -1052,28 +1052,26 @@ bool Level::loadScene(rapidjson_flax::Value& data, int32 engineBuild, Scene** ou
// TODO: resave and force sync scenes during game cooking so this step could be skipped in game // TODO: resave and force sync scenes during game cooking so this step could be skipped in game
SceneObjectsFactory::SynchronizePrefabInstances(context, prefabSyncData); SceneObjectsFactory::SynchronizePrefabInstances(context, prefabSyncData);
// Call post load event to connect all scene actors // Initialize scene objects
{ {
PROFILE_CPU_NAMED("Post Load"); PROFILE_CPU_NAMED("Initialize");
for (int32 i = 0; i < sceneObjects->Count(); i++) for (int32 i = 0; i < sceneObjects->Count(); i++)
{ {
SceneObject* obj = sceneObjects->At(i); SceneObject* obj = sceneObjects->At(i);
if (obj) if (obj)
obj->PostLoad(); {
} obj->Initialize();
}
// Delete objects without parent // Delete objects without parent
for (int32 i = 1; i < objectsCount; i++) if (i != 0 && obj->GetParent() == nullptr)
{
SceneObject* obj = sceneObjects->At(i);
if (obj && obj->GetParent() == nullptr)
{ {
LOG(Warning, "Scene object {0} {1} has missing parent object after load. Removing it.", obj->GetID(), obj->ToString()); LOG(Warning, "Scene object {0} {1} has missing parent object after load. Removing it.", obj->GetID(), obj->ToString());
obj->DeleteObject(); obj->DeleteObject();
} }
} }
}
}
// Cache transformations // Cache transformations
{ {

View File

@@ -430,7 +430,7 @@ bool PrefabInstanceData::SynchronizePrefabInstances(Array<PrefabInstanceData>& p
for (int32 i = existingObjectsCount; i < sceneObjects->Count(); i++) for (int32 i = existingObjectsCount; i < sceneObjects->Count(); i++)
{ {
SceneObject* obj = sceneObjects.Value->At(i); SceneObject* obj = sceneObjects.Value->At(i);
obj->PostLoad(); obj->Initialize();
} }
// Synchronize existing objects logic with deserialized state (fire events) // Synchronize existing objects logic with deserialized state (fire events)
@@ -470,8 +470,6 @@ bool PrefabInstanceData::SynchronizePrefabInstances(Array<PrefabInstanceData>& p
if (Script* script = dynamic_cast<Script*>(obj)) if (Script* script = dynamic_cast<Script*>(obj))
{ {
if (Editor::IsPlayMode || script->_executeInEditor)
script->OnAwake();
if (script->GetParent() && !script->_wasEnableCalled && script->GetParent()->IsActiveInHierarchy() && script->GetParent()->GetScene()) if (script->GetParent() && !script->_wasEnableCalled && script->GetParent()->IsActiveInHierarchy() && script->GetParent()->GetScene())
script->Enable(); script->Enable();
} }
@@ -1010,7 +1008,7 @@ bool Prefab::ApplyAllInternal(Actor* targetActor, bool linkTargetActorObjectToPr
auto obj = sceneObjects.Value->At(i); auto obj = sceneObjects.Value->At(i);
if (obj) if (obj)
{ {
obj->PostLoad(); obj->Initialize();
} }
} }

View File

@@ -190,9 +190,7 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, Actor* parent, Dictionary<Guid
{ {
auto obj = sceneObjects->At(i); auto obj = sceneObjects->At(i);
if (obj) if (obj)
{ obj->Initialize();
obj->PostLoad();
}
} }
// Synchronize prefab instances (prefab may have new objects added or some removed so deserialized instances need to synchronize with it) // Synchronize prefab instances (prefab may have new objects added or some removed so deserialized instances need to synchronize with it)

View File

@@ -339,24 +339,13 @@ void Scene::OnDeleteObject()
Actor::OnDeleteObject(); Actor::OnDeleteObject();
} }
void Scene::PostLoad() void Scene::Initialize()
{ {
// Initialize // Initialize
_parent = nullptr; _parent = nullptr;
_scene = this; _scene = this;
// Base Actor::Initialize();
Actor::PostLoad();
}
void Scene::PostSpawn()
{
// Initialize
_parent = nullptr;
_scene = this;
// Base
Actor::PostSpawn();
} }
void Scene::BeginPlay(SceneBeginData* data) void Scene::BeginPlay(SceneBeginData* data)

View File

@@ -137,8 +137,7 @@ public:
protected: protected:
// [Actor] // [Actor]
void PostLoad() override; void Initialize() override;
void PostSpawn() override;
void BeginPlay(SceneBeginData* data) override; void BeginPlay(SceneBeginData* data) override;
void OnTransformChanged() override; void OnTransformChanged() override;
}; };

View File

@@ -97,7 +97,6 @@ public:
/// <summary> /// <summary>
/// Determines whether object is during play (spawned/loaded and fully initialized). /// Determines whether object is during play (spawned/loaded and fully initialized).
/// </summary> /// </summary>
/// <returns><c>true</c> if object is during play; otherwise, <c>false</c>.</returns>
FORCE_INLINE bool IsDuringPlay() const FORCE_INLINE bool IsDuringPlay() const
{ {
return (Flags & ObjectFlags::IsDuringPlay) != 0; return (Flags & ObjectFlags::IsDuringPlay) != 0;
@@ -207,14 +206,9 @@ public:
public: public:
/// <summary> /// <summary>
/// Called after whole scene or local group of scene objects deserialization. /// Called after object loading or spawning to initialize the object (eg. call OnAwake for scripts) but before BeginPlay. Initialization should be performed only within a single SceneObject (use BeginPlay to initialize with a scene).
/// </summary> /// </summary>
virtual void PostLoad() = 0; virtual void Initialize() = 0;
/// <summary>
/// Called after spawning scene object to the level (similar to the PostLoad but only for spawned objects at runtime).
/// </summary>
virtual void PostSpawn() = 0;
/// <summary> /// <summary>
/// Called when adding object to the game. /// Called when adding object to the game.

View File

@@ -114,7 +114,7 @@ void Script::SetParent(Actor* value, bool canBreakPrefabLink)
if (value && value->IsDuringPlay() && !IsDuringPlay()) if (value && value->IsDuringPlay() && !IsDuringPlay())
{ {
// Prepare for gameplay // Prepare for gameplay
PostSpawn(); Initialize();
{ {
SceneBeginData beginData; SceneBeginData beginData;
BeginPlay(&beginData); BeginPlay(&beginData);
@@ -122,10 +122,6 @@ void Script::SetParent(Actor* value, bool canBreakPrefabLink)
} }
// Fire events for scripting // Fire events for scripting
CHECK_EXECUTE_IN_EDITOR
{
OnAwake();
}
if (GetEnabled()) if (GetEnabled())
{ {
Start(); Start();
@@ -265,24 +261,21 @@ const Guid& Script::GetSceneObjectId() const
return GetID(); return GetID();
} }
void Script::PostLoad() void Script::Initialize()
{ {
ASSERT(!IsDuringPlay());
if (Flags & ObjectFlags::IsManagedType || Flags & ObjectFlags::IsCustomScriptingType) if (Flags & ObjectFlags::IsManagedType || Flags & ObjectFlags::IsCustomScriptingType)
SetupType(); SetupType();
// Use lazy creation for the managed instance, just register the object // Use lazy creation for the managed instance, just register the object
if (!IsRegistered()) if (!IsRegistered())
RegisterObject(); RegisterObject();
}
void Script::PostSpawn() CHECK_EXECUTE_IN_EDITOR
{ {
if (Flags & ObjectFlags::IsManagedType || Flags & ObjectFlags::IsCustomScriptingType) OnAwake();
SetupType(); }
// Create managed object
if (!HasManagedInstance())
CreateManaged();
} }
void Script::BeginPlay(SceneBeginData* data) void Script::BeginPlay(SceneBeginData* data)

View File

@@ -10,12 +10,11 @@
/// </summary> /// </summary>
API_CLASS(Abstract) class FLAXENGINE_API Script : public SceneObject API_CLASS(Abstract) class FLAXENGINE_API Script : public SceneObject
{ {
DECLARE_SCRIPTING_TYPE(Script); DECLARE_SCRIPTING_TYPE(Script);
friend Actor; friend Actor;
friend SceneTicking; friend SceneTicking;
friend class PrefabInstanceData; friend class PrefabInstanceData;
protected: protected:
int32 _enabled : 1; int32 _enabled : 1;
int32 _tickFixedUpdate : 1; int32 _tickFixedUpdate : 1;
int32 _tickUpdate : 1; int32 _tickUpdate : 1;
@@ -27,7 +26,6 @@ protected:
#endif #endif
public: public:
/// <summary> /// <summary>
/// Gets value indicating if script is active. /// Gets value indicating if script is active.
/// </summary> /// </summary>
@@ -54,7 +52,6 @@ public:
API_PROPERTY() void SetActor(Actor* value); API_PROPERTY() void SetActor(Actor* value);
public: public:
/// <summary> /// <summary>
/// Called after the object is loaded. /// Called after the object is loaded.
/// </summary> /// </summary>
@@ -77,7 +74,7 @@ public:
} }
/// <summary> /// <summary>
/// Called before the object will be destroyed.. /// Called before the object will be destroyed.
/// </summary> /// </summary>
API_FUNCTION(Attributes="NoAnimate") virtual void OnDestroy() API_FUNCTION(Attributes="NoAnimate") virtual void OnDestroy()
{ {
@@ -126,14 +123,12 @@ public:
} }
private: private:
void SetupType(); void SetupType();
void Start(); void Start();
void Enable(); void Enable();
void Disable(); void Disable();
public: public:
// [ScriptingObject] // [ScriptingObject]
String ToString() const override; String ToString() const override;
void OnDeleteObject() override; void OnDeleteObject() override;
@@ -143,8 +138,7 @@ public:
void SetParent(Actor* value, bool canBreakPrefabLink = true) override; void SetParent(Actor* value, bool canBreakPrefabLink = true) override;
int32 GetOrderInParent() const override; int32 GetOrderInParent() const override;
void SetOrderInParent(int32 index) override; void SetOrderInParent(int32 index) override;
void PostLoad() override; void Initialize() override;
void PostSpawn() override;
void BeginPlay(SceneBeginData* data) override; void BeginPlay(SceneBeginData* data) override;
void EndPlay() override; void EndPlay() override;
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;