2

i'am completely new to Unity and C#. I try to use my OOP knowledge to build something that holding the data and "business logic" of my game.

Game outline: Some cubes falling down, can be moved while falling and finally dropping on an pane.

The cubes are prefab objects and must be tracked to count the score, detect un/wanted behaviour, etc.

In the scene is:

  • 1 empty GameObject = CubeSpanPoint + CubeSpawn Script
  • 1 empty GameObject = GameMain + GameMain script (holding game settings and business logic)
  • 1 prefab Cube + MoveScript + FallingScript

GameMain.cs

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

[System.Serializable]
public class GameMain : MonoBehaviour
{
    private float CubeSpawnSpeed = 3.0f;  //seconds
    private int score = 0;

    // construtor
    public GameMain()
    {
    }

    // getter: is falling allowed for the cube
    public bool getFalling(){
        return true;
    }

    // getter cube spawn speed
    public float getCubeSpawnSpeed(){
        return this.CubeSpawnSpeed;
    }
}

The FallingScript must get the data from MainGame (getters), FallingSpeed and the falling permission.

CubeFalling.cs

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

public class BoxFalling : MonoBehaviour
{
    public GameMain gameMain;

    void Start(){
        // an attempt to get the instance this way, but fail
        // GameMain main = GameObject.Find("GameMain").GetComponent<GameMain>();
    }

    void Update()
    {
        // Is still falling allowed?
        if (gameMain.getFalling()){
            transform.Translate(Vector3.down);
        }
    }
}

But this produces the error NullReferenceException: Object reference not set to an instance of an object BoxFalling.Update ()

It is also not possible to use the inspector by pulling the GameMain GameObject onto gameMain slot in the CubeFalling Script to the same named public variable.

What i've been expecting is that i've to pull the GameMain scipt to the GameMain GameObject, what is equal to an instantiation with new GameMain. And to reuse this instance, that i've to pull the GameObject to the GameMain Variable in the falling script. But this don't work.

row
  • 131
  • 2
  • 11
  • 1
    If you want GameMain be single and other script can use that directly , you can google this "singleton pattern c#" – TimChang Sep 03 '19 at 09:29
  • Possible duplicate of [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – BugFinder Sep 03 '19 at 10:06

2 Answers2

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

[System.Serializable]
public class GameMain : MonoBehaviour
{   private static GameMain _gameMain;
    public static GameMain Instance {get {return _gameMain;}}
    void Awake()
    {
        _gameMain = this;
    }

    // getter: is falling allowed for the cube
    public bool getFalling(){
        return true;
    }
}

BoxFalling.cs

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

public class BoxFalling : MonoBehaviour
{
    void Update()
    {
        // Is still falling allowed?
        // now you can got it
        if (GameMain.Instance.getFalling()){
            transform.Translate(Vector3.down);
        }
    }
}
TimChang
  • 2,249
  • 13
  • 25
  • Awesome. That helped me a lot! There's something I don't understand. Why doesn't GameMain need to be instantiated? Does this happen because the script is on the GameMain GameObject? – row Sep 04 '19 at 10:37
  • @row yes , `Monobehaivor` is depency on "GameObject" life cycle , So put it on a exist GameObject. And sure this GameObject is enabled. https://docs.unity3d.com/Manual/ExecutionOrder.html Or without Monobehaivor , just write a "singleton pattern" class. – TimChang Sep 05 '19 at 01:29
0

You could use a Singleton to access GameMain. This would be handy when in future you are instantiating more cubes at runtime.

But you also should be able to retrieve the GameMain using

gameMain = GameObject.Find("GameMain").getComponent<GameMain>();

Perhaps you misspelled something? Deactivated objects will not be found.

(Edit: This approach searches through all GameObjects in the hierarchy. At least cache the result. See more at Unity's documentation)

aalmigthy
  • 1,261
  • 8
  • 19