error: attempt to call function 'is_colliding' in base 'null instance' on a null instance - godot

I've just started making a basic fps in the Godot engine, and I'm currently stuck on making a basic Raycast weapon. I've looked up tutorials from Coding With Tom, Gabaj YT, and multiple others, and yet no matter which one, I always end up writing the same piece of code:
if Raycast.is_Colliding:
and no matter how exactly I copy it down, I always end up with the same error:
error: attempt to call function 'is_colliding' in base 'null instance' on a null instance.

Raycast is a class. And is_colliding is one of its methods. But it is not an static method, you need an instance of Raycast.
Chances are, you do have an instance. If you have been following the tutorials, presumably you have a Raycast node in the scene tree added from the editor, and it is called… let me guess… Raycast. Yes, I do it too. Until it begins to be an issue and I rename it to something more meaningful or go for a different approach, but I digress.
The issue is that you are not referring the Raycast instance. You can reference nodes from your script using $, like this: $Raycast. It is a shorthand for using the get_node method. See Nodes and scene instances. To be clear, what you put after $ is the relative path on the scene tree, so it might not be just the name of the node. Here I'm assuming the node is a direct child of the node that has the script you are writing.
Thus, I would expect code like this:
if $Raycast.is_colliding():
Granted, you will see code that does look like this:
if raycast.is_colliding():
That is because somewhere in the script they have a line that looks something like this:
onready var raycast := $Raycast
Which declares a variable raycast and - on ready - sets it to a reference to the node, and then they can continue using that variable form there. With video tutorials some might skim over that. Here I found it on a Garbaj video on the topic: Godot FPS Hitscan Weapons Tutorial at 1:52

Related

How to force reimport of texture in godot?

I have a sample.png file which is being changed outside godot
and after it's modified, godot recives a signal and when that signal is received
I want that specific sample.png file to be reimported
I tried this answer but I want to reimport in my script itself not create a plugin for it
(atleast that's what I'm assuming it does)
I also tried this from the documents but I'm not sure how to use it exactly
EditorFileSystem.update_file("res://Assets/sample.png")
so how do I achieve the desired result?
The class EditorFileSystem is intended for plugins.
You would call get_editor_interface() from an EditorPlugin (which would be where you would be writing code if you were making a plugin). And that gives you an EditorInterface object, on which you can call get_resource_filesystem() which gives you an EditorFileSystem object.
So the intended use is something like this:
extends EditorPlugin
func example() -> void:
var editor_file_system := get_editor_interface().get_resource_filesystem()
editor_file_system.scan_sources()
# editor_file_system.update_file("res://icon.png")
By the way, EditorInterface also has a filesystem_changed signal. Although I don't know how reliable it is.
Usually you don't have to do that. When you restore the Godot window, it will scan for changes in the project folder. So you might minimize Godot while you are working on something else and when you bring the Godot window back it will pick on the changes.
In practice, the only situations when I had to use scan or scan_sources was when I had a tool script that write a resource file which should be imported, and I wanted it to reflect right away.
Instead of making a custom plugin, I'll remind you that form a tool script (as long as it is running in the editor) you can simply create an EditorPlugin object. For example:
var ep = EditorPlugin.new()
ep.get_editor_interface().get_resource_filesystem().scan()
ep.free()
I had also shared this example in another answer I wrote for you a while back here, it is under the title "About saving resources from tool scripts".

Declarative Pipeline using env var as choice parameter value

Disclaimer: I can achieve the behavior I’m looking for with Active Choices plugin, BUT I really want this to work in a Jenkinsfile and controlled with scm because it’s tedious to configure the Active Choices on each job we may need them on. And with it being separate from the Jenkinsfile creation, it’s then one job defined in multiple places. :(
I am looking to verify if this is possible, because I can’t get the syntax right, if it is possible. And I haven’t been able to find any examples online:
pipeline {
environment {
ARTIFACTS = lib.myfunc() // this works well
}
parameters {
choice(name: "Artifacts", choices: ARTIFACTS) // I can’t get this to work
}
}
I cannot use the function inline in the declaration of the parameter. The errors were clear about that, but it seems as though I should be able to do what I’ve written out above.
I am not home, so I do not have the exceptions handy, but I will add them soon. They did not seem very helpful while I was working on this yesterday.
What have I tried?
I’ve tried having the the function return a List Because it requires a list according to the docs, and I’ve also tried (illogically) returning a String in the precise syntax of a list of strings. (It was hacky, like return "['" + artifacts.join("', '") + "']" to look like ['artifact1.zip', 'artifact2.zip']
I also tried things like "$ARTIFACTS" and ${ARTIFACTS} in desperation.
the list of choices has to be supplied as String containing new line characters (\n): choices: 'TESTING\nSTAGING\nPRODUCTION'
I was tipped off by this article:
https://st-g.de/2016/12/parametrized-jenkins-pipelines
Related to a bug:
https://issues.jenkins.io/plugins/servlet/mobile#issue/JENKINS-40358
:shrug:
First, we need to understand that Jenkins starts running your pipeline code by presenting you with Parameters page. Once you've set up the parameters, and pressed Build, then a node is allocated, variables are set, and your code starts to run.
But in your pipeline, as presented above, you want to run some code to prepare the parameters.
This is not how Jenkins usually works. It's definitely not doing the following: allocating a node, setting the variables, running some of your code until parameters clause is reached, stopping all that, presenting you with GUI, and then continuing where it left off. Again, it's not how Jenkins works.
This is why, when writing a new pipeline, your first option to build it is Build and not Build with Parameters. Jenkins hasn't run your code yet; it doesn't have any idea if there are any parameters. When running for the first time, it will remember the parameters (and any choices, if were) as were configured for this (first) run, so in the second run you will see the parameters as configured in the first run. (Generally, in run number n you will see the result of configuration in run number n-1.)
There are a number of ways to overcome this.
If having a "somewhat recent" (and not "current and absolutely up-to-date") situation fits you, your code may need minor changes to work — second time. (I don't know what exactly lib.myfunc() returns but if it's a choice of Development/Staging/Production this might be good enough.)
If having a "somewhat recent" situation is an absolute no-no (e.g. your lib.myfunc() returns the list of git branches, and "list of branches as of yesterday" is unacceptable), then your only solution is ActiveChoice. ActiveChoice allows you to run some code before showing you the Build with Parameters GUI (with script approval etc.).

Access var from another script in Godot

Node World contains two children- Pe2node and HUD.
Pe2node (Node2D) node has attached pe2.gd script and it has variable - shift.
HUD node (CanvasLayer) has attached HUD.gd script and I want display variable shift from Pe2node. I try some variants, but it don't work at all. I have ready to try autoload but may be there is simple way to get it work.
HUD.gd:
extends CanvasLayer
var fps=0
var shift_hud=0
func _process(delta):
fps = Engine.get_frames_per_second()
$var_fps.text=str(fps)
#shift_hud=get_node("Pe2node").get_variable("shift")
#shift_hud=get_node("Pe2node").shift
#shift_hud=get_node("World/Pe2node").shift
#shift_hud=$World/Pe2node.shift
$var_shift.text=str(shift_hud)
Node World contain 2 children - Pe2node and HUD
This means that Pe2node and HUD are siblings, right?
Let us go over you attempts:
get_node("Pe2node")
This is looking for a "Pe2node" child of the current node, not a sibling.
get_node("World/Pe2node")
And now you are looking for a "Pe2node" child of "World" child of the current node.
$World/Pe2node
Same as above.
You can either go one level up, like this:
get_node("../Pe2node")
Or like this:
$"../Pe2node"
Or you could have an absolute path, that I will not put example of, but if you print the result of calling get_path on the Node you want, it will show the absolute path (it starts with "/root/").
The reason why I often do not advice doing it the way I describe above is because it depends on the relative position of these nodes, which you might not move together, breaking the code.
A better way to do it - without going for the autoload solution - is to export a NodePath:
export var node_path:NodePath
Which you can set to the node you want in the inspector panel. And then we use it to get the node:
get_node(node_path)
This will work as long as the things you are connecting are in the scene tree from the start (you are not trying to get something instanced dynamically). And as long as that is the case, and you only manipulate the scene from the Godot interface, Godot can keep the NodePath updated.
As per the autoload solution, I would suggest to put signals there instead. You can have an autoload with just a signal like this:
extends Node
signal shift_changed(value)
That would be the whole code of the autoload.
You can create that script and then add it as an autoload in the project settings, with some name. I'll be using the name SingalBus.
And then from anywhere emit the signal:
SingalBus.emit_signal("shift_changed", value)
And from anywhere connect to it:
SingalBus.connect("shift_changed", self, "_on_shift_changed")
Which assumes a method something like this:
func _on_shift_changed(value) -> void:
pass
Which means that you no longer need any kind of node path at all, so there is no path that could break. Plus you can update the UI only when the value changes, instead of having it checking all the time. And there might not be something at the other side, so this works for things that are instanced dynamically too.
To be fair, you could put the variables on the autoload instead of the signals. That also works. And in some cases it is useful to put a reference to a Node there.
The advantage of placing the variables there is that it also gives you a single place to place them all, which might also be useful for a save/load feature, and also to keep them around when going from one scene to another.

Getting this error "add_child: Parameter "p_child" is null" and can't seem to track it down

add_child: Parameter "p_child" is null
I suspect this is a Godot editor error because the game runs fine.
This one is hard to describe but basically I have a "memory" card game that runs from a grid. You select your difficulty and then press New Game. The first time, there are no errors but if you win or select "New Game" the errors start piling up and they seem to double each time, maxing out at 100 errors each time you press the new game button.
The only thing on the googles seems to be related to C++ (which that p_child name definitely suggests) but I'm not using C++, I'm using GDScript... this is why I'm thinking maybe it's just an editor error and Godot is just getting confused that I didn't add_child in the C++ way.
Any thoughts?
EDIT
the code generating the errors is this:
func dealDeck():
randomize()
deck.shuffle()
var c = 0
while c < deck.size():
Game.get_node('grid').add_child(deck[c])
c += 1
Game is just a reference to the main scene (/root/Memory) and deck is an array created previously that contains all the cards. I'm 99% sure that the problem isn't in the deck creation.
and to be clear, I am clearing the grid when a new game is started but I have my suspicions that something is going wrong with the whole process (even though the game is working)
Since Godot was written in C++, the errors given in the console are from the C++ side of the editor. This does not mean that your GDScript code is not responsible for the error. It seems like you're trying to add a child to an object but the child you are trying to add is null. This may be due to many reasons. You should start by looking at how you add the cards to your scene when a new game starts. Also, if you could show us some of the code we may be able to help you further.

How to call a variable from a preload script in godot?

When I make a preload script in godot and put a variable in there, how do I call the variable in my other scripts?
Is there a special way to call the variable that I don't know or is there a better way to do it than preload scripts?
If you are preloading a script, e.g. const item = preload("res://scripts/item.gd") it acts as a type. That is, you can declare variables as it, and make instances of it. The variables declared on the script exist on its instances:
const Item = preload("res://scripts/item.gd")
var my_item:Item
func _ready():
my_item = Item.new()
print(my_item.variable)
See Custom variable types and Classes and nodes. By the way, no, there are no static variables in Godot, see "static" on Keywords table.
You could be preloading a scene instead of a script. In that case you get a PackedScene, similar rules apply. But you would be using the instance method.
Instead of doing this, I suggest to give a class_name to your script. Godot will recognize it and make it available everywhere. See Register scripts as classes.
Please note that this is different from accessing a variable defined on another node in the scene tree. If you are trying to access a variable defined in the script of another node in the scene tree, the use get_node or similar to access the node, and then you can access the variable on it. See Understanding node paths.
If you need a global variable, what you want is an "singleton" autoload. You can set a scene to autoload in the "AutoLoad" tab in your project settings (select the scene path, give it a name, and click "Add"). They will be available on the scene tree regardless of the scene. They persist changes of scene.
Since autoloads are on the scene tree, you can use get_node to access them. The path will "/root/" followed by the name you gave it. For example:
onready var global_variables = get_node("/root/GlobalVariables")
func _ready():
print(global_variables.variable)
If you want to have access to one script from 1 or more different scripts, It is not a good way to use preload script. (at least in my opinion)
I prefer to make an script, global in the project and have access to that script from other scripts and nodes.
Now how to do that?
Open a new or a prefered scene.
On top menu, under project scroll, click on Project Settings.
On Project Settings, click on Autoload tab and add the script that you want to have access to from everyscript in the game and ofcourse add a fine Node Name to it.
Now based on that Node Name, you can have access to anything inside that global script.
For example, if this is my global script that I Autoloaded it as Global node name:
extends Node
var num: int = 5
I can have access to num variable from every other scripts like:
Global.num = 6
Make sure to take a look at the AutoLoad Documentation for more info.

Resources