Skip to content

BaseForEachAction

BaseForEachAction is an abstract base class for loop actions that run the state once for each item in a collection or for each iteration in a counted loop.

It provides the shared looping behavior used by actions such as ForEachListItem, ForEachChild, and Loop.

Core Functionality

The class provides:

Loop Start Behavior

BaseForEachAction marks the action as starting a loop:

public override bool StartsLoop => true;

This tells PlayMaker that the action will repeatedly run the state as part of a loop.

Current Index Output

The optional _currentIndex output stores the current loop index.

This value is updated before each iteration, so other actions in the same state can use it.

Reset On Exit

The _resetOnExitState option controls whether the loop progress is reset when the state exits.

This is useful when you want the loop to restart from the beginning every time the state is entered again.

Required Members

Inheritors must implement:

protected abstract int ItemCount { get; }
public abstract void EachAction(int index);

ItemCount returns how many items or iterations the loop should process.

EachAction(int index) sets up the data for the current iteration.

How It Works

BaseForEachAction advances one item per loop pass:

  1. OnStart() checks ItemCount
  2. It stores the current index in _currentIndex
  3. It calls EachAction(index) for the current item
  4. It advances to the next item
  5. When the last item is reached, it stops the loop and calls OnLoopFinished()

This means the derived action usually only needs to expose the current item for the rest of the state to use.

Optional Override

Inheritors can also override:

protected virtual void OnLoopFinished()

Use this if the action needs to do extra work when the loop completes.

Debug Info

In the Unity Editor, BaseForEachAction provides debug info showing the current progress:

currentIndex/itemCount

For example:

2/5

Example

ForEachListItem is a typical example:

using System;
using System.Collections;
using JetBrains.Annotations;
using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{
    [Serializable, PublicAPI]
    [ActionCategory(Category.Loop)]
    [ActionDescription("Run actions in this state on each item in a list.")]
    public class ForEachListItem : BaseForEachAction
    {
        [BaseType(typeof(IList))]
        [Tooltip("The list variable.")]
        [SerializeReference] 
        private IListVariableRef _list;

        [MatchType(nameof(_list))]
        [Tooltip("The current item retrieved from the list.")]
        [SerializeReference, WriteOnly] 
        private IVariableRef _item;

        protected override int ItemCount => _list.ListVariable?.Count ?? 0;

        public override bool CanExecute() => CheckParameters(_list, _item);

        public override void EachAction(int index) => _item.SetValue(_list.ListVariable[index]);
    }
}

With this setup, the base class handles the loop flow and index tracking, and the derived action only needs to provide the item count and expose the current item for each iteration.