getting position of a node in gdscript - godot

hi I'm trying to make a frog that jumps when the player gets close I tried this
onready var playerpos = get_parent().get_node("player").position
And
onready var playerpos = get_parent().get_node("player").global_position
and get this error
Invaled get index 'position' (on base: 'null instance')

Null instance means that the object you are trying to get, doesn't exist. And that is, because you are asking for its position, before it even enters the scene.
However, what you are trying to do, is completely unnecessary. You already have a main scene, so that should be able to access all of its nodes global position, without having to call the entire object.
Access your player's position from the main scene, not the frog scene.
That is, if you want the players position. What you want to do, however, does not require that.
You need to have an area node attached to the frog, that detects and sends a signal, when it detects a physics object. After which you simply check, whether the physics object is player or not, and execute the appropriate action.

According to GDDoc below:
https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#literals
You can use the dollar sign to get node:
onready var player = $player
onready var player_pos = player.position
onready var player_global_pos = player.global_position
Or, you can get the player's position directly:
onready var player_pos = $player.position
onready var player_global_pos = $player.global_position

Related

How to get the property name from key?

I'm trying to get a list of all the properties and the values that are being changed from an animation player node,
but how do I get the property name of node that the animation key is changing?
maybe something like this:
var ani=aniplayer.get_animation('running');
for i in range(0,ani.get_track_count()):
var key_idx=ani.track_find_key(i,0,0);
print("property=>",ani.get_key_property(i,key_idx)," new value=>",ani.track_get_key_value(i,key_idx));
Let us say you have an animation player:
var aniplayer := $AnimationPlayer as AnimationPlayer
And you get an animation by name:
var ani := aniplayer.get_animation("running")
As you know you can get the number of tracks the animations has:
var track_count := ani.get_track_count()
And, of course we can loop:
for track_id in range(0,track_count):
pass
Let us see, you want to know what property is being set. To get the property, we need to get the path, and extract the property from there:
for track_id in range(0,track_count):
var track_path := (ani.track_get_path(track_id) as String).split(":")
var node_path := track_path[0]
var property_path := track_path[1]
Addendum:
There is another way to get the property path from a NodePath: get_concatenated_subnames.
Or we can get the elements separated with get_subname.
So this is the property name:
var property_path = ani.track_get_path(track_id).get_subname(0)
I guess this is good time as any to bring attention to the fact that AnimationPlayer can animate sub-properties. With get_subname(0) you get the property, but not the sub-property.
For example, you don't have to animate position, you can animate position.y and you would do that by adding :y at the end of the track name in the Animation panel. I describe how to do it with more detail elsewhere. In this case get_subname(0) will give you position, but get_concatenated_subnames() will give you position:y.

I have a error in my godot script gdscript can you please solve it

onready var healthBar : TextureProgress = get_node("HealthBar")
func update_health_bar (curHp, maxHp):
healthBar.max_value = maxHp
healthBar.value = curHp
Error is: Invalid set index 'max_value' (on base: 'Nil') with value of type 'int'.
your healthBar was null when you called update_health_bar.
This might be because you don't have a children node called "HealthBar" or it is not a TextureProgress node.
Can you send a screenshot of your scene tree ?
It should look like this:
When I encounter such an error, it usually is because I am instancing the scene dynamically via scripts, and to get around the null error I create a init function to assign the node.
So in your case, after instancing your scene and adding it to the scene tree, call init on your scene, where you init function is as follows:
func init():
healthBar=get_node("HealthBar")
Maybe that might work.

Error message "Invalid set index 'text' (on base: "null instance") with value of type 'String' " when trying to change the text of a label

i am trying to update the text of a label but keep getting the above error message. i don't know what i am doing wrong. here is my code:
extends Node
var PlayerScore = 0
var EnemyScore = 0
func _on_Left_body_entered(body):
$Ball.position = Vector2(640,360)
EnemyScore += 1
func _on_Right_body_entered(body):
$Ball.position = Vector2(640,360)
PlayerScore += 1
func _process(delta):
$PlayerScore.text = str(PlayerScore)
$EnemyScore.text = str(EnemyScore)
$PlayerScore is shorthand for get_node("PlayerScore") which means it checks direct child with name "PlayerScore". Your error shows that (on base: ”null instance“) which means that you were accessing null instance (it doesn't exists, at least as direct child or at that moment).
P.S.
Since you are calling it that often I'd suggest save the reference to that node in a script's global variable.
onready var playerScore: = $PlayerScore #variable will be created when script's owner is ready
The solution that I implemented was to put the Label in another scene.
You will decide if you put it above or below the scene you are using.
I do not understand why it happens but for some reason it does not allow to read or update the text in a main scene. It usually happens to me in the scenes that it starts to execute.

How do I make a kinematic body (3d) follow a player

I've been making a FPS in Godot and I'm having a hard time getting the kinematic body (the enemy) to go towards the player. Could someone please help?
The simplest way to do this is to get the player's position, compare it to the enemy position, and make the enemy move towards it every frame.
Full example code is at the bottom.
To get the player's position you first need a reference to it. You can usually do this through storing the reference in global singleton (autoload) or by exposing a public property.
If you are doing it with a global singleton, then you get the position by calling var player_position = my_singleton.player.global_transform.origin
If you are using an exported property, then you would get the position by calling var player_position = get_node(path_to_player).global_transform.origin
Once you have the player position, you can compare it to the enemy by writing var direction_to_target = player_position - global_transform.origin from inside the enemy node.
Now in order to follow the player, we override the _physics_process method with something like this:
### Inside the enemy script
var ENEMY_SPEED= 50
func _physics_process(delta):
var player_position = my_singleton.player.global_transform.origin
var direction_to_target = (player_position - global_transform.origin).normalized() # We normalize the vector because we only care about the direction
move_and_slide(direction_to_target * ENEMY_SPEED) # We multiply the direction by the speed

Hololens Placing Objects With Spatial Understanding

I have been running SpatialUnderstandingExample scene from holo-toolkit. Couldnt figure out how to place my objects into the scene. I want to replace those small boxes that comes default with my own objects. How can I do that?
Thanks
edit: found the draw box but how do i push my object there?
edit2: finally pushed an object at the position but still code is very complicated its messing up with the size and shape of my object. Will try to make it clean and neat.
It's been a while since I've looked at that example so hopefully I remember its method name's correctly. It contains a "DrawBox" method that is called after a successful call to get a location from spatial understanding. The call that creates the box looks something like this:
DrawBox(toPlace, Color.red);
Replace this call with the following (assuming "toPlace" contains the results from the spatial understanding call and "model" contains the model you are trying to place there):
var rotation = Quaternion.LookRotation(toPlace.Normal, Vector3.up);
// Stay center in the square but move down to the ground
var position = toPlace.Postion - new Vector3(0, RequestedSize.y * .5f, 0);
// instantiate the hologram from a model
GameObject newObject = Instantiate(model, position, rotation) as GameObject;
if (newObject != null)
{
// Set the parent of the new object the GameObject it was placed on
newObject.transform.parent = gameObject.transform;
}

Resources