HelloMars
HelloMars

Reputation: 13

C# / new keyword / class member reference

So i have 2 classes (Sound class, AudioManager class)

I dont understand why we can access Sound's field without creating instance of Sound class. ()

Like what are the differences between

public Sound test1;

AND

Sound test2 = new Sound();

Its weird to me cause when i was learning c# tutorials / u could only access variables from another class only by creating instance of that class but in Unity u cas access it just by typing public Sound test1;

Sound Class

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

[System.Serializable]
public class Sound
{
    public AudioClip clip;
    public string name;
    public float volume;
    public float pitch;

    public AudioSource soundclass_source;
}

AudioManager class

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

public class AudioManager : MonoBehaviour
{
    public Sound test1;
    Sound test2 = new Sound();

    test1.name = "test1"; // without new
    test2.name = "test2"; // with new
}

Upvotes: 1

Views: 89

Answers (1)

derHugo
derHugo

Reputation: 90789

Since it is [Serializable] and the Unity Inspector of MonoBehaviour and ScriptableObject (etc) classes automatically initializes serialized fields with a default instance there is no difference between

public Sound test1;

and

public Sound test1 = new Sound();

(public fields are serialized by default if the type is serializable)

Also note that once you created an instance in Unity and the values are set via the Inspector those serialized values will always overrule the ones you hardcode here. If you later e.g. decide to pre-initliaze some values and change it to

public Sound test1 = new Sound() { name = "test1" };

it will have no effect since the value configured in the Inspector is taken instead. This coded value only is used for the very forst time the instance is created or if you hit Reset in the components context menu.

If you want later that the coded value is used instead you have to assign the new value in a method instead (see below).


No accesibility definition for a field (/class/method/property/etc) like public, protected or private in c# always means private.

If a field is private like in your case you have to initialize it "manually" otherwise the default value for classes is always null (== no instance reference).

You can do this like you did staticly in the class

private Sound test2 = new Sound();

this means the instance is already created as soon as an instance of your class is created or can do it laso later in a method like

private Sound test2;

private void Awake()
{
    Sound test2 = new Sound();
}

Finally you can/should make as private as possible for capsulation but can still make them serialized => displayed in the Inspector and stored using the [SerializeField] attribute:

[SerilaizeField] private Sound test2;

You can read more about Unity's serialization here

Upvotes: 6

Related Questions