Why can't I call a func on an instance? Invalid call. Nonexistant function [funcname] in base 'Spatial'

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By MisterAcoustic

Apologies in advance, I’m brand new at this.

I have a scene (.tscn) that contains a Spatial with a child MeshInstance of a rock model.

In my main scene, I load the rock scene, and call .instance.

On the instance, I thought I could call a function in the scene script, but I get “Nonexistant function ‘Initialize’ in base ‘Spatial’”.

I’m sorry to say, I don’t know why :).

(Quick background: trying to make a moving asteroid field. I put initial rotation code in the rock scene, thinking it would get called when instanced. Moved the code to an Initialize function, which I cannot call. Also have _process code that I would like to be called on each to rotate each rock, but it doesn’t get called. I’d like some help with that too :slight_smile: )

Entire rock scene script:

extends Spatial

var minRotationalVelocity = 0.0
var maxRotationalVelocity = 0.040


var RNG = RandomNumberGenerator.new()

var xRotationVelocity = 0

var yRotationVelocity = 0

#var zRotationVelocity = RNG.randf_range(minRotationalVelocity, maxRotationalVelocity)

# Called when the node enters the scene tree for the first time.
func _ready():
	pass
	
func Initialize():
	
	print("Initialize Called")
	print("I am a rock")

	RNG.randomize()

	xRotationVelocity = randomNegate(RNG.randf_range(minRotationalVelocity, maxRotationalVelocity))

	RNG.randomize()
	
	yRotationVelocity = randomNegate(RNG.randf_range(minRotationalVelocity, maxRotationalVelocity))


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	
	var b = Basis()
	var xaxis = b.x
	var yaxis = b.y
	var zaxis = b.z
	
	rotate(xaxis, xRotationVelocity)
	rotate(yaxis, yRotationVelocity)
	#rotate(zaxis, zRotationVelocity)
	
	orthonormalize()
	
func randomNegate(value):

	var doIt = RNG.randi_range(1, 2)
	print(doIt)

	if(doIt == 2):
		value = -value

	return value

And entire main scene script:

extends Spatial

var initialObjectCount = 1000
var maxObjectCount = 50000
var maxDistanceFromOrigin = 100.0

var objectCount = 1

func AddObjects():

	if (objectCount >= maxObjectCount):
		return

	var numberToAdd  = clamp(objectCount * 2, initialObjectCount, maxObjectCount)

	var objectScene = load("res://moss rock 05.tscn")
	
	if(objectScene):

		print("LOADED")

		for i in range(objectCount, numberToAdd):

			var newObject = objectScene.instance()
			
			newObject.Initialize()
			
			var t = newObject.transform

			t.origin = Vector3(randf() * maxDistanceFromOrigin, randf() * maxDistanceFromOrigin, randf() * maxDistanceFromOrigin) - Vector3(0.5 * maxDistanceFromOrigin, 0.5 * maxDistanceFromOrigin, 0.5 * maxDistanceFromOrigin)

			newObject.set_transform(t)
			
			add_child(newObject)
			
			newObject.set_process(true)
			
		objectCount = objectCount + numberToAdd
			


	else:
		print("Failed to load asteroid object scene")

# Called when the node enters the scene tree for the first time.
func _ready():
	randomize()
	AddObjects()

var mouse_sens = 0.3
var camera_anglev=0

func _input(event):         
	if event is InputEventMouseMotion:
		$Camera.rotate_y(deg2rad(-event.relative.x*mouse_sens))
		var changev=-event.relative.y*mouse_sens
		if camera_anglev+changev>-50 and camera_anglev+changev<50:
			camera_anglev+=changev
			$Camera.rotate_x(deg2rad(changev))

Look into using a ‘singleton’ to make functions global, that’s going to be something handy for you to understand, probably in this context.

I think this might be helpful also: https://www.youtube.com/watch?v=iq4eOaox5Oo&t=7s

I’m relatively new to godot and I’m realizing it’s important to create some fully functional super simple games and picking up the concepts along the way as you build more and more complex games.

ryanscott | 2020-05-03 12:35

:bust_in_silhouette: Reply From: hilfazer

My only idea is that your “res://moss rock 05.tscn” scene doesn’t have the script attached.

Thanks for your answer. I’m so new, I don’t know how to check for certain if it’s attached to the scene - it sure looks like it is to me, but… If I just add a single instance of the rock scene to the main scene using the editor instead of code, that rock is oriented properly and rotates. Does that confirm the script is attached to the scene?
EDIT: It turns out I lied. I thought I was using the scene before, but I was using a MeshInstance - so adding the rock scene to the main scene in the editor does NOT give the correct behavior. I re-added a MeshInstance (and figured out how to attach the script), and that single one works. Still tinkering…

MisterAcoustic | 2020-05-03 16:30

Okay - it turns out that was it! Thank you very much!

I think I had multiple confusions about what was happening when I did things in the editor.

I finally realized that the scene did not have the script attached (probably because it was created when the thing was a MeshInstance). I was able to drag and drop the .gd script file to the top level Spatial node in the rock scene, and voila! All my instances behaved as expected (after taking out Initialize, and restoring that code in the _ready function).

Thanks again!

MisterAcoustic | 2020-05-03 17:14