Getting a minor error despite following the course exactly

Getting this error:

NullReferenceException: Object reference not set to an instance of an object
RPG.Stats.Progression.GetLevels (RPG.Stats.Stat stat, RPG.Stats.CharacterClass characterClass) (at Assets/Scripts/Stats/Progression.cs:30)
RPG.Stats.BaseStats.GetLevel () (at Assets/Scripts/Stats/BaseStats.cs:31)
RPG.Stats.BaseStats.GetStat (RPG.Stats.Stat stat) (at Assets/Scripts/Stats/BaseStats.cs:22)
RPG.Attributes.Health.Start () (at Assets/Scripts/Attributes/Health.cs:17)

Not sure what the cause is. It’s happening on the Player gameObject, but if I make another scene with no enemies, more errors pop up. I think it has something to do with the progression dictionary not fully loading up by the time Awake() is called on the Player’s Health script.

First things first, we’ll need to see where the null reference is occuring.
Let’s start with your Progression.cs class, as that’s where the null reference is… Be sure to mark line 30 with a comment and we can go from there.

Here is my Progression.cs script. I’m also using Unity 2020.3.30f1 if that helps.

using UnityEngine;
using System.Collections.Generic;
using System;

namespace RPG.Stats
{
    [CreateAssetMenu(fileName = "Progression", menuName = "Stats/New Progression", order = 0)]
    public class Progression : ScriptableObject
    {
        [SerializeField] ProgressionCharacterClass[] characterClasses = null;

        Dictionary<CharacterClass, Dictionary<Stat, float[]>> lookUpTable = null;

        public float GetStat(Stat stat, CharacterClass characterClass, int level)
        {
            BuildLookUp();

            float[] levels = lookUpTable[characterClass][stat];

            if (levels.Length < level)
            {
                return 0;
            }

            return levels[level - 1];
        }

        public int GetLevels(Stat stat, CharacterClass characterClass)
        {
            // This is where the issue happens. 
            float[] levels = lookUpTable[characterClass][stat];
            return levels.Length;
        }

        private void BuildLookUp()
        {
            if (lookUpTable != null) return;
            Debug.Log("Building Lookup");

            lookUpTable = new Dictionary<CharacterClass, Dictionary<Stat, float[]>>();

            foreach (ProgressionCharacterClass progressionClass in characterClasses)
            {
                var statLookUpTable = new Dictionary<Stat, float[]>();

                foreach (ProgressionStat progressionStat in progressionClass.stats)
                {
                    statLookUpTable[progressionStat.stat] = progressionStat.levels;
                }

                lookUpTable[progressionClass.characterClass] = statLookUpTable;
            }
        }

        [System.Serializable]
        class ProgressionCharacterClass
        {
            public CharacterClass characterClass;
            public ProgressionStat[] stats;
        }

        [System.Serializable]
        class ProgressionStat
        {
            public Stat stat;
            public float[] levels;
        }
    }
}

Ok, so it looks like BaseStats.GetLevel() is calling Progression.GetLevels(), but the lookup has not been initialized. As it’s a public method entry into Progression, it should also have a BuildLookup(); call in it to guarantee that the lookup has been created when it’s called.

        public int GetLevels(Stat stat, CharacterClass characterClass)
        {
            BuildLookup(); //Add this line
            float[] levels = lookUpTable[characterClass][stat];
            return levels.Length;
        }
1 Like

That turned out to be the problem. It works just fine now. Thanks for the help!

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

Privacy & Terms