Wonderland Component Life Cycle
Hello Coders! 👾
Today, I want to talk about something that often puzzles people: the lifecycle of a component. You know, those moments when you’re left scratching your head, wondering when and in what order functions like start
and onActivate
are being called. 🤔
I’ve seen plenty of documents from Unity and other platforms, but I thought it was high time we had one for Wonderland. So, let’s dive right in!
The Basics
First, let’s have a look at all the steps in the lifecycle of a Wonderland component. These are all the different places you can hook into. This doesn’t mean you have to, but you could.
If you’ve ever seen a Wonderland component, a couple might be familiar. In the default template init
, start
and update
are included.
Let’s go over them and talk about their key functions and when you should (and shouldn’t) use them:
onRegister
The first method that is called in the life cycle of a component is the onRegister
method. This immediately is a special one, since it is static. It is called when the component is registered with Wonderland Engine. This is before the component is instantiated. The common thing you can do here is register other components this component depends on. You can add a little bit of logic to have a
specific component registered in specific cases
. The instance of the engine is passed a parameter.
init
The more often used method init
is called once after the component is initialized.
This is not the place to create or use components, but you’ll be fine initiating a download from an external service, loading a file or maybe something else. As long as you keep in mind you can’t do anything with resources in the engine yet.
validateProperties
Before the component is started, the validateProperties
method is called. Here, you can add custom validations by overriding the method. Whenever you find that a property should be invalid, throw an error. Remember to call super()
to make sure the original validation is being executed as well.
start
The start
method is overridden very commonly. This is the place where you start reading components from properties and start to change things on other components. The start (and validateProperties) is called once in the life cycle of a component, but it doesn’t have to be called right after init. When a component is not active at the beginning, for example when it is disabled in the Editor, validateProperties and start are called when the component first becomes active.
onActivate
Now we’re getting to the methods that can be called more than once in the life cycle of the component. onActive
is called when a component becomes active. Whether this is done by another component or when the component is started active. Common to add event handlers.
update
The update
method is called every frame. As a parameter, it gets the time that has passed since the previous frame in seconds. This can be used to calculate constant changes over time. Update
would be the right place to do the business logic of your game.
onDeactivate
When a component is deactivated, by setting the active
to false either on the component itself or on the object the component belongs to. Keep in mind this method is not called when a component starts with its inactive property set to false. It had to be active first. Overriding the onDecative
method would be the perfect place to unsubscribe from event handlers.
onDestroy
When destroy
is called on an object it gets removed. When destroy
is called on a component the component is removed from the object. In either of these cases, the onDestroy
method is called. This way you can make sure everything is cleaned up or maybe even do something else. The destruction of the object can’t be stopped though.
Overriding Methods
There are also a couple of methods that can be overridden, although they’re not really a part of the lifecycle. With all of these, make sure to call super()
and keep an eye on the return value. Some return this
.
resetProperties
The first method that is being called after a component is instantiated is the resetProperies
method. This method resets all properties to their default values, so a bool to false and a number to 0. If there’s anything you’d like to reset yourself, that is not used by the editor, you can do it here. Make sure you call super()
to make sure that the original resetProperties is executed as well. Also, return this
so the method can be chained.
copy
This method copies all the properties from src
into this instance. When overwritten, you can add some custom logic to the cloning process.
equals
This method is used for comparing components. Override it if you want to add custom code. If you override this, make sure to return a bool indication if the component is equal to the one passed as a parameter.
The Order of Things
The onRegister
method is always called first. Even when a component is not used but is registered with the engine in the onRegister
method of another component, it is called.
Under the most common situation, the order is as follows:
onRegister → resetProperties → init → validateProperties → start → onActivate → update
There’s a lot of stuff happening internally between the calls, but you can be certain everything is called in this order. Update
keeps being called every frame from then on.
So, what’s the order of operations when adding a component to an object at runtime? The sequence stays the same, although the onRegister
isn’t called in that case since it was already registered.
resetProperties → init → validateProperties → start → onActivate → update
And if you want to start inactive, you can use this code:
this.object.addComponent(Test,{active:false});
This will add the component, but keep it inactive. The sequence then becomes:
resetProperties → init
After which it stops and waits until it is activated. To activate the component:
this.object.getComponent(Test).active = true;
At that point, the sequence continues.
validateProperties → start → onActivate → update
Until you might want to deactivate it again:
this.object.getComponent(Test).active = false;
onDeactivate
… is the only method that is called then. Until it becomes active again.
onActivate → update
And then when you want to remove the component.
this.object.getComponent(Test).destroy();
onDestroy
This is the final method that is called. If you try to access the component after that the engine will throw you an error.
Your Thoughts?
I hope this post has helped clear up some of the confusion around the lifecycle of a component in Wonderland. But I’d love to hear your thoughts! Have you found any tricks or tips that make managing the lifecycle easier? Or maybe you’ve run into some pitfalls that other developers should avoid. Let me know in the comments!
Until next time, keep coding, keep creating, and keep having fun. Game development is a journey, and I’m glad we’re on it together.
Happy Coding! 🚀