playMaker

Author Topic: (Solved) Index was out of range on Array. Help finding the exact array.  (Read 793 times)

Aaddiction

  • Full Member
  • ***
  • Posts: 166
Code: [Select]
Index was out of range. Must be non-negative and less than the size of the collection.
I get this log on the console and it's obvious what is the issue if I knew which is the exact array. I have a lot of arrays and I can't pinpoint the exact action and array causing this message. Do you have and idea how to identify the exact source of the message?

Thank you.
« Last Edit: May 19, 2022, 09:45:52 AM by Aaddiction »

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7616
    • jinxtergames
Re: Index was out of range on Array. Help finding the exact array.
« Reply #1 on: May 18, 2022, 10:13:18 AM »
Hi.
If you select the error, there should be a reference the the action .cs script (for example ArrayGet.cs)

edit the action and add this line :

Code: [Select]
Debug.LogError("Index out of Range: " + index.Value + " / GO Name :" + Fsm.OwnerName + " / FSM :" + Fsm.Name + " / State : " + Fsm.ActiveState, Fsm.Owner);
right above the :
Code: [Select]
Fsm.Event(indexOutOfRangeEvent);
like this sample code on Array Get (line 72)

Code: [Select]
// (c) Copyright HutongGames, LLC 2010-2014. All rights reserved.

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{
    [ActionCategory(ActionCategory.Array)]
    [Tooltip("Get a value at an index. Index must be between 0 and the number of items -1. First item is index 0.")]
    public class ArrayGet : FsmStateAction
    {
        [RequiredField]
        [UIHint(UIHint.Variable)]
        [Tooltip("The Array Variable to use.")]
        public FsmArray array;

        [Tooltip("The index into the array.")]
        public FsmInt index;

        [RequiredField]
        [MatchElementType("array")]
        [UIHint(UIHint.Variable)]
        [Tooltip("Store the value in a variable.")]
        public FsmVar storeValue;

        [Tooltip("Repeat every frame while the state is active.")]
        public bool everyFrame;

        [ActionSection("Events")]

        [Tooltip("The event to trigger if the index is out of range")]
        public FsmEvent indexOutOfRange;

        public override void Reset()
        {
            array = null;
            index = null;
            everyFrame = false;
            storeValue = null;
            indexOutOfRange = null;
        }

        public override void OnEnter()
        {
            DoGetValue();

            if (!everyFrame)
            {
                Finish();
            }

        }

        public override void OnUpdate()
        {
            DoGetValue();

        }

        private void DoGetValue()
        {
            if (array.IsNone || storeValue.IsNone)
            {
                return;
            }

            if (index.Value >= 0 && index.Value < array.Length)
            {
                storeValue.SetValue(array.Get(index.Value));
            }
            else
            {
                Debug.LogError("Index out of Range: " + index.Value + " / GO Name :" + Fsm.OwnerName + " / FSM :" + Fsm.Name + " / State : " + Fsm.ActiveState, Fsm.Owner);
                Fsm.Event(indexOutOfRange);
            }
        }

        /* Not sure it's a good idea to range check at edit time since it can change at runtime
        public override string ErrorCheck()
        {
            if (index.Value<0 || index.Value >= array.Length)
            {
                return "Index out of Range. Please select an index between 0 and the number of items -1. First item is index 0.";
            }
            return "";
        }*/

#if UNITY_EDITOR
        public override string AutoName()
        {
            return ActionHelpers.GetValueLabel(storeValue.NamedVar) + "=" + array.Name + "[" + ActionHelpers.GetValueLabel(index) + "]";
        }
#endif
    }
}

if you want the log only happen in the editor, then add it in this way :

Code: [Select]
#if UNITY_EDITOR
                Debug.LogError("Index out of Range: " + index.Value + " / GO Name :" + Fsm.OwnerName + " / FSM :" + Fsm.Name + " / State : " + Fsm.ActiveState, Fsm.Owner);
#endif

when you select the error it gives, it should highlight in the hierarchy, but the name will also be printed in the error (in case the object gets removed)

If you want the editor Not to stop, rename the "Debug.LogError" to "Debug.LogWarning"

Fat Pug Studio

  • Beta Group
  • Hero Member
  • *
  • Posts: 1294
    • Fat Pug Studio
Re: Index was out of range on Array. Help finding the exact array.
« Reply #2 on: May 18, 2022, 12:57:01 PM »
That should be added in all array actions tbh.
Available for Playmaker work

Aaddiction

  • Full Member
  • ***
  • Posts: 166
Re: Index was out of range on Array. Help finding the exact array.
« Reply #3 on: May 18, 2022, 01:48:01 PM »
Hi.
If you select the error, there should be a reference the the action .cs script (for example ArrayGet.cs)

edit the action and add this line :

Code: [Select]
Debug.LogError("Index out of Range: " + index.Value + " / GO Name :" + Fsm.OwnerName + " / FSM :" + Fsm.Name + " / State : " + Fsm.ActiveState, Fsm.Owner);
right above the :
Code: [Select]
Fsm.Event(indexOutOfRangeEvent);
like this sample code on Array Get (line 72)

Code: [Select]
// (c) Copyright HutongGames, LLC 2010-2014. All rights reserved.

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{
    [ActionCategory(ActionCategory.Array)]
    [Tooltip("Get a value at an index. Index must be between 0 and the number of items -1. First item is index 0.")]
    public class ArrayGet : FsmStateAction
    {
        [RequiredField]
        [UIHint(UIHint.Variable)]
        [Tooltip("The Array Variable to use.")]
        public FsmArray array;

        [Tooltip("The index into the array.")]
        public FsmInt index;

        [RequiredField]
        [MatchElementType("array")]
        [UIHint(UIHint.Variable)]
        [Tooltip("Store the value in a variable.")]
        public FsmVar storeValue;

        [Tooltip("Repeat every frame while the state is active.")]
        public bool everyFrame;

        [ActionSection("Events")]

        [Tooltip("The event to trigger if the index is out of range")]
        public FsmEvent indexOutOfRange;

        public override void Reset()
        {
            array = null;
            index = null;
            everyFrame = false;
            storeValue = null;
            indexOutOfRange = null;
        }

        public override void OnEnter()
        {
            DoGetValue();

            if (!everyFrame)
            {
                Finish();
            }

        }

        public override void OnUpdate()
        {
            DoGetValue();

        }

        private void DoGetValue()
        {
            if (array.IsNone || storeValue.IsNone)
            {
                return;
            }

            if (index.Value >= 0 && index.Value < array.Length)
            {
                storeValue.SetValue(array.Get(index.Value));
            }
            else
            {
                Debug.LogError("Index out of Range: " + index.Value + " / GO Name :" + Fsm.OwnerName + " / FSM :" + Fsm.Name + " / State : " + Fsm.ActiveState, Fsm.Owner);
                Fsm.Event(indexOutOfRange);
            }
        }

        /* Not sure it's a good idea to range check at edit time since it can change at runtime
        public override string ErrorCheck()
        {
            if (index.Value<0 || index.Value >= array.Length)
            {
                return "Index out of Range. Please select an index between 0 and the number of items -1. First item is index 0.";
            }
            return "";
        }*/

#if UNITY_EDITOR
        public override string AutoName()
        {
            return ActionHelpers.GetValueLabel(storeValue.NamedVar) + "=" + array.Name + "[" + ActionHelpers.GetValueLabel(index) + "]";
        }
#endif
    }
}

if you want the log only happen in the editor, then add it in this way :

Code: [Select]
#if UNITY_EDITOR
                Debug.LogError("Index out of Range: " + index.Value + " / GO Name :" + Fsm.OwnerName + " / FSM :" + Fsm.Name + " / State : " + Fsm.ActiveState, Fsm.Owner);
#endif

when you select the error it gives, it should highlight in the hierarchy, but the name will also be printed in the error (in case the object gets removed)

If you want the editor Not to stop, rename the "Debug.LogError" to "Debug.LogWarning"

Thank you! :)

The action in question is ArrayListGet.cs and there is no such line there
Code: [Select]
Fsm.Event(indexOutOfRangeEvent);
so I get an error

Code: [Select]
Assets\PlayMaker ArrayMaker\Actions\ArrayList\ArrayListGet.cs(82,45): error CS0103: The name 'index' does not exist in the current context
« Last Edit: May 18, 2022, 01:50:08 PM by Aaddiction »

Aaddiction

  • Full Member
  • ***
  • Posts: 166
Re: Index was out of range on Array. Help finding the exact array.
« Reply #4 on: May 19, 2022, 07:34:32 AM »
Sorry to be bumping that. Any help would be greatly appreaciated.

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7616
    • jinxtergames
Re: Index was out of range on Array. Help finding the exact array.
« Reply #5 on: May 19, 2022, 09:18:15 AM »
Hi.
Try the code below :

Code: [Select]
// (c) Jean Fabre, 2011-2013 All rights reserved.
// http://www.fabrejean.net

// INSTRUCTIONS
// Drop a PlayMakerArrayList script onto a GameObject, and define a unique name for reference if several PlayMakerArrayList coexists on that GameObject.
// In this Action interface, link that GameObject in "arrayListObject" and input the reference name if defined.
// Note: You can directly reference that GameObject or store it in an Fsm variable or global Fsm variable

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{
[ActionCategory("ArrayMaker/ArrayList")]
[Tooltip("Gets an item from a PlayMaker ArrayList Proxy component")]
public class ArrayListGet : ArrayListActions
{
[ActionSection("Set up")]

[RequiredField]
[Tooltip("The gameObject with the PlayMaker ArrayList Proxy component")]
[CheckForComponent(typeof(PlayMakerArrayListProxy))]
public FsmOwnerDefault gameObject;

[Tooltip("Author defined Reference of the PlayMaker ArrayList Proxy component ( necessary if several component coexists on the same GameObject")]
public FsmString reference;

[UIHint(UIHint.FsmInt)]
[Tooltip("The index to retrieve the item from")]
public FsmInt atIndex;


[ActionSection("Result")]
[RequiredField]
[UIHint(UIHint.Variable)]
public FsmVar result;

[UIHint(UIHint.FsmEvent)]
[Tooltip("The event to trigger if the action fails ( likely and index is out of range exception)")]
public FsmEvent failureEvent;


public override void Reset()
{
atIndex = null;
gameObject = null;

failureEvent = null;

result = null;

}



public override void OnEnter()
{
if ( SetUpArrayListProxyPointer(Fsm.GetOwnerDefaultTarget(gameObject),reference.Value) )
GetItemAtIndex();

Finish();
}



public void GetItemAtIndex(){

if (! isProxyValid())
return;

if (result.IsNone)
{
Fsm.Event(failureEvent);
return;
}

object element = null;

try{
element = proxy.arrayList[atIndex.Value];
}catch(System.Exception e){
#if UNITY_EDITOR
                Debug.Log(e.Message);
Debug.Log("ARRAY LIST COULD NOT GET --> FSM Game Object : " + Fsm.OwnerName + " / FSM Name: " + Fsm.Name + " / FSM State: " + Fsm.ActiveStateName + " / Reference : " + reference.Value + " / Index  : " + atIndex.Value, Fsm.OwnerObject);
#endif
                Fsm.Event(failureEvent);
return;
}

PlayMakerUtils.ApplyValueToFsmVar(Fsm,result,element);
}
}
}

on line 83, inside the (System.Exception e)

i use the debug :

Code: [Select]
Debug.Log("ARRAY LIST COULD NOT GET --> FSM Game Object : " + Fsm.OwnerName + " / FSM Name: " + Fsm.Name + " / FSM State: " + Fsm.ActiveStateName + " / Reference : " + reference.Value + " / Index  : " + atIndex.Value, Fsm.OwnerObject);
inside the "try" it will try to get the data.
If it fails, it will trigger the "catch"

Aaddiction

  • Full Member
  • ***
  • Posts: 166
Re: Index was out of range on Array. Help finding the exact array.
« Reply #6 on: May 19, 2022, 09:45:27 AM »
Thank you!!! Works! I really need to bump up my code knowledge.

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7616
    • jinxtergames
Hi.
Looking and playing around with existing action scripts was the best way to learn C# for me.
I have to thank Playmaker to get where i am now.

@Fat Pug Studio
I agree, it saves a lot of time when you need to debug.