Skip to content

Tutorial Update Manager

Kamran Wali edited this page Nov 26, 2024 · 8 revisions

Tutorial Update Manager

In CodeOptPro you can use another powerful feature that allows you to use custom update to update your script, that is the _process(delta) and _physics_process(delta). This custom update allows you to share one _process(delta) or _physics_process(delta) method with many scripts. This in turn saves lot of performance issues as one script is handling the call for processes. There are two types of custom update classes in CodeOptPro they are COP_UpdateManager and COP_UpdateManagerGlobalHelper. Each of these custom update classes have 2 more types which are process_manager_local and physics_process_manager_local for the COP_UpdateManager. And process_manager_global and physics_process_manager_global for the COP_UpdateManagerGlobalHelper. The main logic between all of them are same but the only difference is that the local ones needs to be referenced by dragging and dropping the node object containing the script while the global ones are referenced by giving the resource reference. Below I will explain how to use the custom update manager.

Adding The Update Manager

The first task you need to do is to add at least one update manager in the scene. This could be added any where but it is best to add all update managers under one Node called UpdateManagers so that it remains organized and easy to debug. So create a new Node called UpdateManager1 and add any of the update manager scripts called physics_process_manager_global, process_manager_global, physics_process_manager_local or process_manager_local. Now let me explain the properties of the update manager.

  • a. Helper (Only available in the global types) - This the cop_update_manager_global_helper resource that helps to keep the code decoupled. The update objects will use this reference to interact with the update manager. This property is only available for the global types. There is already a cop_update_manager_global_helper resource created called default_update_manager. You can use this as well for your project if you want to.
  • b. Objects - This is an array which will contain all the update objects related to this update manager. These objects will share one _physics_process(delta) or _process(delta) method from the update manager. You can manually add the update objects here but that is NOT recommended. Instead we shall use the Auto Setup plugin to add update objects to update managers automatically. Will talk about how to create an update object and using Auto Setup plugin later below.
  • c. Num Update - This value handles how many objects should be updated per frame. For example if this value is set to 5 then 5 objects will be update in one frame cycle. If there are too many update objects that needs to be updated then increasing this value should make the update process much better but that depends on your scripts and their logic.
  • d. Is Set Num Update - If set true then will automatically set the Num Update value to the number of objects added to the update manager. If null or false then the Num Update value will be used and auto setup for Num Update won't work. For example if there are 5 objects added and the Num Update value is 1 and Is Set Num Update value is true then the actual num update value will be 5. Note: This value can remain null as null is taken as a false flag here.

Creating And Adding Update Object

The second step is to create an update object. It is very easy to create an update object. If you haven't copied the folder script_templates to the main folder res:// then do that now as we will needed the update object template to create our scripts. Once that is done then create a new script. In the Inherits: field select Node. Then in the Template: field either select Cop Update Object Global Tepmlate, if you have added the global update manager, or select Cop Update Object Local Template, if you have added the local update manager. Name the script anything you want and then press Create button. You can read COP_update_object_global_template or COP_update_object_local_template docs for understanding the update object scripts a bit better but I have commented the script with much details and will explain what each of these properties and functions does.

  • a. update_manager (COP_UpdateManagerGlobalHelper or COP_UpdateManager) - This property keeps the reference of the update manager. Depending on what type you used it could be either COP_UpdateManagerGlobalHelper, for global update objects, or COP_UpdateManager, for local update objects. This reference is mainly used by the Auto Setup plugin to add the update object automatically to the update managers but can also be used for using any data from the update manager.
  • b. void update(float delta) - This is the method that will update the update object every frame. So any update logic that you were going to put in either _physics_process(delta) or _process(delta) should be put in here.
  • c. void set_active(bool) - This method enables/disables the update object. So if any flags that are going to be used for activation check must be able to be updated by this function.
  • d. bool is_active() - This method checks if the update object is active or NOT. If it is NOT active then the update manager will NOT call it's update(float delta) method. Again use a separate flag that will be used to check for activation.
  • e. void on_enable() - This method is called whenever the linked Update Manager is enabled.
  • f. void on_disable() - This method is called whenever the linked Update Manager is disabled.

The last two methods, which are NOT shown here, can be ignored and should NEVER be called by any script or overridden. These are used by the Auto Setup plugin for automation. I have commented extensively here to avoid any errors. Also you can change the extension of the script to anything else you want but as long as the object is a child of Node then it will be fine. Below is an example script of a global update object called update_object1.gd.

@tool
extends Node

## The global update manager that will update this object.
@export var update_manager: COP_UpdateManagerGlobalHelper:
	set(p_update_manager):
		if update_manager != p_update_manager:
			update_manager = p_update_manager
			update_configuration_warnings()

@export var _counter:= 0
@export var _is_active:= true

func _get_configuration_warnings():
	var warnings = []

	if !update_manager:
		warnings.append("Update Manager: Please assign a COP_UpdateManagerGlobalHelper 
			otherwise object will NOT be updated and auto setup will give error.")
	
	return warnings

## This method updates the update object.
func update(delta: float) -> void:
	_counter += 1
	print("Counter: ", _counter)

## This method activates/deactivates the update object.
func set_active(is_enable: bool) -> void:
	_is_active = is_enable

## This method checks if the update object is active or NOT.
func is_active() -> bool:
	return _is_active

## This method is ONLY called by the Update Manager when the update
## manager is enabled through script, which is UM.set_enable(true). 
## Note: This method can be removed if NEVER needed.
func on_enable() -> void:
	_counter = 0 # Resetting counter on object enable
	print("Counter has been resetted")

## This method is ONLY called by the Update Manager when the update
## manager is disabled through script, which is UM.set_enabled(false).
## Note: This method can be removed if NEVER needed.
func on_disable() -> void:
	print("Counter stopped at: ", _counter) # Showing the last value of the counter

#region The logic in this section MUST NOT BE CHANGED OR OVERRIDDEN!
## This method adds this object to the update manager._action_options
## THIS METHOD SHOULD NOT BE CALLED OR OVERRIDDEN. IT IS ONLY USED
## FOR AUTOMATION!
func _add_self_to_manager():
	if update_manager:
		update_manager._add_object(self)
	else:
		push_error("Error: ", name, " does not have update manager assigned!")

## This method always sends true as the script is an update object.
## This method is needed for duck typing check and SHOULD NOT BE
## OVERRIDDEN OR CHANGED!
func _is_update_object():
	return true
#endregion

When this script runs it will just show the value of the counter going up. Create a new Node in the example scene and attach this script to it.

Auto Setup

The final step is to use the Auto Setup plugin to setup the update managers and update objects. Enable the Auto Setup plugin from the Plugins tabs in the Project Settings.

Variable-Creator1.png
Auto Setup
  • a. Run Project - This will run the auto setup and then play the project which is the main scene.
  • b. Run Current Scene - This will run the auto setup and then play the edited scene which is the currently active scene.
  • c. Manual Setup - This will only run auto setup.
  • d. Log - Here the logs will be shown for the auto setup process.
  • e. Auto Save (Current Scene) - If enabled then the current scene will be automatically saved once the auto setup process is done. It is recommended to keep it enabled so that if you forget to save the scene then this will do the saving for you.

Before using the Auto Setup plugin we must first setup the update managers and the update objects. If you have used local update manager then there is nothing needed to setup the update manager but if you have used global update manager then you must set the Helper. You can either select or drag and drop the default_update_manager, which is found in this path res://addons/kamran_wali/code_opt_pro/variables/, or you can create a new cop_update_manager_global_helper through the Variable Creator. In this example we will use the default one if global update manager is used. Now we need to setup the update object. Select the update object. If local update object is used then drag and drop the update manager into the Update Manager field in the update object. If global update object is used then either select the defaul_update_manager or the one you created. Finally make sure the Is Active flag is true.

Alright. We done setting up the update manager and update objects. Now in the Auto Setup plugin press the Run Current Scene button. If everything is alright then this should start the auto setup process and then run the scene. Once the scene runs you will see the Counter value going up in the Output. You will also notice in the Auto Setup plugin that the Log has been updated showing all the process of the auto setup.

Update Manager Runtime Functions/Methods

I have also added some runtime methods for the update manager. This will help tremendously during runtime of the game. Below are the methods:

  • void add_object(Node object): This method adds a new object to the update manager. Also please do NOT confuse this method with the private method _add_object(Node object) as this private method does NOT handle some of the validation checks and is ONLY used by the automation script. If you don't want any duplicate objects added then make sure to check using the method has_object(Node object) before calling the void add_object(Node object) method. Below is a small example of avoiding duplicate object addition when adding object to update manager.
extends Node

@export var update_manager: COP_UpdateManager

func some_method(object: Node) -> void:
	if !update_manager.has_object(object): # Checking if the object does NOT exist in the Update Manager
		update_manager.add_object(object)
  • void remove_object(Node): This method removes the given object. Note: When calling this method the update method will stop working till all remove actions are done. If number of remove objects are small then the update pause won't be noticable. It is recommended NOT to call this method every frame.
  • void remove_object_index(int): This method removes an object using an int index value. Note: When calling this method the update method will stop working till all remove actions are done. If number of remove objects are small then the update pause won't be noticable. It is recommended NOT to call this method every frame.
  • int get_size(): This method gets the number of objects added to the update manager.
  • Node get_object_index(int): This method gets the indexth object. If the index value given is higher than the size of the update object array then a null object will be returned.
  • void set_enabled(bool): This method enables/disables the update manager. True means to enable and false means to disable. If disabled then another script MUST be used to enable it.
  • bool is_enabled(): This method checks if the update manager is enabled or NOT.

Auto Setup Objects

This feature allows objects to be setup automatically during the auto setup process in the editor mode. This helps with certain tasks like automatically populating an array with objects. If you haven't copied the folder script_templates to the main folder res:// then do that now as that contains the script template for auto setup object called COP_auto_setup_object_template under Node. To declare an object as auto setup object is easy. You can create a new script using the script template COP_auto_setup_object_template or add the methods func auto_setup() -> void: and func _is_auto_setup_object() -> bool: and @tool to an existing script. The auto setup object can extend from any other script as long as that script is a child of Node object. These two methods will make the script an auto setup object. Let me explain what each method does.

  • void auto_setup(): This method is called during the auto setup process and this is where all the logic for auto setup should be placed.
  • bool _is_auto_setup_object(): This method is used by the auto setup process to check if the object is an auto setup object. This method MUST NOT be changed or overridden.

Below I am sharing a very simple code on how to use the auto setup object. This code just populates the Arrya[Node] with children from a Node.

@tool
extends Node

@export var _object_holder: Node
@export var _some_objects: Array[Node]

var _index: int

## This method handles all the setup that needs to be done during 
## automation setup process.
func auto_setup() -> void:
	_some_objects.clear() # Making sure every auto setup process the array is cleared so no duplication occurs
	_index = 0
	while _index < _object_holder.get_child_count(): # Loop for populating the array from the given Node
		_some_objects.append(_object_holder.get_child(_index))
		_index += 1

#region The logic in this section MUST NOT BE CHANGED OR OVERRIDDEN!
## This method always sends true as the script is an auto setup object.
## This method is needed for duck typing check and SHOULD NOT BE
## OVERRIDDEN OR CHANGED!
func _is_auto_setup_object() -> bool:
    return true
#endregion

If you want to you can also make any update objects to be auto setup objects as well just by adding the methods void func auto_setup() and bool _is_auto_setup_object() to the update object script. That way the object will be both update object and auto setup object.


Clone this wiki locally