-1

I was working on adding an upgrade-like system to my game, but was having some trouble with the get_tree().get_root().get_node() thing.

In an attempt to retrieve a different node multiple layers up, I go the error
ERROR: Attempt to call function 'get_root' in base 'null instance'\ on a null instance. If I am correct, this means that it cannot find the node in the tree.

I have also tried using get_parent().get_parent()..., as well as get_node("../../../.. ...") with no luck.

Variables to get (points and pointsAdder)

extends Area2D

var points = 0.000000000001
var pointAdder = 1
var pointMultiplier = 1
var mouseover = false
var unit 


var defaultArrow = load("defaultCursor_16x16.png")
var clickableCursor = load("clickableCursor.png")

func _ready():
    get_parent().get_node("scoreLabel").text = "Logs: 0"

func _input(event):
    if mouseover and event is InputEventMouseButton and event.pressed and event.button_index == BUTTON_LEFT:
        points = (pointAdder* pointMultiplier) +points
        if points < 1000:
            set_label_text(points)
        elif points >= 1000 and points < 1000000:
            set_label_text(str(points / 1000) + " K")
            unit = "thousand"
            set_unit_text()
        elif points >= 1000000 and points < 1000000000:
            set_label_text(str(points / 1000000) + " M")
            unit = "million"
            set_unit_text()
        elif points >= 1000000000 and points < 1000000000000:
            set_label_text(str(points / 1000000000) + " B")
            unit = "billion"
            set_unit_text()
        elif points >= 1000000000000:
            set_label_text(str(points / 1000000000000) + " T")
            unit = "trillion"
            set_unit_text()

    elif Input.is_key_pressed(KEY_SPACE) and not event.is_echo():
        points = (pointAdder* pointMultiplier) +points
        if points < 1000:
            set_label_text(points)
        elif points >= 1000 and points < 1000000:
            set_label_text(str(points / 1000) + " K")
            unit = "thousand"
            set_unit_text()
        elif points >= 1000000 and points < 1000000000:
            set_label_text(str(points / 1000000) + " M")
            unit = "million"
            set_unit_text()
        elif points >= 1000000000 and points < 1000000000000:
            set_label_text(str(points / 1000000000) + " B")
            unit = "billion"
            set_unit_text()
        elif points >= 1000000000000:
            set_label_text(str(points / 1000000000000) + " T")
            unit = "trillion"
            set_unit_text()
            
func _on_Area2D_mouse_entered():
    
    Input.set_custom_mouse_cursor(clickableCursor)
    
    mouseover = true

func _on_Area2D_mouse_exited():
    
    Input.set_custom_mouse_cursor(defaultArrow)

    mouseover = false

func set_label_text(text_to_send):
    get_parent().get_node("scoreLabel").text = ("Logs: "+str(text_to_send))

func set_unit_text():
    get_parent().get_node("scoreUnitLabel").text = unit

And the code I am attempting to retrieve them in:

Extends Button

var points_cost = 10

func _on_Button_down():
    
    if get_tree().get_root().get_node("treeClickableArea").points >= points_cost:
        points_cost = (points_cost/2) + points_cost
        get_tree().get_root().get_node("treeClickableArea").pointAdder = get_tree().get_root().get_node("").pointAdder + 1
        get_tree().get_root().get_node("treeClickableArea").points = get_tree().get_root().get_node("treeClickableArea").points - points_cost

\Node tree:

┖╴Spatial
  ┠╴○ backgroundMap2
  ┠╴▦ backgroundMap
  ┠╴☺  scoreBackground
  ┠╴Tᵀ scoreLabel
  ┠╴Tᵀ scoreUnitLabel
  ┠╴☺  logSymbol
  ┠╴▭ treeClickableArea
  ┃ ┠╴☺ treeSprite
  ┃ ┖╴treeCollider
  ┠╴☺ upgradeBackground
  ┖╴▣ tabContainer
    ┠╴▯ perClick
    ┃ ┠╴perUpgradeScroll
    ┃ ┃ ┖╴▬ Button [scriptHavingIssuesHere]
    ┃ ┖╴Tᵀ Label
    ┖╴▯ perClickMultiplier

Could anybody clarify why I am getting this error? What exactly does it mean? Thank you for you time, I greatly appreciate any help.

CATboardBETA
  • 418
  • 6
  • 29

1 Answers1

1

Ok, another edit. I'm leaving the code from the edit I made before in case you need it for reference. I'm calling it EDIT#1.

The new example I'm posting is from a very simple test program I made. I'll call it EDIT#2.


EDIT#2 - TEST PROGRAM

Ok, so I made a simple 2D scene consisting of only a root node and 2 sprites that I named "Test1" and "Test2". I attached a script to both of the sprite nodes, each containing a variable called "points". In the first script I made points = 60,000,000, and in the second, I made points = 16. In the first script (Test1), I used onready var testNode to load the Test2 node and store it as the variable testNode. I then made a simple input event that prints the points value of the testNode variable when I press the key I assigned to "move forward". The expected result is to have the value 16 print to the console, despite both scripts containing a variable named points which each have different values (to prove i'm getting the number from the second script). For me, it works just fine. Here is the code I used for the scripts:

Node setup

-Node2d
--Test1(sprite) - script 1
--Test2(sprite) - script 2

Script 1 -

extends Sprite

var points = 60000000
onready var testNode = get_parent().get_node("Test2")

func _input(event):
    if Input.is_action_just_pressed("move_forward"):
        print(testNode.points)

Script 2 -

extends Sprite

var points = 16

Hopefully this stripped down example can help provide some insight into what is going on. Hope it helps.


EDIT#1 - (PREVIOUS)NEW CODE EXAMPLE - for reference

I changed the code to be more reflective of our discussion. This is how it should look in final form. Notice I changed the name of the variable treePoints to treeClickNode for clarity.

 extends Button

    var points_cost = 10
    onready var treeClickNode = get_tree().get_root().get_node("treeClickableArea")

    func _on_Button_down():
        if treeClickNode.points >= points_cost:
            points_cost = (points_cost/2) + points_cost
            treeClickNode.pointAdder +=  1
            treeClickNode.points =  treeClickNode.points  - points_cost
Christopher Bennett
  • 803
  • 1
  • 8
  • 20
  • It still throws the same error... Let me check for spelling errors ONE more time, although this is the first thing I did, like 5 times. – CATboardBETA May 13 '20 at 21:52
  • I tried going back into my old code and adding "treeClickableArea" into the quotes, but the when I go to click on the upgraded, it returns with the error: "Invalid get index 'points' (on base 'null instance')" Any idea what this might mean? – CATboardBETA May 13 '20 at 21:56
  • 1
    `Attempt to call function 'get_root' in base 'null instance' on a null instance.` means Godot cant find a node you're trying to call, either from a spelling mistake or path error. Does Godot tell you what line the error is from? – Christopher Bennett May 13 '20 at 21:58
  • Yes. It is coming from line 7, and I just copy and pasted the node name to make sure it would work. Let me go and add my Node tree in case that helps. – CATboardBETA May 13 '20 at 22:02
  • Yeah, that would help. – Christopher Bennett May 13 '20 at 22:06
  • there we go, sorry I took so long. – CATboardBETA May 13 '20 at 22:18
  • Ok. Looking at your node setup, the engine should be finding the `treeClickableArea` node all right, but I'm wondering if it's having trouble accessing the `points` attribute. Try assigning the variable before the function like I did in the code above in the line `var treePoints = get_tree().get_root().get_node("treeClickableArea").points`, but make it an `onready var`. – Christopher Bennett May 13 '20 at 22:33
  • If that doesn't work, try `onready var treePoints = get_tree().get_root().get_node("treeClickableArea")`, and call on it in the function as `treePoints.points`, (Ex: `if treePoints.points) >= points_cost:`). – Christopher Bennett May 13 '20 at 22:35
  • OK, so My code is now extends Button ``` var points_cost = 10 onready var treePoints = get_tree().get_root().get_node("treeClickableArea") onready var treePointAdder = get_tree().get_root().get_node("treeClickableArea") func _on_Button_down(): if treePoints.points >= points_cost: points_cost = (points_cost/2) + points_cost treePointAdder.pointAdder += 1 treePoints.points = treePoints.points - points_cost ``` – CATboardBETA May 13 '20 at 22:46
  • but I am still getting the same error on line 9. (sorry the code came out so bad) – CATboardBETA May 13 '20 at 22:46
  • The onready var that you use calls the node (treeClickableArea) which has both the attributes: `points` and `pointsAdder`. Maybe I should have called it (treeNode) for clarity. Either way, you can access both the `points` and `pointsAdder` attrubutes from it. Therefore ,you can just call `treePoints.pointAdder` the same way you call `treePoints.points` you dont need to declare a second `onready var`. Does that make sense? – Christopher Bennett May 13 '20 at 23:10
  • I edited my answer with some new code, have a look above, I think it shows it better than I can explain it. – Christopher Bennett May 13 '20 at 23:20
  • OK, that all makes sense, I will test it myself when I can. I am personally more used to C and Java, and not so much of languages like this. Seeing code without semicolons or curly braces is quite odd to me. – CATboardBETA May 14 '20 at 00:12
  • I really do not know. It is still returning with the error: Invalid get index 'points' (on base 'null instance'). Here is another screenshot: – CATboardBETA May 14 '20 at 00:44
  • Yeah, I can't really tell without building and running the program myself. Last thing - try making `var points` an `onready var` in your `Area2D` script so it's ready when the button is looking for it. Other than that, i'm at a loss as to what to do. However, if you're used to C and Java, you might want to look into Godot's "singletons". They're basically pre-loaded scripts that sort of act as Godot's version of a global variable set. – Christopher Bennett May 14 '20 at 01:26
  • Ok, ill look into that tomorrow, (im crashing early tonight). In case you genius come up with anything else, here is a screenshot https://pasteboard.co/J8gASgN.png – CATboardBETA May 14 '20 at 02:16
  • 1
    I just tested, for some reason `get_parent().get_parent().get_parent().get_parent().get_node("treeClickableArea")` WORKS, but `get_tree().get_root().get_node("treeClickableArea")` DOESN'T. I don't know why, but it makes a difference. – Christopher Bennett May 14 '20 at 03:46
  • Hm. Odd. I guess I will use that instead then. – CATboardBETA May 14 '20 at 13:27
  • OK. It works fine. I greatly appreciate all the help. I really don't know where.i would be with Godot if it wasn't for you. – CATboardBETA May 14 '20 at 22:54