【问题标题】:How to access gameobject present in another scene [duplicate]如何访问另一个场景中存在的游戏对象[重复]
【发布时间】:2018-04-03 18:57:07
【问题描述】:

我正在 unity3d 中创建一个简单的猜数字游戏。

我想在按钮单击时打开一个新场景,并从当前场景更改加载场景中存在的文本元素的文本。

我已经能够在按钮单击时打开新场景,但是我如何访问其他场景中的文本元素,以便我可以从当前场景更改其文本。 这是我到目前为止所拥有的,但它显然会抛出NullReferenceException,因为我无法从当前场景访问另一个场景中的文本元素。

SceneManager.LoadScene("End Scene");
gameResultText.text = "You Won!!";        //<-------this line throws the exception
gameResultText.color = Color.green;

【问题讨论】:

    标签: unity3d scene-manager


    【解决方案1】:

    我想出了更好的解决方案:

    制作一个设置静态字符串变量的脚本。此脚本必须在您的游戏场景中,并且会保存结果。

    public class ResultTextScript : MonoBehaviour
    {
        public static string ResultText;
    
        void EndGame(){
        if (won){ //if won game
                ResultText = "You won!"
           }
           else //if lost game
           {
                ResultText = "You lost, try again another time!"
           }
           //Change scene with SceneManager.LoadScene("");
        }
    
    }
    

    将此脚本放在最终场景的结果文本中。此脚本将检索结果并显示它。

    Using UnityEngine.UI;
    
    public class EndGameDisplayResult{
    
       Text text; 
       OnEnable(){
       Text.text = ResultTextScript.ResultText
       }
    }
    

    这样一加载新场景就会设置文本。





    以前/替代方法:

    如果您已经打开了场景,一种选择是在“您赢了!”中添加一个脚本。包含引用自身的静态变量的文本。

    就这样吧。

    public class ResultTextScript : MonoBehaviour
    {
        public static ResultTextScript Instance;
    
        void Awake(){
            if (Instance == null)
                Instance = this;
        }
    }
    

    然后您可以从其他脚本中的任何位置(包括场景之间)调用对该游戏对象的引用。

    点赞ResultTextScript.Instance

    请注意,虽然您不能在 Awake 方法中调用引用,因为这是初始化变量的地方,但您可以在调用 Awake 方法后使用它。

    基本上

    1. 将 ResultTextScript 添加到“结束场景”中的 Text 对象中
    2. 从“游戏场景”中打开“结束场景”,例如使用您已经执行的 SceneManager 方法。
    3. 确保已加载结束场景,然后在脚本中说出您希望更改文本gameObject go = ResultTextScript.Instance.gameObject

    【讨论】:

    • 把'!='改成'==',第一个写错了。
    • End Scene 是包含我要更改的文本元素的场景,目前我在Game SceneEnd Scene 尚未打开。我想从Game Scene 访问End Scene 中的文本元素,以便在加载时更改其文本。
    • 您已经使用 SceneManager 打开了场景。请看一下我现在在回答中提出的更好的解决方案。旧答案在其下方,但请查看最高答案。
    【解决方案2】:

    我不相信有办法修改当前未打开的场景的上下文或对象。

    public class GameResults {
       public static string finalText = "";
    }
    

    在加载场景的函数中,在调用加载场景之前,您可以像这样访问该文本:

    GameResults.finalText = "You Win!"; 要么 GameResults.finalText = "You Lose!";

    加载你的场景,然后在你的文本对象上给它一个这样的脚本:

    using UnityEngine;
    using UnityEngine.UI;
    public class ResultTextScript : MonoBehaviour
    {
        public Text textResults;
        void Start() {
            textResults = getComponent<Text>();
            if(textResults != null) {
                textResults.text = GameResults.finalText;
            }
        }
    }
    

    您还可以使用其他东西,将游戏结果存储在PlayerPrefs 中,并在结束场景开始时加载您存储在PlayerPrefs 首选项中的字符串或整数。这将帮助您避免创建不必要的类或静态变量。

    所以喜欢之前你可以这样做:

    PlayerPrefs.SetString("GameResults", "You Win!"); 要么 PlayerPrefs.SetString("GameResults", "You Lose!");

    加载你的场景,然后在你的文本对象上给它一个这样的脚本:

    using UnityEngine;
    using UnityEngine.UI;
    public class ResultTextScript : MonoBehaviour
    {
        public Text textResults;
        void Start() {
            textResults = getComponent<Text>();
            if(textResults != null) {
                textResults.text = PlayerPrefs.GetString("GameResults", "");
            }
        }
    }
    

    【讨论】:

    • 我建议的参考不会被破坏,因为它是在他正在移动的场景中,而不是在他要离开的场景中。
    • 你能保证在调用该函数的下一行时,场景已经完全加载并且所有对象都已经开始调用了吗?另外,您的静态对象所在的实例将在他的文本对象之前完全初始化吗?你不能,因为你不知道他的层次结构是如何布置的。
    • @Doh09 根据他的代码,他确实卸载了旧场景。他没有覆盖默认的辅助参数LoadSceneMode.Single,它会卸载当前场景。 docs.unity3d.com/ScriptReference/… 直接引用文档When using this SceneManager.LoadScene, the loading **does not happen immediately**, it completes in the next frame. 不能保证在原始帖子中的该行运行之前调用了starts。
    • 恐怕我以某种方式将加载误认为是附加场景加载,而不是常规场景加载。在这种情况下,您是对的,对象方法可能无法像我最初提出的那样工作。但是,新的字符串方法仍然有效。
    • @Doh09 是的,您的新方法将起作用,您没有存储单一行为的实例,它是一个静态字符串,在场景转换中不会变为 null。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-31
    • 2022-10-18
    • 1970-01-01
    • 1970-01-01
    • 2022-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多