访问非静态成员需要对象引用

本文关键字:对象引用 静态成员 访问 | 更新日期: 2023-09-27 18:03:35

我有这个错误出现,我不知道为什么…我试着查了一下,人们说创建一个类的对象或创建静态方法…但我不确定如何。

下面是我的代码:

public class SoundManager : MonoBehaviour {
public List<AudioSource> audioSounds = new List<AudioSource>();
public double minTime = 0.5;
public static void playSound(AudioClip sourceSound, Vector3 objectPosition, int volume, float audioPitch, int dopplerLevel)
{
    bool playsound = false;
    foreach (AudioSource sound in audioSounds) // Loop through List with foreach
    {
        if (sourceSound.name != sound.name && sound.time <= minTime)
        {
            playsound = true;
        }
    }
    if(playsound) {
        AudioSource.PlayClipAtPoint(sourceSound, objectPosition);
    }
}
}

访问非静态成员需要对象引用

你应该设置audioSounds和minTime成员为static:

public static List<AudioSource> audioSounds = new List<AudioSource>();
public static double minTime = 0.5;

但是我会考虑使用单例对象而不是静态成员:

public class SoundManager : MonoBehaviour
{
    public List<AudioSource> audioSounds = new List<AudioSource>();
    public double minTime = 0.5;
    public static SoundManager Instance { get; private set; }
    void Awake()
    {
        Instance = this;
    }
    public void playSound(AudioClip sourceSound, Vector3 objectPosition, int volume, float audioPitch, int dopplerLevel)
    {    
        bool playsound = false;
        foreach (AudioSource sound in audioSounds) // Loop through List with foreach
        {  
            if (sourceSound.name != sound.name && sound.time <= minTime)
            {
                playsound = true;
            }
        }
        if(playsound) {
            AudioSource.PlayClipAtPoint(sourceSound, objectPosition);
        }
    }
}

2020年9月更新:

六年后,它仍然是我在StackOverflow上最受欢迎的答案之一,所以我觉得有义务补充:单例是一种模式,它在未来会产生很多问题,我个人认为它是一种反模式。它可以从任何地方访问,并且在不同的游戏系统中使用singleton会在项目的不同部分之间创建无形的依赖关系。

如果你刚刚学习编程,现在使用单例是可以的。但是,请考虑阅读依赖注入、控制反转和其他架构模式。至少把它归类为"我以后要学的东西"。当您第一次了解它们时,这可能听起来有点小题大做,但是适当的体系结构可以成为中型和大型项目的救星。

我猜你在访问audioSoundsminTime时遇到了错误,对吧?

问题是你不能从static methods访问instance members。这意味着,静态方法是一种只存在一次的方法,可以被所有其他对象使用(如果它的访问修饰符允许的话)。

另一方面,

实例成员是为对象的每个实例创建的。因此,如果您创建了十个实例,运行时如何知道在所有这些实例中,应该访问哪个audioSounds列表?

就像其他人说的,让你的audioSoundsminTime是静态的,或者你可以让你的方法是一个实例方法,如果你的设计允许的话。

playSound是一个静态方法,意味着它在程序加载时存在。audioSounds和minTime是SoundManager实例变量,这意味着它们将存在于SoundManager的一个实例中。你没有创建一个SoundManager的实例,所以audioSounds不存在(或者它存在,但你没有一个SoundManager对象的引用来查看)。

要解决这个问题,你可以将audioSounds设置为静态:

public static List<AudioSource> audioSounds = new List<AudioSource>();
public static double minTime = 0.5;

,所以它们将被创建,并可能以与PlaySound相同的方式被引用。或者你可以在你的方法中创建一个SoundManager的实例:

SoundManager soundManager = new SoundManager();
foreach (AudioSource sound in soundManager.audioSounds) // Loop through List with foreach
{
    if (sourceSound.name != sound.name && sound.time <= soundManager.minTime)
    {
        playsound = true;
    }
}

playSound是您的类中的静态方法,但您指的是audioSoundsminTime等成员,未声明为static,因此它们需要SoundManager sm = new SoundManager();分别作为sm.audioSoundssm.minTime操作

解决方案:

public static List<AudioSource> audioSounds = new List<AudioSource>();
public static double minTime = 0.5;

使您的audioSoundsminTime变量作为静态变量,因为您在静态方法(playSound)中使用它们。

将方法标记为static可以防止在该方法中使用非静态(实例)成员。

要了解更多,请阅读SO QA:

c#中的Static关键字