Index Out Of Range Exception

Just finished this lecture and getting this error now.


Looking at the code. I have this in the PlayerCOntroller.cs script

using RPG.Attributes;
using RPG.Combat;
using RPG.Movement;
using UnityEngine;

namespace RPG.Control
{
    public class PlayerController : MonoBehaviour
    {
        Health health;

        enum CursorType
        {
            None,
            Movement,
            Combat
        }

        [System.Serializable]
        struct CursorMapping
        {
            public CursorType type;
            public Texture2D texture;
            public Vector2 hotspot;
        }

        [SerializeField] CursorMapping[] cursorMappings = null;

        private void Awake()
        {
            health = GetComponent<Health>();
        }

        private void Update()
{
            if (health.IsDead()) return;

            if (InteractWithCombat()) return;
            if (InteractWithMovement()) return;

            SetCursor(CursorType.None);
        }

        private bool InteractWithCombat()
        {
            RaycastHit[] hits = Physics.RaycastAll(GetMouseRay());
            foreach (RaycastHit hit in hits)
            {
                CombatTarget target = hit.transform.GetComponent<CombatTarget>();
                if (target == null) continue;

                if (!GetComponent<Fighter>().CanAttack(target.gameObject))
                {
                    continue;
                }

                if (Input.GetMouseButton(0))
                {
                    GetComponent<Fighter>().Attack(target.gameObject);
                }
                SetCursor(CursorType.Combat);
                return true;
            }
            return false;
        }

        private bool InteractWithMovement()
        {
            RaycastHit hit;
            bool hasHit = Physics.Raycast(GetMouseRay(), out hit);
            if (hasHit)
            {
                if (Input.GetMouseButton(0))
                {
                    GetComponent<Mover>().StartMoveAction(hit.point, 1f);
                }
                SetCursor(CursorType.Movement);
                return true;
            }
            return false;
        }

        private void SetCursor(CursorType type)
        {
            CursorMapping mapping = GetCursorMapping(type);
            Cursor.SetCursor(mapping.texture, mapping.hotspot, CursorMode.Auto);
        }

        private CursorMapping GetCursorMapping(CursorType type)
        {
            foreach (CursorMapping mapping in cursorMappings)
            {
                if (mapping.type == type)
                {
                    return mapping;
                }
            }
            return cursorMappings[0];
        }

        private static Ray GetMouseRay()
        {
            return Camera.main.ScreenPointToRay(Input.mousePosition);
        }
    }
}

It says the error is coming from this line at the end of this section
return cursorMapping[0];

        private CursorMapping GetCursorMapping(CursorType type)
        {
            foreach (CursorMapping mapping in cursorMappings)
            {
                if (mapping.type == type)
                {
                    return mapping;
                }
            }
            return cursorMappings[0];
        }

I looked at help for this, but we didn’t assign a “int” for this, so I’m at a bit of a loss. :grey_question:
Anyone have any ideas what went wrong here?
Thank you so much for the help. :slight_smile:

Have you assigned the cursormappings in the PlayerController’s inspector?

Yup. :smiley:

Check to make sure that there are no other PlayerController scripts in your game… cursorMappings[0] cannot be out of range on the one you screenshotted, unless something is erasing the cursorMappings after the game is started.

Thank you so much Brian for your help and guidance. You have really been a huge asset to me on my journey to learn Unity. I have some good news, and I have some bad news.
The good news is… I think I figured out the problem. I went back into the inspector on the player prefab and saw in the overrides tab there was a whole list of uncommitted changes.
The bad news is… committing all the changes on the player prefab crashed my project into a unrecoverable state.

I was able to restore a backup, but it still has a bunch of uncommitted changes on the player prefab, which when I commit; doesn’t crash my game; but gives me 999+ errors immediately upon starting the game. I’m going to work through the course again from the beginning I think, to try and resolve the issues. I didn’t realize (or remember) that just because I save the code (test the code?) and run the game with no errors doesn’t mean everything is fine. A tough break on the learning front, but I will write this down as a thing to remember after every day doing some lectures. *Make sure you commit all your changes before testing the game.

I do have one more question before I restart everything. I’m seeing this as a potential big problem. When I commit the changes on the player prefab it wants to override the main character prefab. And when I went and looked at the enemy prefab it wants to do the same thing. I don’t think this is very good. What one should get priority, or what do you do in this situation? The main issue is the last one on the list. Character_Knights_Soldier_01 & 02. If you commit the player all the enemies change to the player model, and if you do the enemy the player model changes.

There should be options to choose how far up the ladder you want to apply changes.
For example:

Apply to Prefab Player
Apply to Prefab Character

You always have to be mindful of how far up the chain you want the changes to be applied, because applying to the Character will also apply the change to all other children of Charcter. I wish that applying to something two levels up the chain would automagically prop up a warning saying “This change will affect Character and the following prefabs that are descended from Character: Enemy” or something like that and make you confirm.

Hey @Brian_Trotter
I’ve been thinking about this all morning and I don’t think I fully understand how the overrides work. I’m trying to think of all my questions in one comment here.

  • The overrides are only available to a prefab variant? (by the looks of it I’m seeing in the Inspector)
  • If you apply a change you made in a prefab variant it only pushes it up one level? Is there a way to push the change all the way to the top?
  • You don’t want to apply (I said commit in my previous message), but you don’t want to apply anything that is too specific up the chain? We created a fire arrow and then made a prefab variant of it and changed it to an ice arrow. And I don’t think we should have done that? We should have made a normal arrow (standard) and then made two prefab variants of that original unaltered arrow and made one fire and one ice? Because they each need to have there specific effect, but the main arrow could of had the effect field added, but just remained blank?
  • You don’t “have” to apply any of the overrides in the Prefab variant if you don’t want to? It only helps if you want to make another prefab variant of the parent so then you don’t have to add all of the same components again?
  • And conversely you don’t need to change all the prefab variants if you make a change to the parent prefab it will push down the change to all the prefab variants of it? Or does your change only go one level down as well?

My previous message made it sound like I was sad. lol. I was sad, but I thought going through it again would have just reinforced the concepts and practices of the course material. And I’m still new and learning this so again… (shrugs shoulders). But I guess I don’t have to start from scratch if point #4 is true? You don’t “have” to apply any of the overrides if you don’t want to? I’ll wait to hear from you about all this, as it will mean either start from square one, or resume from where I had my backup.

Thank you again Brian. Have a great and wonderful day! :rainbow: :rainbow: :star:

Correct, there’s often no need to apply anything back to the parent prefab. Most often, it’s because you realized there was some feature that you added that you think would look really cool on the original prefab as well.

You can also apply changes you’ve made in a scene instance to the prefab just like if you were editing a prefab variant. Same cautions apply, you can mess things up pretty easily.

If there are more levels up the chain, you’ll see options in the context menu like “Apply to Player | Apply to Character”…

Changes you make to the top level prefab cascade all the way down the chain. The catch is that anything that is already serialized won’t get overwritten.

Super Awesome. Thank you so much again Brian. :sunglasses: :+1:

Hey there Brian. I’m back at this point after recovering my project, but I’m still having the same issue.

detail or error

Code on line 99

            return cursorMappings[0];

Code on line 86

            CursorMapping mapping = GetCursorMapping(type);

Code on line 42

            SetCursor(CursorType.None);

Complete code is here again for reference.

using RPG.Attributes;
using RPG.Combat;
using RPG.Movement;
using UnityEngine;

namespace RPG.Control
{
    public class PlayerController : MonoBehaviour
    {
        Health health;

        enum CursorType
        {
            None,
            Movement,
            Combat
        }

        [System.Serializable]
        struct CursorMapping
        {
            public CursorType type;
            public Texture2D texture;
            public Vector2 hotspot;
        }

        [SerializeField] CursorMapping[] cursorMappings = null;

        private void Awake()
        {
            health = GetComponent<Health>();
        }

        private void Update()
{
            if (health.IsDead()) return;

            if (InteractWithCombat()) return;
            if (InteractWithMovement()) return;

            SetCursor(CursorType.None);
        }

        private bool InteractWithCombat()
        {
            RaycastHit[] hits = Physics.RaycastAll(GetMouseRay());
            foreach (RaycastHit hit in hits)
            {
                CombatTarget target = hit.transform.GetComponent<CombatTarget>();
                if (target == null) continue;

                if (!GetComponent<Fighter>().CanAttack(target.gameObject))
                {
                    continue;
                }

                if (Input.GetMouseButton(0))
                {
                    GetComponent<Fighter>().Attack(target.gameObject);
                }
                SetCursor(CursorType.Combat);
                return true;
            }
            return false;
        }

        private bool InteractWithMovement()
        {
            RaycastHit hit;
            bool hasHit = Physics.Raycast(GetMouseRay(), out hit);
            if (hasHit)
            {
                if (Input.GetMouseButton(0))
                {
                    GetComponent<Mover>().StartMoveAction(hit.point, 1f);
                }
                SetCursor(CursorType.Movement);
                return true;
            }
            return false;
        }

        private void SetCursor(CursorType type)
        {
            CursorMapping mapping = GetCursorMapping(type);
            Cursor.SetCursor(mapping.texture, mapping.hotspot, CursorMode.Auto);
        }

        private CursorMapping GetCursorMapping(CursorType type)
        {
            foreach (CursorMapping mapping in cursorMappings)
            {
                if (mapping.type == type)
                {
                    return mapping;
                }
            }
            return cursorMappings[0];
        }

        private static Ray GetMouseRay()
        {
            return Camera.main.ScreenPointToRay(Input.mousePosition);
        }
    }
}

I’m not getting any errors in the code, but after starting the game I get the Index Out Of Range error in the console, and it just ticks up to 999+ within a few seconds.

  • I have only the one instance of the player controller script on the player prefab with the cursors assigned as well.

Does this get fixed a few lessons ahead in the “Raycasting to a Navmesh” fix? Looked like a person was having a issue with the cursor not changing. Mine cursor seems to work fine, it changes right away, and I don’t get any flickering. Just the errors in the console. I don’t know if these issues are related.

Thanks again for you help. :slight_smile:

Is there any chance you have a PlayerController on another GameObject somewhere in the scene?
Toss this into Update()

Debug.Log($"{gameObject.name} PlayerController Update()");

@Brian_Trotter you are a genius my friend. The player controller was on all my enemies in the scene. And after deleting it off of their prefab and then running the game again no more errors.

AND… this also fixed the enemies running towards the player when I clicked to move. I’m sure for the exact same reason. I had a post about that here.

I’m going to update that post as well as a possible fix. Check your enemies in the scene for the player controller.

Thank you again Brian. :rainbow: :star: :+1:

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms