Help with AI script in particular null instances

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Evan Symonds
:warning: Old Version Published before Godot 3 was released.

Hi, I’m very new to the godot engine (and pretty new to coding altogether) and I’m trying to piece together a very small game. I’m making a very basic ai zombie that I’m hoping to be able to clone. I wrote this script:

extends KinematicBody2D

var speed = 150

func _ready():    	
	set_fixed_process(true)    	
	pass

func _fixed_process(delta):
	
	var move = Vector2()
	var body = get_node("player")
	
	if body.get_global_pos() != 0:
       move = body.get_global_pos() - self.get_global_pos()
       move(move)
		

and I’m getting the error : ‘Attempt to call function ‘get_global_pos’ in base ‘null instance’ on a null instance.’ I have looked up what it means and people seem to say the path is wrong when that comes up however I have checked it and it is correct.

Please do help and point out all the things I have done wrong as I would love to learn more about this great engine.

Thanks
P.S I have indented all the lines correctly it is just showing up strange

I have fixed your indentation and caps lock issue on the title, to keep indentation on text just select it and use the “code sample” button.


As for the null instances, these are usually null instances, check the tree on the remote inspector while running to be sure the nodes are where you are looking for, in this case, “player” needs to be children of the node that use the script.

eons | 2017-06-16 17:12

Thank you for fixing those things.

I’m confused, how do you find the position of a sibling node then?

Thank you!

Evan Symonds | 2017-06-16 17:15

There are many ways to “navigate” the tree, you can get_tree().get_root() that gives you the main viewport where all the scenes are added (current and “autoloaded”), then you can use get_node with a notation like a terminal/console, ‘“scene_root/node1/child1”’.

Is possible to get the sibling of a node with get_parent().get_node("sibling_name") or (since get node is relative) get_node("../sibling_name").

I prefer to use groups so the script won’t depend on the scene structure or even node names, I add the player to the group “player” then get_tree().get_nodes_in_group("player")[0] (with a size check before accessing “0” if you want it to work when there is no player around)

eons | 2017-06-16 17:44

Thanks, the …/ thing seems to work fine but now it is doing the null instance on get_global_position. Any idea how to fix this.

Sorry for bugging you but I couldn’t find the info anywhere else online.

Evan Symonds | 2017-06-16 17:48

When it stops, check the debugger, remote inspector and look if the node you were trying to get exists (same parent and the exact name).

eons | 2017-06-16 19:27

I just want to find out how to send the position between two kinematic bodies on the same level of the tree. I want my ‘zombie’ to be able to know where my player is. Thanks for helping.

Evan Symonds | 2017-06-16 19:33

How about sending a signal? There’s a video in this series that shows you how.

https://www.youtube.com/playlist?list=PLsk-HSGFjnaFISfGRTXxp65FXOa9UkYc5

whooshfrosted | 2017-06-16 22:21

:bust_in_silhouette: Reply From: eons

For me, the best way to locate a node is to have it on a group (like “zombie_target”), then, if it is going to be used all the time prepare a instance variable to store a reference to the node:

var target = null

Then on _ready or a function triggered by something (like a timer, animation, etc.) do

var target_group = get_tree().get_nodes_in_group("zombie_target")
if target_group.size() > 0:
  target = target_group[0]

when processing and trying to use the variable

if target != null: 
  do_something_with_target()
#else search_for_target_again?

You need null checks in case you free the target or for some reason enters later to the scene (and to try to find it again if “respawn”), also to test it without a target.

Using groups you can mark anything (with position) as target and test your zombies.


Depends on the design but the reverse can be done too, mark the zombies as “enemy” and then (when player is ready) make the player do get_tree().call_group(SceneTree.GROUP_CALL_DEFAULT,"enemy","set_target",self) where enemy.set_target sets the target property.

Thank you for this.
I’m trying the group thing but cannot progress as I don’t know what ‘.size’ actually means and every time I look it up it tells me about godot resolution and scaling.
Hmmmmm

Evan Symonds | 2017-06-17 06:43

THANK YOU SO MUCH I HAVE FINALLY GOT IT WORKING WITH A BIT OF TINKERING.
YOU HAVE SAVED ME :slight_smile:

Evan Symonds | 2017-06-17 07:59

The method to get nodes in a group returns an array, size() is to check that array’s length Array — Godot Engine (stable) documentation in English

eons | 2017-06-17 14:25