C# 在差异场景统一中寻找参照
我不知道如何找到referenceC# 在差异场景统一中寻找参照,c#,unity3d,C#,Unity3d,我不知道如何找到referenceGameObjectbut different Scene并设置onclick when difference Scene,所以我有一个GameManager,它可以管理所有场景,但只能在主菜单上使用。所以我决定让Dontdestroyonload,问题从这里开始,所以当我玩main游戏场景时,inspector的GameManager字段会找到,但我不能拖放不同的场景,对吗?这使我困惑 如果游戏管理器在主菜单场景中运行,问题是如何在onClick事件中拖放,比
GameObject
but different Scene并设置onclick when difference Scene,所以我有一个GameManager,它可以管理所有场景,但只能在主菜单上使用。所以我决定让Dontdestroyonload
,问题从这里开始,所以当我玩main游戏
场景时,inspector的GameManager字段会找到,但我不能拖放不同的场景,对吗?这使我困惑
如果游戏管理器在主菜单
场景中运行,问题是如何在onClick
事件中拖放,比如我希望暂停按钮处于活动状态或游戏中的其他内容
]
我尝试了onloadscene(场景s,模式)
,但什么都没发生,这里是GameManager的纸条:
public static GameManager gameManager;
[Header("Main Menu panels")]
public GameObject startPanel;
public GameObject settingPanel;
public GameObject levelPanel;
[Header("InGame Panels")]
#region Panel
public GameObject pausePanel;
public GameObject ObjectivePanel;
public GameObject shopPanel;
private int click = 0;
[Header("Int Tweaks")]
public int indexLevel;
public int onlevel;
public bool isPaused;
_levelSelect LevelSelect;
public static GameManager Instance { set; get; }
public int levelindexPlayerPrefs;
private void Awake()
{
if (gameManager != null)
{
Instance = this;
Destroy(gameObject);
}
else
{
DontDestroyOnLoad(gameObject);
}
}
void Start()
{
LevelSelect = FindObjectOfType<_levelSelect>();
OnStart();
onlevel = int.Parse(LevelSelect.levelIndex) + 1;
indexLevel = int.Parse(LevelSelect.levelIndex);
getPlayerData();
}
// Update is called once per frame
void Update()
{
ExitApp();
}
public void OnStart()
{
startPanel.SetActive(true);
settingPanel.SetActive(false);
levelPanel.SetActive(false);
}
#region Buttons
public void startbutton()
{
levelPanel.SetActive(true);
startPanel.SetActive(false);
settingPanel.SetActive(false);
}
public void backButtonMainMenu()
{
levelPanel.SetActive(false);
startPanel.SetActive(true);
settingPanel.SetActive(false);
}
public void settingbutton()
{
levelPanel.SetActive(false);
startPanel.SetActive(false);
settingPanel.SetActive(true);
}
public void PauseButton()
{
Time.timeScale = 0f;
pausePanel.SetActive(true);
ObjectivePanel.SetActive(false);
}
public void Resume()
{
Time.timeScale = 1f;
}
#endregion
public void ExitApp()
{
if (Input.GetKey(KeyCode.Escape))
{
click++;
StartCoroutine(ClickTime());
if (click>1)
{
print("Exit Game");
Application.Quit();
}
}
}
IEnumerator ClickTime()
{
yield return new WaitForSeconds(0.5f);
click = 0;
}
public void getPlayerData()
{
levelindexPlayerPrefs = PlayerPrefs.GetInt("LevelIndex", 0);
}
public void updateLevel(int Index)
{
if (levelindexPlayerPrefs < Index)
{
PlayerPrefs.SetInt("LevelIndex", Index);
levelindexPlayerPrefs = PlayerPrefs.GetInt("LevelIndex");
}
}
#region onloadedScenePickRefferences
private void OnEnable()
{
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnDisable()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
pausePanel = GameObject.FindGameObjectWithTag("PausePanel");
ObjectivePanel = GameObject.FindGameObjectWithTag("ObjectivePanel");
}
#endregion
//public IEnumerator EndChapter()
//{
// updateLevel(indexLevel + 1);
// getPlayerData();
//}
公共静态游戏管理器游戏管理器;
[标题(“主菜单面板”)]
公共游戏对象startPanel;
公共游戏对象设置面板;
公共游戏对象级面板;
[标题(“InGame面板”)]
#地区小组
公共游戏对象pausePanel;
公共游戏对象对象面板;
公共游戏对象商店面板;
私有int click=0;
[标题(“整数调整”)]
公共指数级;
公共国际层面;
公共场所;
_levelSelect levelSelect;
公共静态GameManager实例{set;get;}
公共int-levelIndExplayerRefs;
私人空间
{
如果(gameManager!=null)
{
实例=此;
摧毁(游戏对象);
}
其他的
{
DontDestroyOnLoad(游戏对象);
}
}
void Start()
{
LevelSelect=FindObjectOfType();
OnStart();
onlevel=int.Parse(LevelSelect.levelIndex)+1;
indexLevel=int.Parse(LevelSelect.levelIndex);
getPlayerData();
}
//每帧调用一次更新
无效更新()
{
ExitApp();
}
public void OnStart()
{
startPanel.SetActive(真);
settingPanel.SetActive(设置激活)(错误);
levelPanel.SetActive(假);
}
#区域按钮
公共无效开始按钮()
{
levelPanel.SetActive(真);
startPanel.SetActive(假);
settingPanel.SetActive(设置激活)(错误);
}
公共无效backButtonMainMenu()
{
levelPanel.SetActive(假);
startPanel.SetActive(真);
settingPanel.SetActive(设置激活)(错误);
}
公共无效设置按钮()
{
levelPanel.SetActive(假);
startPanel.SetActive(假);
settingPanel.SetActive(真);
}
公共无效暂停按钮()
{
Time.timeScale=0f;
pausePanel.SetActive(真);
ObjectivePanel.SetActive(假);
}
公众简历()
{
Time.timeScale=1f;
}
#端区
公营机构
{
if(Input.GetKey(KeyCode.Escape))
{
点击++;
开始例行程序(单击时间());
如果(单击>1)
{
打印(“退出游戏”);
Application.Quit();
}
}
}
IEnumerator ClickTime()
{
收益率返回新的WaitForSeconds(0.5f);
单击=0;
}
公共无效getPlayerData()
{
levelindexPlayerPrefs=PlayerPrefs.GetInt(“LevelIndex”,0);
}
公共void updateLevel(int索引)
{
if(levelindexPlayerPrefs<索引)
{
PlayerPrefs.SetInt(“LevelIndex”,索引);
levelindexPlayerPrefs=PlayerPrefs.GetInt(“LevelIndex”);
}
}
#区域超负荷情景差异
私有void OnEnable()
{
SceneManager.sceneLoaded+=在sceneLoaded上;
}
私有无效不可撤销()
{
scenemager.sceneLoaded-=在sceneLoaded上;
}
void OnSceneLoaded(场景,加载场景模式)
{
pausePanel=GameObject.FindGameObjectWithTag(“pausePanel”);
ObjectivePanel=GameObject.FindGameObjectWithTag(“ObjectivePanel”);
}
#端区
//公共IEnumerator EndChapter()
//{
//更新级别(索引级别+1);
//getPlayerData();
//}
以下是我可能会做的:
使用static
类存储和共享所有引用。它不必出现在任何场景中,只需“生活”在资产中:
public static class GlobalReferences
{
// as example just for one reference but you can implement the rest equally yourself
// here this class actually stores the reference
private static GameObject startPanel;
// A public property in order to add some logic
// other classes will always access and set the value through this property
public static GameObject StartPanel
{
get
{
// if the reference exists return it right away
if(startPanel) return startPanel;
// as a fallback try to find it
startPanel = GameObject.FindGameObjectWithTag("StartPanel");
// ofcourse it might still fail when you simply try to access it
// in a moment it doesn't exist yet
return startPanel;
}
set
{
startPanel = value;
// invoke an event to tell all listeners that the startPanel
// was just assigned
OnStartPanelReady?.Invoke();
}
}
// An event you will invoke after assigning a value making sure that
// other scripts only access this value after it has been set
// you can even directly pass the reference in
public static event Action<GameObject> OnStartPanelReady;
}
在其他场景中,在添加侦听器之前已加载,以便在其他场景准备就绪后立即执行任务:
public class ExampleConsumer : MonoBehaviour
{
[Header("Debug")]
[SerializeField] private GameObject startPanel;
private void Awake()
{
// Try to get the reference
startPanel = GlobalReferences.StartPanel;
// if this failed then wait until it is ready
if(!startPanel)
{
// it is save to remove callbacks even if not added yet
// makes sure a listener is always only added once
GlobalReferences.OnStartPanelReady -= OnStartPanelReady;
GlobalReferences.OnStartPanelReady += OnStartPanelReady;
}
// otherwise already do what you want
else
{
OnStartPanelReady(startPanel);
}
}
private void OnDestroy()
{
// always make sure to clean up callbacks when not needed anymore!
GlobalReferences.OnStartPanelReady -= OnStartPanelReady;
}
private void OnStartPanelReady(GameObject newStartPanel)
{
startPanel = newStartPanel;
// always make sure to clean up callbacks when not needed anymore!
GlobalReferences.OnStartPanelReady -= OnStartPanelReady;
// NOTE: It is possible that at this point it is null anyway if another
// class has set this actively to null ;)
if(startPanel)
{
// Now do something with the startPanel
}
}
}
另一种情况是,当您需要在新加载的场景中引用主场景时。。。它应该已经设置,因为主场景是首先加载的,并且已经分配了相应的引用
现在,您可以选择这个
静态
类,也可以简单地为每个引用实现相同的逻辑,这些引用需要在相应的组件中直接共享,您可以通过拖放引用它们。。这没有什么区别,因为您将使用静态字段和事件,这些字段和事件不绑定到任何实例,而是绑定到类型本身。Unity不能保证同时加载两个场景,因此不允许保存跨场景引用(即,在编辑器中拖放)。您需要管理对象发现(FindObjectOfType
等)在运行时,就像您已经在OnSceneLoaded
@中所做的那样,沉浸式是的,但是什么都没有发生,对于onclick
,这是不可能的referenced@Syarifabdurrahman您也可以在运行时通过类似于someButton.onClick.AddListener(()=>{DoSomething();})的方式向onClick
添加回调代码>(但它们不会出现在检查器中!)。但是,该脚本是在主场景中还是在稍后加载的场景中?问题可能是在将回调添加到之前调用了sceneLoaded
it@derHugo首先在主菜单中,当然,当我进入主游戏场景时,这个脚本也在那个场景中,这就是为什么我使用don't destroy onload,因为我认为如果我在Awake
中只使用1GameManager
这会很好,你为什么要这样做Instance=this;摧毁(游戏对象)代码>??这将立即销毁您刚才分配的引用实例
,因此它将始终为null
。这也会立即导致调用OnDisable
,因此OnSceneLoaded
可能根本就不会执行?或者。。。实际上,gameManager
从未设置到
public class ExampleConsumer : MonoBehaviour
{
[Header("Debug")]
[SerializeField] private GameObject startPanel;
private void Awake()
{
// Try to get the reference
startPanel = GlobalReferences.StartPanel;
// if this failed then wait until it is ready
if(!startPanel)
{
// it is save to remove callbacks even if not added yet
// makes sure a listener is always only added once
GlobalReferences.OnStartPanelReady -= OnStartPanelReady;
GlobalReferences.OnStartPanelReady += OnStartPanelReady;
}
// otherwise already do what you want
else
{
OnStartPanelReady(startPanel);
}
}
private void OnDestroy()
{
// always make sure to clean up callbacks when not needed anymore!
GlobalReferences.OnStartPanelReady -= OnStartPanelReady;
}
private void OnStartPanelReady(GameObject newStartPanel)
{
startPanel = newStartPanel;
// always make sure to clean up callbacks when not needed anymore!
GlobalReferences.OnStartPanelReady -= OnStartPanelReady;
// NOTE: It is possible that at this point it is null anyway if another
// class has set this actively to null ;)
if(startPanel)
{
// Now do something with the startPanel
}
}
}