Verse multidimensional array assignment through for loop doesn't work as expected

Hi, looking for advice since most likely I just didn’t understand how Verse works, despite I’m reading the docs already for weeks. I spawn props in a grid of 2x2x2 or 3x3x3 let’s say, just a simple 3D array of props, a grid. The spawn works correctly, that’s the weird part, but referencing these existing props inside the array is impossible, it shows that all items of the array are empty except the first one (or the last one? I think the first one, yeah, the 1,1,1 item exists, and nothing else, in the array - but all the props are spawned correctly! how is it possible?)
Here is the code:


using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /UnrealEngine.com/Temporary/Diagnostics }
my_log_channel := class(log_channel){}
my_device := class(creative_device):
    # Create an instance of the `log` object.
    Logger:log = log{ Channel := my_log_channel }
    MyMethod()<transacts>:void =
        # Printing to the log will work in <transacts> and <varies> contexts
        Logger.Print("Something happened")

# A Verse-authored creative device that can be placed in a level
island_spawner := class(creative_device):
    Logger:log = log{ Channel := my_log_channel }
    GridLength : int = 2 
    GridDepth : int = 2 
    GridWidth : int = 2 

    var Counter : int = 0
    var IslandsGrid : [][][]?creative_prop = array{array{array{}}}

    @editable var FlyingIsland : creative_prop_asset = DefaultCreativePropAsset

    # Runs when the device is started in a running game
    OnBegin<override>()<suspends>:void=
        Print("init ok")
        PositionIslands()
        Print("Counter {Counter}")
        Print("IslandsGrid.Length {IslandsGrid.Length}")
        spawn:
            MoveIslands(IslandsGrid)

    PositionIslands():void=
        set IslandsGrid = 
            for (Row := 1..GridWidth):
                for (Column := 1..GridLength):
                    for (Layer := 1..GridDepth):
                        CreateIsland(Row, Column, Layer)

    CreateIsland(Xpos : int, Ypos : int, Zpos : int) : ?creative_prop=
        set Counter += 1
        PositionX := float(Xpos * 800.0)
        PositionY := float(Ypos * 800.0)
        PositionZ := float(Zpos * 600.0) - 500.0
        SpawnedCreativeProp := SpawnProp(FlyingIsland, vector3{X := PositionX, Y := PositionY, Z := PositionZ}, IdentityRotation())(0)
        
        if (GotAProp := creative_prop[SpawnedCreativeProp?]):
            Logger.Print("{Counter} prop spawned at: {PositionX} {PositionY} {PositionZ}")
            return SpawnedCreativeProp
        else:
            Logger.Print("{Counter} failed to spawn at: {PositionX} {PositionY} {PositionZ}")
            return false

    MoveIslands( Islands : [][][]?creative_prop)<suspends> : void = 
        loop:
            for (Row := 1..GridWidth):
                for (Column := 1..GridLength):
                    for (Layer := 1..GridDepth):
                        if (Island := Islands[Row][Column][Layer]?):
                            Print("Moving Island: {Row} {Column} {Layer}")
                            T := Island.GetTransform()
                            var IslandPosition : vector3 := T.Translation 
                            var IslandRotation : rotation := T.Rotation
                            #set IslandPosition.X += 1.0
                            set IslandPosition.Z -= 1.0
                            Island.MoveTo(IslandPosition, IslandRotation.ApplyYaw(0.10), 0.10)
                        else: 
                            Print("NO Island at: {Row} {Column} {Layer}")
            Sleep(0.5)

so the “Islands[Row][Column][Layer]” iteration after props were already created in the PositionIslands function, reveals that only 1 prop exists in the array, why? where’s the other props, they got spawned correctly but ended up not being added to the array? :open_mouth: please suggest the optimal way to initialize that array of props in order to control them later? (position, rotation, I need to control from the array, moving these props in various ways during the game).

Thanks in advance :pray:

so the log print shows “Print(“Moving Island: 1,1,1”)” and “NO Island at: …” for all other items in the array :frowning:

@PumbaMumba Thank you for your report! We would like to look into this further, would you be able to submit a bug report using the form available here? Fortnite Creative

It looks like you are trying to access the objects that are define in the props array, You need to store the spawned reference in an array and iterate against that.

inside of:
if(GotAProp := creative_prop[SpawnedCreativeProp?]):

You need to insert the GotAProp var into an array, building the array out as you iterate over the original array. Then later reference this new array to interact with the spawned props.

Edit: Also I could be wrong here, but in your for loops I believe you should be starting at index 0, not 1? ex:
for(Row := 0..GridWith - 1):

Thanks for the suggestion! Yes I’m using 1 on purpose, didn’t know it might be a problem in making the arrays work, but a good point actually, what if it’s what causes the bug (I just need the names and everything later to be numbered from 1 to N so I thought to also position index like that, leaving index 0 as null or whatever happens to it when not assigned).

Sure, will do tomorrow, it does seem like unexpected behavior indeed, especially because it finds and operates on 1,1,1 the first island in the grid, while all others “don’t exist” in the grid but are visually present since they were spawned, so spawn works and future referencing doesn’t.

@PumbaMumba Did you get this to work? Trying to do something similar.

nope, it didn’t work eventually so I kind of abandoned this experiment… I did the following change and updated the other function which iterates over it, but it still shows that ‘nothing’ is in the array

SpawnedCreativeProp := SpawnProp(FlyingIsland, vector3{X := PositionX, Y := PositionY, Z := PositionZ}, IdentityRotation())(0)
        
        if (GotAProp := creative_prop[SpawnedCreativeProp?]):
            Logger.Print("{Counter} prop spawned at: {PositionX} {PositionY} {PositionZ}")
            if (set CreatedIslandsGrid[Xpos][Ypos][Zpos] = GotAProp) {}
            return SpawnedCreativeProp
        else:
            Logger.Print("{Counter} failed to spawn at: {PositionX} {PositionY} {PositionZ}")
            return false

were you able to figure it out? iterating over spawned props? (the fact it causes any difficulty at all, for more than 2 people already, is ridiculous lol, because in any of the other 10 languages I’m familiar with, that would be trivial and straightforward code).
I suspect that this initiative by Epic will fail miserably… I just don’t see roblox kids picking up this language to make their game maps in fortnite :sweat_smile: (which is the main goal of the whole UEFN initiative, isn’t it?), so far the sentiment from all roblox devs I talked to was either “:nauseated_face:” or “:skull:” when asked about UEFN :see_no_evil:.

hi. @PumbaMumba

PositionIslands():void=
    set IslandsGrid = 
        for (Row := 1..2): #GridWidth : int = 2 
            for (Column := 1..2): #GridLength : int = 2 
                for (Layer := 1..2): #GridDepth : int = 2 
                    CreateIsland(Row, Column, Layer)

1..2 range creates a 2-element array, so this for loop creates a 2x2x2=8-element arrays as follows.

[0,0,0]
[0,0,1]
[0,1,0]
[0,1,1]
[1,0,0]
[1,0,1]
[1,1,0]
[1,1,1]
MoveIslands( Islands : [][][]?creative_prop)<suspends> : void = 
    loop:
        for (Row := 1..2):
            for (Column := 1..2):
                for (Layer := 1..2):
                    if (Island := Islands[Row][Column][Layer]?):

First, Island[row][column][layer] represents Island[1][1][1], so you can access [1,1,1],
Next, Islands[Row][Column][Layer] represents Islands[1][1][2], but [1,1,2] was not created.
Therefore, it is not accessible (same below).

1 Like

thanks for your help, but isn’t “1…2” explicitly tells it to use values “1” and “2” ? how in the world it ends up with a “0” inside the values of the list? (Verse tries to compete with JS in the bizarre-unexpected niche? :joy: definitely promising so far)

I wonder what will the effect of “0…1” be then o_O

oh well, the docs disagree - but you managed to confuse me for a moment :smiley: , still thanks for trying to help :wink: .

PositionIslands():void=
    set IslandsGrid = 
        for (Row := 1..2): #GridWidth : int = 2 
            for (Column := 1..2): #GridLength : int = 2 
                for (Layer := 1..2): #GridDepth : int = 2 
                    CreateIsland(Row, Column, Layer)

CreateIsland() returns creative_prop only.
At this time, The value returned by “1…2” is irrelevant .
Array indexes always start from zero.

ahh, I understand now, the IslandsGrid index which is set, will be by array rules and not if it was some map of index numbers to their values :man_facepalming: . Thanks for the explanation, I’m a real n00b :blush: only know JS/Python but decided to try this new syntax here and see what it does, imagined to myself that the index numbers will be keys in a map :sweat_smile: despite knowing I try to make an array, so silly.

1 Like