0 votes

My current method doesn't work but I'm not really sure why

I am saving a custom resource like this:

var w = GameWorld.new(100, 100)
w.add_new_world_item(GROUND_TILE_TYPES[0], Vector2(1, 1))
ResourceSaver.save("res://saves/world_2.tres", w)

GameWorld is a custom resource which looks like this:

extends Resource
class_name GameWorld, "res://world/world_icon.png"

export(int) var width: int = 100
export(int) var height: int = 100

export(Array, Vector2) var gates := []
export(Dictionary) var world_items = {}
export(Array) var world_item_ids = []

func _init(width: int, height: int):
    self.width = width
    self.height = height
    self.gates = get_gate_positions_from_dimensions(width, height)
    self.world_items = {}
    self.world_item_ids = []

func add_new_world_item(type, position) -> void:
...

And world_items in GameWorld is a dictionary int -> WorldItem which is another CustomResource (no idea if that makes a difference)

The world is correctly saved here:
enter image description here

The contents of this look like:

[gd_resource type="Resource" load_steps=5 format=2]

[ext_resource path="res://world/game_world.gd" type="Script" id=1]
[ext_resource path="res://game/vegetation/item_types/grass_1.tres" type="Resource" id=2]
[ext_resource path="res://world/world_item.gd" type="Script" id=3]

[sub_resource type="Resource" id=1]
script = ExtResource( 3 )
world_item_type = ExtResource( 2 )
position = Vector2( 1, 1 )

[resource]
script = ExtResource( 1 )
width = 100
height = 100
gates = [ Vector2( 50, 0 ), Vector2( 50, 100 ) ]
world_items = {
0: SubResource( 1 )
}
world_item_ids = [ 0 ]

I then have a node which takes in a GameWorld as an exported variable:
enter image description here

And drag world_2 to it like so:
enter image description here

But when running and trying to access world like this I get all kinds of errors which basically amount to world not being an instance of GameWorld

When I call world.get_script() it returns [Object:null] but if I call it on a newly created GameWorld (via GameWorld.new(..)) I get [GDScript:1239]

And none of the properties/methods are there: print(world.world_items) fails with Invalid get index 'world_items' (on base: 'Resource').

I don't really understand why I this isn't working; especially because I can generate GameWorld at runtime and populate it but when I try and load it from a .tres file it doesn't think it's a GameWorld anymore? Am I just being dumb?

Godot version 3.4
in Engine by (15 points)

1 Answer

+2 votes
Best answer

I think this is failing because the _init method has no default values; godot doesn't know how to create your object because it doesn't understand width and height. This would usually create an error in the debugger (see below). Note here:

https://docs.godotengine.org/en/stable/getting_started/step_by_step/resources.html

Make sure that every parameter has a default value. Otherwise, there will be problems with creating and editing your resource via the inspector.

If you change your _init method to the following, it should work:

func _init(w: int = 100, h: int = 100):    # note default values

(the error in the debugger may look like E 0:00:01.012 _create_instance: Condition "r_error.error != Variant::CallError::CALL_OK" is true. Returned: nullptr <C++ Source> modules/gdscript/gdscript.cpp:115 @ _create_instance()).

by (418 points)
selected by

Yes! Thank you, it took me another few hours to figure out that it was to do with the init constructor, after recreating a bare-minimum example and slowly breaking it. Though I didn't realise initial values would fix it.

I was getting an entirely different error in the Godot console though

ERROR: Condition "r_error.error != Variant::CallError::CALL_OK" is true. Returned: nullptr

Which was an extremely unhelpful message.

Many thanks!!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.