I'm trying to make an audio player in Unity.
I first created a ResourceManager, that has a
AudioClip[] array.
public class ResourceManager : MonoBehaviour
{
public AudioSource audioSrc;
public AudioClip[] clips;
private int trackNum = 0;
public void Awake()
{
audioSrc = GetComponent<AudioSource>();
audioSrc.Stop();
...omitted...
public void LoadClip()
{
audioSrc.clip = clips[trackNum];
}
}
So that they appear in the Clips drag-and-drop box.
However, I want to make the AudioClip array static in ResourceManager static, so other scripts (e.g. PlayPause.cs can access clips statically (via function calls).
But the problem is once I make clips static, the drag-and-drop for disappears.
Is there a way to fix that? Or are there some better design patterns? Thanks.
You can e.g. simply do
public class ResourceManager : MonoBehaviour
{
...
// This is the one in the Inspector
// Usually I keep the Inspector private and only provide public access
// where needed via properties
[SerializeField] private AudioClip[] clips;
// This will be set in Awake to the ones from the Inspector
// readonly for others, only this class can assign it
public static AudioClip[] Clips { get; private set; }
public void Awake()
{
Clips = clips;
...
}
}
The alternative suggested is make the ResourceManager a so called singleton like e.g.
public class ResourceManager : MonoBehaviour
{
// Here you store your own instance reference
// and provide public readonly access
public static ResourceManager Instance { get; private set; }
[SerializeField] private AudioClip[] clips;
public AudioClip[] Clips => clips;
...
public void Awake()
{
// Make sure only one instance exists at a time
if(Instance && Instance != this)
{
Destroy(gameObject);
return;
}
_instance = this;
// optional: Don't destroy this instance when the scene is switched
// Careful: Make sure this applies also to the AudioSource instance!
// For now I assume it is either attached to this object or a child
// if not simply do the same DontDestroyOnLoad on it as well
DontDestroyOnLoad (this.gameObject);
...
}
public void LoadClip()
{
audioSrc.clip = clips[trackNum];
}
}
And then access everywhere ReaourcesManager.Instance.Clips
Or a built-in alternative to the singleton is using FindObjectOfType so any other script in the Scene can actually simply access
FindObjectOfType<ResourcesManager>().clips
without you having to change anything at all ;)
Except as said I would make it
[SerializeField] private AudioClip[] clips;
public IReadonlyList<AudioClip> Clips => clips;
depending a bit of course what exactly you want to do with the clips but this way the array can not be altered by any other script