How to call a variable from a preload script in godot? - 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.

Related

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

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

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".

Invoke a function on tool mode script reload

How do I invoke a function every time the Script is loaded or reloaded?
tool
func _reload():
print("Changes have been made and saved! Script has been reloaded")
func _load():
print("Project was just opened! Script has been loaded")
I'm not sure what you mean by reloaded (or why it is an issue), but it probably is one of these:
When you add a Node to the scene tree (or when you enable a plugin, which is adding the EditorPlugin to scene tree of the editor), or when it is loaded (all plugins are loaded when you load the project), the code in _enter_tree will run. Similarly when it is removed (or when the plugin is disabled), the code in _exit_tree will run. Be aware that for tool scripts that you run manually (EditorScript), these don't work. So make a Node (or an EditorPlugin).
There is a signal that will notify when the script of an object changed. It is appropriately named "script_changed". So if you want to handle the situation when the tool script was modified, and thus reloaded, you could connect to that signal. You may also want to take advantage of the of _init, which is the first virtual method that Godot calls (on Nodes you can also use _enter_tree and _ready). The signal "script_changed" is emitted before _init is called in the new script.
If you want to handle when properties of a Node are modified (I'm including this since you mention "changed has been made"), you would have to use setters (with setget), or you could intercept the properties in _set.
Since you mention "Project was just opened", I think you want to make an EditorPlugin, and then you can use _enter_tree and _exit_tree.
I haven't found a way to get a notification when the currently edited scene on the editor is saved. However, saving the scene does not mean tool script are loaded or reloaded in anyway.

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.

FISH: How to set a specific $fish_function_path while launching fish?

I'm trying to use the sshrc to execute fish with my own defined functions at the remote server.
I know there is a $fish_function_path variable that I can modify to prepend my custom path with my functions, but this variable seems global and I don't want to affect other fish users.
Is there any way to change this variable only for my single fish session or any other ways to use my fish functions only for a single session?
I have also tried setting and environment variable from the outer shell: fish_functions_path="$MY_FUNCTIONS_PATH" fish but it seems environment variables don't affect those inner variables of fish.
Used this docs.
Thanks!
Global variables, including $fish_function_path, are per-session. You might be thinking of universal variables, which are shared across sessions for a given user.
It should be fine to modify $fish_function_path for a given instance of fish - it won't affect any others.

Resources