Cannot assign value of type 'State' to a variable of type 'State'

Godot Version

4.4

Question

I have the following error:
image

The parser is not happy that I’m assigning a State… to a State. This is what Player.Jump looks like:

I understand that the engine stores classes as Resources, however even when I extend the Script class, this problem remains:
image

I’m not sure if this is a bug or if there is some workaround, as this is quite unfortunate. You can see that if I use the more generic ‘Script’ class, there is no issue:

image

It seems to be specifically upset about my classes. Technically, typing the variable as a Script is fine, however I would like the auto-complete suggestions.

Why don’t you just pull out the Jump into its own file and make it a proper class_name? It’ll easily fix your problem. I honestly don’t see a good reason to store your states within the Player class anyway.

It’s actually stored as RefCounted, not Resource. Maybe that’s somehow the reason for these errors.

1 Like

you’re missing a .new() after = Player.Jump. Right now you use State like an enum, but classes are different.

I guess your state should either be Node or a RefCounted depending on how you want to work with it.

The reason for your error is simply the try to assign a type to a variable that’s supposed to store an instance of a class.

The idea is that the stored state of the player is separate from the physics simulation. You wouldn’t actually instance Player, it’s just a class for static functions.

The script on the CharacterBody3D in the simulation calls functions from the class Player to give it behavior.

In other words, a Player is not a concrete thing… just a set of possible behaviors. Anyways, this issue forced me to think about the problem more and I think I’ve found another solution that is maybe better.

Also, I’m curious where you heard that inner classes are instances of RefCounted?

As you can see in the image, the Parser is happy to say that Player.Jump is an instance of script, which I guess does inherit from RefCounted, but wouldn’t it be upset if it wasn’t also a Script?

The type of Player.Jump does inherit from Script, and you only gave it the type, instead of an instance (via Player.Jump.new())

I also have a hard time looking that information up on the web, but it can be verified easily with this test:

extends Node

class MyInnerClass:
	var my_variable: int

func _ready() -> void:
	var my_inner_class_instance = MyInnerClass.new()
	print(my_inner_class_instance)
	print(my_inner_class_instance.get_class())

The output of that code is

<RefCounted#-9223372009860233829>
RefCounted

So that means that if you don’t extend anything explicitly, it will by default be extending RefCounted.

If you explicitly say it extends Resource it will actually extend whatever you say it should extend, e.g. this:

extends Node


class MyInnerClass:
	extends Resource
	var my_variable: int


func _ready() -> void:
	var my_inner_class_instance = MyInnerClass.new()
	print(my_inner_class_instance)
	print(my_inner_class_instance.get_class())

outputs

<Resource#-9223372009860233829>
Resource

However, even though it extends the Resource, it doesn’t behave like a Resource, e.g. I still can’t export it into the inspector, or create a .tres file of this type. So I’m not sure this is meant to be working this way extending other classes than the default RefCounted. If you need a Resource, just create it in a separate file.