I come from a background mostly C#, Ruby, and then JavaScript. Please forgive me for the gdscript questions as I've tried to wrap my head around this but haven't gotten to the bottom of it.

When writing code I like to split it into concerns, such that I might have a TerrainPainter.gd that I use somewhere in the form of the following or similar. Essentially trying to get complex logic out.

func _ready(): TerrainPainer.render(self)

But in gdscript I've run into it many many times where the editor complains of cyclic dependencies or loading errors. The game will run fine but I can't get the editor to stop complaining about me. A very quick example is I have a class called MapData that basically has a lot of vars and nothing else. It doesn't extend anything, it doesn't load anything, it could basically be just a dictionary.

But I add class_name MapData to the top of the file and many of my other files start complaining about a cyclic dependency when I use it. What am I doing wrong?

res://GameWorld/IslandMap/MapRenderer.gd:18 - Parse Error: Class 'MapData' could not be fully loaded (script error or cyclic dependency). modules/gdscript/gdscript.cpp:580 - Method/Function Failed, returning: ERR_PARSE_ERROR Another resource is loaded from path: res://GameWorld.gd (possible cyclic resource inclusion) res://GameWorld.gd:7 - Parse Error: Class 'MapData' could not be fully loaded (script error or cyclic dependency). modules/gdscript/gdscript.cpp:580 - Method/Function Failed, returning: ERR_PARSE_ERROR

I've mixed these up all over the place trying to figure out how to use them. Essentially should I be preferring preload, should I use onready.

GDquest has a recent video on Youtube regarding how to make proper use of the class_name feature.

For one thing, you're not allowed to load up a class inside another script with class_name in use (ie. the cyclic dependency).

To make the best use of class name, you need to think of a structure like this.

A base script..

common_functions.gd

extends Spatial
class_name example

var common_var1 : float = 12.5
var common_var2 : int = 20
var common_var3 : Array = []

func common_func1() -> void:
    #do something#

func common_func2() -> void:
    #do something else#

And scripts for objects that will make use of the functions and variables above

object.gd

extends example
var local_var1 : Vector3 = Vector3(0.2,0,0.5)

func _physics_process(delta:float) -> void:
    if common_var2 < 100:
        global_transform.origin += local_var1
        common_var1 *= 1.2
        common_func1()
    else:
        rotate_y(0.1)
        common_func2()

This is only a rough overview and these example scripts won't do anything useful, GDquest gives far more detail. This type of thing avoids having to worry about trying to preload scripts or adding another node to the tree as a holder for another script. You could probably have the second script also be a class and make an even more local script that extends that class (as long as your user-made class structure resembles a tree with branches, but no direct references that would form a loop).

Here is the GDQuest video about using class_name in Godot:

Updating Godot 3.1 -> 3.1.1 has fixed a lot of my issues. I think I'm just interested in best practices and conventions for loading scripts into my scripts.

Modularisation still feels pretty important to me and so I'm going to keep playing with it.

4 years later