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
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!
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
update are included.
Let’s go over them and talk about their key functions and when you should (and shouldn’t) use them:
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.
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.
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 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.
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 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.
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.
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.
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
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.
This method copies all the properties from
src into this instance. When overwritten, you can add some custom logic to the cloning process.
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
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 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;
… 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 is the final method that is called. If you try to access the component after that the engine will throw you an error.
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! 🚀