+2 votes

Quite an odd question but I have a fatal error about a variable returned by get_collider from a raycast.

Usually it returns null or an object. And the condition "extends" does the job to tell if the object type is valid.
But sometimes, especially with lot of free_queue happening at the same time, the variable is the number 0. And godot doesn't like doing an extends on a number. It does not like it at all. It says

Left operand of 'extends' is not an instance of anything.

But if I try to check if the variable != 0, it crashes as well and says:

Invalid operands 'Object' and 'int' in operator '!='.

Then how am I supposed to avoid the error?

asked Apr 13, 2016 in Engine by Gokudomatic2 (689 points)

1 Answer

+7 votes
Best answer

You need to use global function:
int typeof( Variant what )
it will return one of the following global constants:

TYPE_NIL = 0  Variable is of type nil (only applied for null).
TYPE_BOOL = 1  Variable is of type bool.
TYPE_INT = 2  Variable is of type integer.
TYPE_REAL = 3  Variable is of type float/real.
TYPE_STRING = 4  Variable is of type String.
TYPE_VECTOR2 = 5  Variable is of type Vector2.
TYPE_RECT2 = 6  Variable is of type Rect2.
TYPE_VECTOR3 = 7  Variable is of type Vector3.
TYPE_MATRIX32 = 8  Variable is of type Matrix32.
TYPE_PLANE = 9  Variable is of type Plane.
TYPE_QUAT = 10  Variable is of type Quat.
TYPE_AABB = 11  Variable is of type AABB.
TYPE_MATRIX3 = 12  Variable is of type Matrix3.
TYPE_TRANSFORM = 13  Variable is of type Transform.
TYPE_COLOR = 14  Variable is of type Color.
TYPE_IMAGE = 15  Variable is of type Image.
TYPE_NODE_PATH = 16  Variable is of type NodePath.
TYPE_RID = 17  Variable is of type RID.
TYPE_OBJECT = 18  Variable is of type Object.
TYPE_INPUT_EVENT = 19  Variable is of type InputEvent.
TYPE_DICTIONARY = 20  Variable is of type Dictionary.
TYPE_ARRAY = 21  Variable is of type Array.
TYPE_RAW_ARRAY = 22
TYPE_INT_ARRAY = 23
TYPE_REAL_ARRAY = 24
TYPE_STRING_ARRAY = 25
TYPE_VECTOR2_ARRAY = 26
TYPE_VECTOR3_ARRAY = 27
TYPE_COLOR_ARRAY = 28
TYPE_MAX = 29
answered Apr 13, 2016 by kubecz3k (1,253 points)
selected Apr 13, 2016 by Gokudomatic2

Thank you for your answer. I'm very sure this is the proper way to check it.
But I still get an error. The variable is of type 18 (object) but the debugger says it's 0. I guess it's a bug in the engine. I'll open a ticket in the bug tracker.

From my experience: when debugger say it's 0 it usually means it's a reference to some object... from your description it feels fishy indeed. If you decide to open an issue on github it would be great if you could provide some small sample project in which it's possible to observe this.

As a workaround I would propose to test first if it's null, if not then test it with typeof, if it returns 18 (an object) -> then before using 'extends' maybe one of the following checks would work: is_queued_for_deletion() or is_inside_tree or is_in_group(the last one can be used instead of extends if you put your 'collision nodes' into proper groups)

I tried some check, but it's neither null nor is a valid object. Any call on this variable gives an error.
If 0 is the value displayed in the debugger of an object, it can only mean that the object is in an invalid state. And I believe it's a real bug.
I'll try to create a small demo project, but the node that causes the problem is not found yet.

Yes I also believe it's a bug (some really nasty one), but in meantime one more thought come to my mind... had you check raycast.is_colliding() before actually using get_collider()? If not then it's possible raycast is not colliding, but is returning the reference to the last object for which collision was detected.. and that object might be already destroyed.

I do make a check is_colliding() before that. But it happens only after a lot of staticbodies were queue_freed. And very probably one of those makes the problem.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.