-2

I am creating a version of the Tower of Hanoi puzzle. The way it is represented in the Unity hierarchy is

-Game Objects
-----PegA
---------Arm
---------Base

Sorry I didn't know how to represent the hierarchy.

There are 3 "pegs" and have 7 "rings" as objects in the scene. The pegs and rings are on the same level in the hierarchy.

It is obvious that I can "SerializeField" the ring class and just click and drag each Peg onto them in the inspector but what I want to do is just add them at runtime in the code. This is what I tried.

This is part of my ring class

public class ring : MonoBehaviour
{
    public bool locked, resting;
    private float startX, startY, deltaX, deltaY;
    private Vector3 mousePos, beforeDrag;

    private List<GameObject> pegs;

    // Start is called before the first frame update
    void Start()
    {
        startX = transform.position.x;
        startY = transform.position.y;
        locked = false;
        pegs.Add(GameObject.Find("PegA"));
        pegs.Add(GameObject.Find("PegB"));
        pegs.Add(GameObject.Find("PegC"));
    }
}

The error I'm getting is "Object reference not set to an instance of an object"

Can someone possibly explain?

MaxAttax
  • 67
  • 6
  • 5
    Does `private List pegs = new List();` fix it? – Sweeper Sep 05 '19 at 18:56
  • 1
    1. `pegs` is not an `Array`, it is a `List` 2. you need to assign a `new List` to `pegs`, as it is otherwise `null` when the class is constructed. – crashmstr Sep 05 '19 at 18:57
  • As @Sweeper said, you List is private, therefore it will not be serialized and you have to call new on it. – AresCaelum Sep 05 '19 at 18:57
  • @MaxAttax Unity will properly initialize public serializeable variables in MonoBehaviours. Any variable that is not public defined needs to be initialized properly, so your `List` is private and not initialized, you will need to call new on it before you attempt to use it. – AresCaelum Sep 05 '19 at 19:02
  • @Eddge is this the case with all non-native types/ – MaxAttax Sep 05 '19 at 19:04
  • @Eddge such as any class I create or classes created by Unity? – MaxAttax Sep 05 '19 at 19:05
  • @MaxAttax any classes that are not directly created by Unity, yes. – AresCaelum Sep 05 '19 at 19:06
  • @MaxAttax This is the case with every reference type variable allocated on the heap. Reference variables hold a memory address to an object on the heap, in this case you have no memory address because you have made no allocation. – ColinM Sep 05 '19 at 19:06
  • @ColinM so any class I create in C# is a reference type that must be instantiated with the new keyword/ – MaxAttax Sep 05 '19 at 19:09
  • Classes are reference types, structs are value types. `private List pegs;` = declaration, `pegs = new List()` = initialization, and subsequently allocation. – ColinM Sep 05 '19 at 19:10
  • Can you guys like remember to upvote and downvote. I'm teaching myself Unity and C# and you get penalized if it stays at zero I think. – MaxAttax Sep 05 '19 at 19:20

1 Answers1

6
public class ring : MonoBehaviour
{
    //These are value types they have a default value
    public bool locked, resting;// bool default value is false
    private float startX, startY, deltaX, deltaY; // float is zero
    private Vector3 mousePos, beforeDrag;// Vector3 is Vector3.zero
    // This does not have a "default" value cos this is a reference type
    private List<GameObject> pegs = new List<GameObject>();

    // Start is called before the first frame update
    void Start()
    {
        startX = transform.position.x;
        startY = transform.position.y;
        locked = false;
        pegs.Add(GameObject.Find("PegA"));
        pegs.Add(GameObject.Find("PegB"));
        pegs.Add(GameObject.Find("PegC"));
    }
}

Conclusion you should initialize your own classes, and classes in general with the new keyword. Unless these are classes that are inherited from MonoBehaviour, these classes should be initialized using the AddComponent method. If you do not do these Unity will not manage the memory for these classes and it will give you an error telling you to use AddComponent.

AresCaelum
  • 1,558
  • 1
  • 13
  • 18
CodeSorcerer
  • 179
  • 9
  • Can you tell me what the keyword "pegs" returns? – MaxAttax Sep 05 '19 at 19:03
  • 3
    @MaxAttax this is literally your same script, just with comments and pegs properly setup... – AresCaelum Sep 05 '19 at 19:04
  • 2
    @MaxAttax pegs is not a keyword "pegs" is your List collection name – CodeSorcerer Sep 05 '19 at 19:06
  • 1
    I would reword your sentence just a bit, classes created as monobehaviour should be initialized using AddComponent instead of new. – AresCaelum Sep 05 '19 at 19:06
  • I'm sorry I'm basically trying to figure out if the variable "pegs" is a reference and if so if thats the case when I declare a variable of any non-native type – MaxAttax Sep 05 '19 at 19:07
  • 1
    @Eddge You are totaly right, feel free to edit my answer :) – CodeSorcerer Sep 05 '19 at 19:07
  • @MaxAttax `pegs` is a reference because the type of `pegs` is `List` and `List` is a reference type. – Ruzihm Sep 05 '19 at 19:08
  • @MaxAttax the variable pegs is a reference because List is a reference type, classes in c# are reference types, structs are value types. – CodeSorcerer Sep 05 '19 at 19:09
  • @MaxAttax Check these: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/value-types, https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/reference-types – CodeSorcerer Sep 05 '19 at 19:10
  • @MaxAttax See [this question](https://stackoverflow.com/questions/5057267/what-is-the-difference-between-a-reference-type-and-value-type-in-c) for more information – Ruzihm Sep 05 '19 at 19:10
  • 1
    @Ruzihm thank you these are the answers i was looking for. I know C++ decently well and I was confused because you dont have to use new everytime you instantiate a class in C++ – MaxAttax Sep 05 '19 at 19:11
  • 1
    @MaxAttax Just to kind of join the dots, RAII (What you describe of C++) instantiates on the stack, similar to value types in .NET. – ColinM Sep 05 '19 at 19:20
  • 1
    @ColinM That does connect some dots. Thank you. – MaxAttax Sep 05 '19 at 19:23