bog champ
bog champ

Reputation: 21

why do i keep getting invalid get index 'rot_speed' on base GDscript

here is my code in the spinner script:

extends KinematicBody

var glob = preload("res://Glabal.gd")

var rotation_speed = glob.rot_sped

func _physics_process(delta):
    
    if rotation_speed == 300:
        rotation_speed -= 1 
    
    rotation_speed += 0.5
    
    rotate_y(deg2rad(rotation_speed * delta))
    
    print(rotation_speed)

here is my code in the global script and yes it is supposed to be glabal.gd:

extends Node

var rot_sped = 300

and here is my code in the settings script:

extends "res://Glabal.gd"

var glob = preload("res://Glabal.gd")

func _on_Increase_button_pressed():
    glob.rot_sped = glob.rot_sped + 1

func _on_Decrease_button_pressed():
    glob.rot_sped = glob.rot_sped - 1

func _process(delta):
    $"current speed/Label".text = "current rotation speed" + glob.rot_sped

Upvotes: 2

Views: 505

Answers (1)

Theraot
Theraot

Reputation: 40295

The file "res://Glabal.gd" is a script, more precisely a GDScript file.

So when you load it, for example like this:

var glob = preload("res://Glabal.gd")

You get a GDScript object. In fact, you can type it:

var glob:GDScript = preload("res://Glabal.gd")

The GDScript effectively represents a GDScript class. You can, for example, create an instance of it using new:

var glob:GDScript = preload("res://Glabal.gd")
var instance = glob.new()

What will be the type of the instance? Well, that GDScript file is the class. And - as the source code in that GDScript file says - it extends Node:

var glob:GDScript = preload("res://Glabal.gd")
var instance:Node = glob.new()

To answer the question the title. You are getting the error because rot_speed is not a property of GDScript (I remind you that you get a GDScript object from preload("res://Glabal.gd")). And thus this does not work:

var glob = preload("res://Glabal.gd")

var rotation_speed = glob.rot_sped

It might be a property of the instances of that particular script… But you don't have an instance of that particular script (which, again, you can create with new).

Anyway, if you instance your script with new, you are getting a new instance. Yet, I believe you want to get the same instance everywhere. So using preload("res://Glabal.gd") is wrong, I'll get back to that.


I don't know how you use your settings script, but it makes little sense to do this:

extends "res://Glabal.gd"

var glob = preload("res://Glabal.gd")

You are saying that your script extends the class in the file "res://Glabal.gd", and it also has a reference to said class.

The settings script could access the properties on its parent class directly. However, we would be going down the wrong path.

Instead, write your settings script the way you will write anything else…


So, how? - You have a couple options:

  • Make "res://Glabal.gd" an autoload (sigleton), with a name, for example Global. You can do that in Project Settings, on the AutoLoad tab.

    Then you can access it every where you need. For example:

    var rotation_speed = Global.rot_sped
    

    Be aware that it is copying the value of rot_sped into the variable rotation_speed, so changes in rot_sped won't be reflected in rotation_speed.

  • Use resource based communication. For this, you are going to change the base type from Node to Resource. I also recommend giving it a name to the class, like this:

    class_name Global
    extends Resource
    
    var rot_sped = 300
    

    That defines a new Resource type called Global. And we are going to create a resource of that type. To do so, use the context menu on the FileSystem and choose New Resource…. Godot will ask you what kind of resource, and you pick Global. And save it.

    Then you will have a resource file. For example "res://Global.tres". That is what you preload:

    var glob = preload("res://Glabal.tres")
    

    And you can access it the way you intended:

    var glob = preload("res://Glabal.tres")
    
    var rotation_speed = glob.rot_sped
    

    And yes, you are going to get the same instance everywhere you use preload("res://Glabal.tres"). That was also true for preload("res://Glabal.gd"), but that was an instance of GDScript, which is not what you want.

    Here glob will be an instance of Global. In fact, you can type it:

    var glob:Global = preload("res://Glabal.tres")
    
    var rotation_speed = glob.rot_sped
    

Please notice that you need to configure autoloads in project settings, but not resources. Also notice that autoloads exist in the scene tree. Also they can be scenes, not just scripts. On the flip side, resources are not, and don't depend on, the scene tree. So there will be situations where one approach is preferible to the other. Although, for what you are doing so far, either way will work.

Upvotes: 1

Related Questions