Error to pass variable value through classes on Roguelike Tutorial

Well, I’m doing the Roguelike2D tutorial and I’ve found an error on the parameters of the character’s food points. Here is the code:

protected override void Start ()
{
animator = GetComponent ();
food = GameManager.instance.playerFoodPoints;
base.Start ();
}

And the GameManager code for the playerFoodPoints variable:

public int playerFoodPoints = 100;

So, the problem is, when I start game, the food variable should get the playerFoodPoints value from another class (the first code is from the Player class and the second from GameManager class), but it didn’t. When I walk for the first time, the game tests if food is less than or equal to 0, if true, it calls the GameOver function.
I haven’t found why the value isn’t passing to food. Anyone can help me, please?

Are you getting a null ref? How is the static instance of GameManager defined out of curiosity?

1 Like

public static GameManager instance = null;
public BoardManager boardScript;
public int playerFoodPoints = 100;

And I have this on the Awake function:

if (instance == null)
instance = this;
else if (instance != this)
Destroy(gameObject);
DontDestroyOnLoad(gameObject);
enemies = new List();
boardScript = GetComponent();
InitGame();

Can you post the class your character is inheriting from! With code tags for bonus style points

1 Like

Are you getting an error? What is happening? food should get the value from the gamemanager once in Start, so the value should be 100, but I’m not sure what else you are doing with that value since you didn’t mention what was going wrong or if you get an error.

1 Like

Here it goes, sorry, I didn’t know how to use code tags before.

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

public abstract class MovingObject : MonoBehaviour {

    public float moveTime = .1f;
    public LayerMask blockingLayer;

    private BoxCollider2D boxCollider;
    private Rigidbody2D rb2D;
    private float inverseMoveTime;

    // Use this for initialization
    protected virtual void Start ()
    {
        boxCollider = GetComponent<BoxCollider2D> ();
        rb2D = GetComponent<Rigidbody2D> ();
        inverseMoveTime = 1f / moveTime;
    }

    protected bool Move (int xDir, int yDir, out RaycastHit2D hit)
    {
        Vector2 start = transform.position;
        Vector2 end = start + new Vector2 (xDir, yDir);

        boxCollider.enabled = false;
        hit = Physics2D.Linecast (start, end, blockingLayer);
        boxCollider.enabled = true;

        if (hit.transform == null)
        {
            StartCoroutine (SmoothMovement (end));
            return true;
        }

        return false;
    }

    protected IEnumerator SmoothMovement (Vector3 end)
    {
        float sqrRemainingDistance = (transform.position - end).sqrMagnitude;

        while (sqrRemainingDistance > float.Epsilon)
        {
            Vector3 newPosition = Vector3.MoveTowards (rb2D.position, end, inverseMoveTime * Time.deltaTime);
            rb2D.MovePosition (newPosition);
            sqrRemainingDistance = (transform.position - end).sqrMagnitude;
            yield return null;
        }
    }

    protected virtual void AttemptMove <T> (int xDir, int yDir)
        where T : Component
    {
        RaycastHit2D hit;
        bool canMove = Move(xDir, yDir, out hit);

        if (hit.transform == null)
            return;

        T hitComponent = hit.transform.GetComponent<T> ();

        if (!canMove && hitComponent != null)
            OnCantMove (hitComponent);
    }

    protected abstract void OnCantMove <T> (T component)
        where T : Component;
}

Nops, the value 100 don’t pass, when I hit Play Game, food just stays as 0.

Here is the Player code:

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

public class Player : MovingObject {

    public int wallDamage = 1;
    public int pointsPerFood = 10;
    public int pointsPerSoda = 20;
    public float restartLevelDelay = 1f;

    private Animator animator;
    private int food;                // PRIVATE

    // Use this for initialization
    protected override void Start ()
    {
        animator = GetComponent<Animator> ();

        food = GameManager.instance.playerFoodPoints;

        base.Start ();
    }
       
    private void OnDisable()
    {
        GameManager.instance.playerFoodPoints = food;
    }

    // Update is called once per frame
    void Update ()
    {
        if (!GameManager.instance.playersTurn)
            return;

        int horizontal = 0;
        int vertical = 0;

        horizontal = (int)Input.GetAxisRaw ("Horizontal");
        vertical = (int)Input.GetAxisRaw ("Vertical");

        if (horizontal != 0)
            vertical = 0;

        if (horizontal != 0 || vertical != 0)
            AttemptMove<Wall> (horizontal, vertical);
    }

    protected override void AttemptMove <T> (int xDir, int yDir)
    {
        food--;

        base.AttemptMove <T> (xDir, yDir);

        RaycastHit2D hit;

        CheckIfGameOver ();

        GameManager.instance.playersTurn = false;
    }

    protected void OnTriggerEnter2D (Collider2D other)
    {
        if (other.tag == "Exit") {
            Invoke ("Restart", restartLevelDelay);
            enabled = false;
        } else if (other.tag == "Food") {
            food += pointsPerFood;
            other.gameObject.SetActive (false);
        } else if (other.tag == "Soda") {
            food += pointsPerSoda;
            other.gameObject.SetActive (false);
        }
    }

    protected override void OnCantMove <T> (T component)
    {
        Wall hitWall = component as Wall;
        hitWall.DamageWall (wallDamage);
        animator.SetTrigger ("playerChop");
    }

    private void Restart()
    {
        SceneManager.LoadScene (0);
        //Application.LoadLevel(Application.loadedLevel);
    }

    public void LoseFood (int loss)
    {
        animator.SetTrigger ("playerHit");
        food -= loss;
        CheckIfGameOver ();
    }

    private void CheckIfGameOver() {
        if (food <= 0)
            GameManager.instance.GameOver ();
    }
}

And the GameManager code:

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

public class GameManager : MonoBehaviour {

    public float turnDelay = .1f;
    public static GameManager instance = null;
    public BoardManager boardScript;
    public int playerFoodPoints = 100;
    [HideInInspector] public bool playersTurn = true;

    private int level = 3;
    private List<Enemy> enemies;
    private bool enemiesMoving;

    private void Awake()
    {
        if (instance == null)
            instance = this;
        else if (instance != this)
            Destroy(gameObject);

        DontDestroyOnLoad(gameObject);
        enemies = new List<Enemy>();
        boardScript = GetComponent<BoardManager>();
        InitGame();
      //  SceneManager.sceneLoaded += OnSceneLoaded; //------------------------- QUANDO LINHA ATIVA, NÃO SALVA O PERSONAGEM PARA A PROXIMA FASE.
                                                    // ----------------------- QUANDO LINHA INATIVA, NÃO CARREGA O MAPA NA PROXIMA FASE.
        SceneManager.LoadScene(0);
    }

    /*                                                                        // Não Funfa
    static private void OnSceneLoaded(Scene arg0, LoadSceneMode arg1)
    {
        instance.level++;
        instance.InitGame();
    }
    */



    void OnLevelWasLoaded(int index)
    {
        instance.level++;
        instance.InitGame ();
    }



    void InitGame()
    {
        enemies.Clear ();
        boardScript.SetupScene (level);
    }

    public void GameOver()
    {
        enabled = false;
        Debug.Log("Game Over");
    }
   
    // Update is called once per frame
    void Update () {
        if (playersTurn || enemiesMoving)
            return;

        StartCoroutine (MoveEnemies ());
    }

    public void AddEnemyToList(Enemy script)
    {
        enemies.Add (script);
    }

    IEnumerator MoveEnemies()
    {
        enemiesMoving = true;
        yield return new WaitForSeconds (turnDelay);
        if (enemies.Count == 0) {
            yield return new WaitForSeconds (turnDelay);
        }

        for (int i = 0; i < enemies.Count; i++) {
            enemies [i].MoveEnemy ();
            yield return new WaitForSeconds (enemies [i].moveTime);
        }

        playersTurn = true;
        enemiesMoving = false;
    }
}

Like @Brathnann suggested, if you get any error messages, help us help you by sharing them.

If you don’t, it can be many things! The value you set in the inspector will have priority over the one declared in your class. Make sure that you haven’t changed the “playerFoodPoints” value in the inspector.

If you haven’t, possibly you could put a Debug.Log (food); right after your “food=GameManager.Instance.playerFoodPoints;” line, in your player code, to make sure that this is indeed where the code is breaking.

1 Like

Both “playerFoodPoints” and “food” are private, I can’t change it from inspector.

I put a Debug.Log(food) right after the execution of that line and it returned 0, the value isn’t passing.

It didn’t returned any error message, the game just started normally, but food stayed with 0.

Just asking to make sure, but are you certain playerFoodPoints is private? Because in the script you posted, playerFoodPoints it is public.

Edit : Add Debug.Log (playerFoodPoints); in the awake of your game controller class and see what that returns

1 Like

Sorry, it’s public, but I have a function calling GameManager, so I don’t have any way to change it on the inspector, I guess.

How about debug.log’ing the playerFoodPoints in your game controller’s awake?

1 Like

Your GameManager script isn’t in your scene? That wouldn’t be possible as Awake couldn’t run unless it is in your scene somewhere. Which means you need to see where it is.

1 Like

The GameManager must be in the scene somewhere, otherwise you’d be getting a null ref error. Check all the objects in your scene and find the one that has the GameManager attached to it, and make sure the playerFoodPoints is set to 100 there.

1 Like

On my scene, in the Main Camera, has a script called Loader, it’s triggered when the game starts and call the function BoardManager to procedurally create the map and the GameManager function.

And just to verify, once this script is added, what value is the playerFoodPoints showing in the inspector? You can still get access to it after it’s added in play mode.

1 Like

Hey everyone, thank you for the help, I’ve found the problem. I have a line on Player code with a function called OnDisable, and as I looked for, that function doesn’t work properly on the unity new version. I changed for a new fuction I don’t record the name cause I’m working now, but anyway, thanks everybody, I’ll post the solution here.