I am going to keep pumping out these posts, so if you have my site in an RSS reader (I don’t know if this site emits an RSS feed, actually), be warned.
Hot on the heels of my post from [checks calendar] this morning, I managed to create my nested resource structure from hell. It looked cool, with all of the individual programmatic elements representing starship parts, and how Godot colorized the sub-resource nature in the property Inspector panel. But there was a problem: I couldn’t get the properties of any of the resources.
Consider this:
- Player – Currently has movement functionality. Needs info from Propulsion.
- Player Entity – Contains things like ID, name, portrait, etc.
- ComponentHull – Container for other ship parts.
- ComponentPropulsion – Properties for max speed, rotation speed, and acceleration.
- ComponentHull – Container for other ship parts.
- Player Entity – Contains things like ID, name, portrait, etc.
I could get access to the properties in ComponentPropulsion from Player if I used the fully qualified path name:
var max_speed = player_entity.current_ship.thruster.max_speed
The problem I had with this is that it’s ugly and tightly coupled, inexorably linking the Player with the ComponentPropulsion resource. Since most resources are being designed to get swapped out during play, and some will be optional, I didn’t want to have the player become totally inoperable should something go wrong with the resource chain.
Other attempts to get access to those properties were stymied by the fact that I am still coming to terms with Godot, and don’t fully understand it as well as I need to. Since I needed property values from Propulsion in order to allow the player to move, not having those values meant that the physics processor which handled movement would blow up. Since that code runs even when the player isn’t hands-on-keyboard moving, I was getting NULL errors. Again, the FQN assignment would work, but it’s ugly and would get cumbersome as I add more resources. I was trying to find a way to roll sub-resource properties up to the ComponentHull level at least, but since Resources in Godot do not have a _ready function (only an _init, which doesn’t help), there was no way that individual resource scripts could assist. It was all on the shoulders of the Player scene script to get the properties.
Taking advantage of Godot’s compartmentalization, though, I added a new Node object to the Player scene and called it CurrentShip. This new Scene got its own script, and I moved the ComponentHull property from the EntityPlayer to the CurrentShip. What this allows me to do is to dedicate the entirety of the CurrentShip script to collect properties from the various sub-resources and assign them to properties at the surface of CurrentShip. That way, I can write code like this:
### --- CurrentShip.gd --- ###
extends Node
# Public properties. These will be accessible to the Player,
# and hopefully more easily to other entities.
### --- Propulsion --- ###
var max_speed = 0
var rotation_speed = 0.0
var acceleration = 0.0
# This is the core resource for the ship: The ComponentHull.
# This should have access using the fully qualified path to
# various properties that exist on sub-resources. We will need
# to pull them up by FQN and assign them to local properties.
export(Resource) var current_hull
# In _ready, we will do our reaching into the depths of
# our sub-resources, pulling props out and assigning
# them to local props.
func _ready():
get_propulsion_stats()
# This function should be called whenever we switch components.
# It will refresh ALL stats from the resources below, but that
# should be OK. Consider triggering this from a signal.
func update_stats():
get_propulsion_stats()
# Get all stats from the Propulsion-related resources further
# down the stack
func get_propulsion_stats():
var _src = current_hull.thruster
max_speed = _src.max_speed
rotation_speed = _src.rotation_speed
acceleration = _src.acceleration
### --- Player.gd --- ###
onready var _current_ship = $CurrentShip #refer to child node
...
func _physics_process(delta):
get_input(delta)
rotation += rotation_dir * _current_ship.rotation_speed * delta
velocity = move_and_slide(velocity)
1 Comment
Nimgimli
January 6, 2023 - 10:24 PMYes, your site has an rss feed. RSS is pretty much baked into wordpress.