Godot 4.3 Moving Get_properties to a Separate Class
So far, we’ve implemented a powerful object analysis system that can dynamically inspect and categorize both node-based and non-node objects in Godot. However, keeping all this logic inside main.gd
can clutter the script, making it harder to maintain and expand.
To improve code organization, we’ll move the get_properties()
function into its own dedicated class. This will:
- Keep
main.gd
clean and focused on high-level game logic. - Make
get_properties()
reusable across different parts of the project. - Encourage modular programming , making it easier to expand in the future.
Step 1: Creating a New Script for Object Analysis
In Visual Studio Code, we will create a new script to handle object analysis separately.
- Navigate to the Scripts folder (or create one if it doesn’t exist).
- Create a new script and name it
ObjectAnalyzer.gd
. - Open
ObjectAnalyzer.gd
and define a new class.
Step 1.1: Understanding Classes in Godot
What is a Class?
A class in GDScript is a blueprint for creating objects. Classes let us group related functions and variables together, making the code more modular and reusable.
How Do We Define a Class in GDScript?
In Godot, a class is simply a script file that extends a base type (like Node
, Node2D
, or Object
).
For example:
extends Node # This makes it a Node class
var example_variable = "Hello!"
func example_function():
print(example_variable)
extends Node
: This means our script inherits fromNode
, allowing it to be added to the scene.example_variable
: A property that stores a value.example_function()
: A method (or function) that performs an action.
When should we use classes?
- When we reuse code across multiple files.
- When we need to organize related functions into a single location.
- When we want to keep
main.gd
clean.
Step 1.2: Creating Our ObjectAnalyzer
Class
Now that we understand classes, let’s define one for object analysis .
- Inside
ObjectAnalyzer.gd
, define the class by extendingNode
: - What does
class_name ObjectAnalyzer
do?- This registers the class as
ObjectAnalyzer
, so we can instantiate it inmain.gd
without needing to useload()
orpreload()
. - Example usage:
- This registers the class as
extends Node # This makes our script a class that can be instantiated
class_name ObjectAnalyzer # This allows us to reference it by name in other scripts
Now that we’ve defined a class, we can move the get_properties()
function inside it.
Step 2: Moving get_properties()
into ObjectAnalyzer.gd
We’ll define a new class called ObjectAnalyzer
that manages object inspection . Instead of keeping everything in main.gd
, we’ll encapsulate the logic inside this separate script.
ObjectAnalyzer.gd
extends Node
class_name ObjectAnalyzer
var handlers: Dictionary = {
TYPE_NIL: func(): print("Nil"),
TYPE_BOOL: func(o): print("Boolean: ", o),
TYPE_INT: func(o): print("Integer: ", o),
TYPE_FLOAT: func(o): print("Float: ", o),
TYPE_STRING: func(o): print("String: ", o),
TYPE_VECTOR2: func(o): print("Vector2: ", o),
TYPE_VECTOR3: func(o): print("Vector3: ", o),
TYPE_COLOR: func(o): print("Color: ", o),
TYPE_OBJECT: func(o): print("Object: ", o),
TYPE_DICTIONARY: func(o): print("Dictionary: ", o),
TYPE_ARRAY: func(o): print("Array: ", o),
}
func get_properties(obj):
var type_id = typeof(obj)
var handler = handlers.get(type_id, func(): print("handler does not exist"))
# Handle nodes separately
if obj is Node:
var numbers = []
var strings = []
var bools = []
var vectors = []
var colors = []
var objects = []
var arrays = []
var nil = []
var type_lookup = {
0: "Nil", 1: "bool", 2: "int", 3: "float", 4: "String", 5: "Vector2",
9: "Vector3", 11: "Transform2D", 20: "Color", 22: "NodePath", 23: "RID",
24: "Object", 27: "Dictionary", 28: "Array"
}
for prop in obj.get_property_list():
var type_name = type_lookup.get(prop.type, "Unknown")
if prop.type in [1]: bools.append(prop.name + " - Type: " + type_name)
elif prop.type in [2, 3]: numbers.append(prop.name + " - Type: " + type_name)
elif prop.type in [4]: strings.append(prop.name + " - Type: " + type_name)
elif prop.type in [5, 9, 11]: vectors.append(prop.name + " - Type: " + type_name)
elif prop.type in [20]: colors.append(prop.name + " - Type: " + type_name)
elif prop.type in [22, 23, 24]: objects.append(prop.name + " - Type: " + type_name)
elif prop.type in [27, 28]: arrays.append(prop.name + " - Type: " + type_name)
else: nil.append(prop.name + " - Type: " + type_name)
numbers.sort()
strings.sort()
bools.sort()
vectors.sort()
colors.sort()
objects.sort()
arrays.sort()
nil.sort()
return {"numbers": numbers, "strings": strings, "bools": bools, "vectors": vectors, "colors": colors, "objects": objects, "arrays": arrays, "nil": nil}
else:
handler.call(obj)
Step 3: Updating main.gd
to Use ObjectAnalyzer
Now that get_properties()
is moved to a separate script , we need to update main.gd
so it uses ObjectAnalyzer
.
- Open
main.gd
. - Create an instance of
ObjectAnalyzer
. - Call
get_properties()
through this instance.
Updated main.gd
extends Node2D
var object_analyzer: ObjectAnalyzer
func _ready():
object_analyzer = ObjectAnalyzer.new() # Create an instance of ObjectAnalyzer
# Example: Analyzing a Node2D instance
for x in object_analyzer.get_properties(Node2D.new())["numbers"]:
print(x)
# Example: Analyzing a Color object
object_analyzer.get_properties(Color(0, 0, 0, 0))