Open jeadhz opened 3 months ago
Currently when you pass or assign an array, it is a reference.
So, if you do something like this:
func test() -> void:
var a := Wall.new()
var b := Wall.new()
var c := Wall.new()
var walls:Array[Wall] = [a, b, c]
var blocks:Array[Block] = walls # ERROR HERE
class Block:
var x:int
class Wall extends Block:
var y:int
The semantics is that you were to have a reference to the same array in both walls
and blocks
variables. But blocks
has a type that would allow to add to the array things that are not Wall
(such as an instance of another class that extends Block
, such as Tile
from your example), and thus breaking the type of walls
.
You could set a copy instead:
func test() -> void:
var a := Wall.new()
var b := Wall.new()
var c := Wall.new()
var walls:Array[Wall] = [a, b, c]
var blocks:Array[Block]
blocks.assign(walls)
class Block:
var x:int
class Wall extends Block:
var y:int
So, as far as I can tell, this is working as intended. Altough I admit this has biten me in the past. In particular, it is not expected if you come from a language where arrays are value types and have variance by default (which is easy in that case, because when arrays are value types you are always making a copy).
I suppose there are other ways Godot could handle this... The advantage of the current solution is that you are in control of when the copy happens. If you have some idea for an alternative approach, you might consider opening a proposal at https://github.com/godotengine/godot-proposals/issues However, be aware that a breaking change wold delay its implementation.
Anyway, I think the error message could be updated to suggest using assign
.
I'm aware of that solution. Thank you, I use it a lot. My problem comes when you try to pass that array as an argument (sorry if I was not very clear when explaining it)
For example:
placed_walls: Array[Wall]
remove_blocks(placed_walls) # Error here
func remove_blocks(Array[Block]) -> void: ...
The issue is that you can't pass any other than the same exact type to a typed array, even though the elements could be a subtype of it
Hope I've made myself understood ^^
Tested versions
Reproducible in 4.3.rc2
System information
Godot v4.3.rc2 - Windows 10.0.19045 - GLES3 (Compatibility) - NVIDIA GeForce GT 1030 (NVIDIA; 32.0.15.5599) - Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz (8 Threads)
Issue description
I have this base class for all blocks in my game:
And I have this 2 derived from it:
I store each of them like this:
These blocks have to be registered in the game before you can place them, but the thing is that you cannot assign an Array[Wall] to an Array[Block] even though the walls are derived from blocks
In conclusion, you can do:
but not:
or:
It doesn't take into account inheritance ~ . ~
Steps to reproduce
Copy and paste this code:
Or this one:
It's not exactly the same as in my project but it works in the same way
Minimal reproduction project (MRP)
n/a