0

我正在尝试在 Unity 中制作音频播放器。我首先创建了一个 ResourceManager,它有一个 AudioClip[]数组。

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];

    }
}

以便它们出现在Clips拖放框中。

在此处输入图像描述

但是,我想将 AudioClip 数组设为ResourceManager静态,以便其他脚本(例如PlayPause.cs可以clips静态访问(通过函数调用))。但问题是一旦我设为clips静态,拖放就消失了。

有没有办法解决这个问题?还是有更好的设计模式?谢谢。

4

1 回答 1

1

你可以例如简单地做

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;

        ...
    }
}

建议的替代方法是制作ResourceManager一个所谓的单例,例如

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];
    }
}

然后到处访问ReaourcesManager.Instance.Clips


或者使用单例的内置替代方案,FindObjectOfType因此场景中的任何其他脚本实际上都可以简单地访问

FindObjectOfType<ResourcesManager>().clips

无需您进行任何更改;)

除了说我会成功

[SerializeField] private AudioClip[] clips;

public IReadonlyList<AudioClip> Clips => clips;

当然,这取决于您想对剪辑做什么,但是这样数组就不能被任何其他脚本更改

于 2021-03-30T19:55:10.047 回答