playMaker

Author Topic: ArrayMaker 'Array List Get Next' sending event to only half of array [SOLVED]  (Read 287 times)

ToxicFrog

  • Junior Playmaker
  • **
  • Posts: 82
    • View Profile
Hi Playmakers,

I'm using 'Array List Get Next' to quickly send an event to every object in an Array. This is something that I use often with no problems.

However, this time, only 1/2 of the objects in the array are receiving the event. It skips every other one.

Here's the flow:

1.
Array List Get Next from 'Object: ArrayMaster'
Reference: ARRAY_Enemy01'
Type 'Game Object'
Variable 'Next _GO'

2.
Send Event to Game Object FSM
Game Object 'Next _GO'
Event: InstaDeath

3.
Next _GO receives event 'InstaDeath', which spawns an explosion effect and sends Event 'Despawn' to itself
'Despawn' removes owner from Array, then despawns from pool

4.
Loop to Step 1 until done, then FINISHED

HOWEVER,
This only works for every other object in the array. The ones that remain do not receive the 'InstaDeath' event.

I made a workaround for testing which fixes the problem, but it is a hack and should not be necessary. When the Loop is FINISHED, it goes to another state which uses Array List Count to see if there are more than 0 objects in the array. If so, it starts again at Step 1.
This again only works for every other object in the array (that did not get the event the first time), and again half of the objects remain.

This workaround will repeat until finally all of the objects get the event and despawn as intended, but I do not understand why this is happening. It should work the first time and I shouldn't need this workaround.

I want to understand what is happening so I can avoid problems!

I've attached images below that I hope will clarify what's going on. I appreciate any help!
« Last Edit: February 19, 2020, 05:54:14 AM by ToxicFrog »

ToxicFrog

  • Junior Playmaker
  • **
  • Posts: 82
    • View Profile
Image 1

Here you can see that when the Enemy is spawned, it adds itself to 2 Arrays:
ARRAY_Enemy01
ARRAY_EnemiesAll

« Last Edit: February 18, 2020, 09:04:54 AM by ToxicFrog »

ToxicFrog

  • Junior Playmaker
  • **
  • Posts: 82
    • View Profile
Image 2

At a point in the game, the Level's FSM gets the next object from ARRAY_Enemy01 and saves it as 'Next _GO'

Then it sends event 'InstaDeath' to Next _Go's Enemy_FSM

The InstaDeath event spawns an explosion effect, then sends Event 'Despawn' to its own 'Properties_FSM'

Properties_FSM then receives the Despawn event and removes the owner 'Self _GO' from the 2 arrays, then despawns itself.

But as you can see, it only succeeds for 1/2 of the objects in the array (every other one).

The ones that remain never received the 'InstaDeath' event as intended
« Last Edit: February 18, 2020, 09:00:58 AM by ToxicFrog »

ToxicFrog

  • Junior Playmaker
  • **
  • Posts: 82
    • View Profile
Image 3

For testing and debugging, I made an additional state. Once the Array Get Next loop is FINISHED, a new state counts the number of objects in ARRAY_Enemy01. If it's more than 0, it returns to Array Get Next.

Each time this happens, exactly half of the objects in the array get the InstaDeath event as intended.

Eventually, this workaround will clear the array as intended, but I should not need to use this workaround.

I don't understand why this is happening. I use Array List Get Next all the time and have never seen anything like this.

Any thoughts?
« Last Edit: February 18, 2020, 09:03:09 AM by ToxicFrog »

Athin

  • Full Member
  • ***
  • Posts: 135
    • View Profile
Heya,

I can't see exactly where the issue is but have a few ideas you can look into.

Try to put break points on the Get next array State and the instant death State.  I feel like you got something triggering a global event somewhere that is pulling the logic away each time.  Can't see the whole FSM in the screen shots so unsure if thats the case.

If you simply want to send the same action to everything in the array, you can skip the whole get next action all together and use the array list send event.  Basically the same thing you're doing but less steps.

The fact that its doing every other means to me its a logic error somewhere.  Break points will be your friend to find where the issue is.

Broken Stylus

  • Sr. Member
  • ****
  • Posts: 362
    • View Profile
The thing with parsers that scan arrays, array lists or hash tables, is that you must not modify the structure of the array, array list or hash table, during the entire looping process.

The action does not refresh the knowledge it has of the array but instead keeps in memory the snapshot it made when it started. If it did refresh itself at every loop, it would be pointless to loop since it would be a constant restart, forced to begin anew always at the same starting index (0 by default), which means you'd be quicker to simply use a [Something] Get action and do the looping yourself (you would build the looping structure with two or three states), and the moment no item would be found you would then finish the loop and move on to something else in the FSM.

Therefore you should actually use an intermediary array, and not necessarily an Array List component but an FsmArray type variable that you'll fill with the items you picked while looping inside the [Something] Get Next action, and work on this FsmArray.

ToxicFrog

  • Junior Playmaker
  • **
  • Posts: 82
    • View Profile
Thanks for the replies!

It turns out that the problem was as Broken Stylus said: The array was being modified by the objects removing themselves, which caused the skipping.

The solution was to set reset=true, which switches itself to false after the action starts, so I had another action set it to true again during the loop.

Thanks to our forum friend tcmeric for helping me figure this out!

Broken Stylus

  • Sr. Member
  • ****
  • Posts: 362
    • View Profile
The same applies to a Game Object acting as a parent (container) of other GOs.
You can't loop properly through a GO's children if you reparent its children or destroy them during the looping process (hence the point of using a FsmArray var to store the list of children to loop through).