C# 为什么在场景重新加载后,我的非静态游戏对象会在脚本中丢失其引用?

C# 为什么在场景重新加载后,我的非静态游戏对象会在脚本中丢失其引用?,c#,unity3d,reference,scene,gameobject,C#,Unity3d,Reference,Scene,Gameobject,我的画布上有一个空的游戏对象,用来显示一个广告菜单,我通过inspector将它附加到一个单独的脚本(而不是菜单本身)中的一个公共变量中 我正在使用adMenu.SetActive(false)在脚本中将其设置为非活动状态,该脚本在我的游戏的第一次播放时起作用。但是,当我通过场景中的一个按钮重新启动场景时,菜单将失去对检查器中相同游戏对象的引用,我收到以下错误: MissingReferenceException: The object of type 'GameObject' has been

我的画布上有一个空的游戏对象,用来显示一个广告菜单,我通过inspector将它附加到一个单独的脚本(而不是菜单本身)中的一个公共变量中

我正在使用
adMenu.SetActive(false)
在脚本中将其设置为非活动状态,该脚本在我的游戏的第一次播放时起作用。但是,当我通过场景中的一个按钮重新启动场景时,菜单将失去对检查器中相同游戏对象的引用,我收到以下错误:

MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.
这在我身上从未发生过,在场景重新加载后,其他游戏对象以类似的方式初始化

其他详情:

  • GameObject.Find()
    可以使用同一脚本中的名称检索游戏对象
  • DontDestroyOnLoad()
    不会在脚本或它所连接的游戏对象上的任何位置使用

代码:

使用System.Collections.Generic;
使用UnityEngine;
使用UnityEngine。广告;
使用MEC;
公共类AdManager:MonoBehavior,iUnityadListener
{
内部静态AdManager实例;
私有静态布尔值初始化=false;
公共游戏对象菜单;
私有字符串放置=“rewardedVideo”;
void Start()
{
实例=此;
如果(!i初始化)
{
isInitialized=true;
advision.AddListener(本);
advision.Initialize(Constants.appleGameId,true);
}
}
IEnumerator ShowAd()
{
如果(!advision.IsReady())
{
屈服返回定时。WaitForOneFrame;
}
广告、表演(安置);
}
公共无效关闭菜单()
{
Debug.Log(“Is adMenu null:+(adMenu==null));//仅在第一次播放时返回false
adMenu.SetActive(false);
}
UNITYADSDIDFinish上的公共void(字符串placementId,ShowResult ShowResult)
{
如果(showResult==showResult.Finished)
{
CloseAdMenu();
}
}
公共void onUnityadReady(字符串placementId)
{
//抛出新系统。NotImplementedException();
}
public void OnUnityAdsDidError(字符串消息)
{
//抛出新系统。NotImplementedException();
}
公共void OnUnityAdsDidStart(字符串placementId)
{
//抛出新系统。NotImplementedException();
}
}

在重新启动方法中,您应该使用
adMenu.SetActive(true)
重新激活按钮,否则,当您再次调用场景时,
adMenu
GameObject
被禁用,因此您无法访问
GameObject

也许您可以在AdManager中添加一个方法,如:

public void OpenAdMenu()
{
    adMenu.SetActive(true);
}

然后在
AdManager.Start()
上调用它,所发生的事情与菜单对象或
静态
实例无关

问题是重新调用

public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
由于您已通过注册实例

Advertisement.AddListener(this);
但是
这个
实例将在场景更改后被销毁

如图所示,你应该这样做

private void OnDestroy() 
{
    Advertisement.RemoveListener(this);
}

我将检查由单例模式引起的流。静态实例可能仍然指向上一场景中的AdManager实例。即使更新了静态引用,调用CloseAdMenu()的事件(可能是onUnityadDidFinish)也可能会在AdManager.Start()之前调用,从而导致在更新为当前场景中的场景之前对使用的前一场景的静态引用。通常,在Awake()中连接所有依赖项以最小化此类风险,甚至尽可能避免单例模式。这很有效,谢谢,但为什么错误回溯会指向my
adMenu.SetActive(false)
行,而不是不运行
onUnityadDidFinish()
private void OnDestroy() 
{
    Advertisement.RemoveListener(this);
}