playMaker

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

ToxicFrog

  • Beta Group
  • Full Member
  • *
  • Posts: 139
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, 07:54:14 AM by ToxicFrog »

ToxicFrog

  • Beta Group
  • Full Member
  • *
  • Posts: 139
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, 11:04:54 AM by ToxicFrog »

ToxicFrog

  • Beta Group
  • Full Member
  • *
  • Posts: 139
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, 11:00:58 AM by ToxicFrog »

ToxicFrog

  • Beta Group
  • Full Member
  • *
  • Posts: 139
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, 11:03:09 AM by ToxicFrog »

Athin

  • Full Member
  • ***
  • Posts: 163
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

  • Beta Group
  • Hero Member
  • *
  • Posts: 772
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

  • Beta Group
  • Full Member
  • *
  • Posts: 139
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

  • Beta Group
  • Hero Member
  • *
  • Posts: 772
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).

curb47

  • Sr. Member
  • ****
  • Posts: 256
I've got exactly the same problem with an FSM using Array List Get Next.

I'm controlling a wave of 10 enemies, and when looping through the Array, each item (enemy) is re-parented and/or being destroyed, therefore the Array List is being compromised, and the loop 'finishes' without running through all the objects in the array.

I kind of understand what Broken Stylus is saying, but I can't work out how to implement his suggested fix for the problem. Can anyone help?

Thanks.

Broken Stylus

  • Beta Group
  • Hero Member
  • *
  • Posts: 772
Use the reset flag after each operation on the array or parent if you change its content. But it should be preferable to just loop through all items in the array with a get next and then purge the array after all processes have been handled.
That's why you could load all children as FsmGameobject variables, loop through all of them one by one and only then empty the array.

By default you have the FsmArray available in PM, but you can add the ArrayMaker add-on. Array List provides slightly different actions. This is a bit redundant with FsmArrays but the add-on shines with Hash Tables.

curb47

  • Sr. Member
  • ****
  • Posts: 256
Hello, I understand what you're saying, but I still don't understand how to action the solution. What is the Array Maker add-on? Is that an additional Action on the Ecosystem (add-on) or do you mean, as I have Array Maker already, I have the add-on?

Is the add-on i should be using - 'Array List' ?

I started a new thread here -

https://hutonggames.com/playmakerforum/index.php?topic=23380.0


Thanks.

Broken Stylus

  • Beta Group
  • Hero Member
  • *
  • Posts: 772
Check the Playmaker dropdown menu in Unity's top bar. If you have Addons > ArrayMaker, then yes, you have it already installed.

curb47

  • Sr. Member
  • ****
  • Posts: 256
Yes, I have ArrayMaker.

I'm not sure which ArrayMaker action you mean then, to get me through this.

Thanks.