【问题标题】:Realoding an scene doesn't load the content of a variable from another script重新加载场景不会从另一个脚本加载变量的内容
【发布时间】:2015-08-03 19:21:36
【问题描述】:

我需要帮助解决我在为 Unity3D 编写脚本时发现的问题。

这是我的情况:

我桌上有 5 张牌。一张牌会给分数加分,而另外 4 张牌会夺走生命。正确的卡片是在附加到场景中不同对象的脚本上随机选择的。

在我的第一张卡片中,我附上了这个脚本

public void SelectCard()
{
    switch (externalVariable)
    {
        case 1:
            UnityEngine.Debug.Log("You win a point!");
            Application.LoadLevel("Mini Game 1");
            break;

        case 2:
            UnityEngine.Debug.Log("You lose a life!!!");
            Application.LoadLevel("Mini Game 1");
            break;

        case 3:
            UnityEngine.Debug.Log("You lose a life!!!");
            Application.LoadLevel("Mini Game 1");
            break;

        case 4:
            UnityEngine.Debug.Log("You lose a life!!!");
            Application.LoadLevel("Mini Game 1");
            break;

        case 5:
            UnityEngine.Debug.Log("You lose a life!!!");
            Application.LoadLevel("Mini Game 1");
            break;
    }
}

如您所见,如果随机数为 1,则玩家选择第一张牌将获得一分,但如果随机数不同且玩家选择第一张牌,则玩家将失去一条生命。

p>

随机数存储在一个 int 变量中。为了访问它,我将它添加到第一张卡上附加的脚本的 start() 部分

externalVariable= externalObject.GetComponent<MiniGame1RightCard>().rightCard;
UnityEngine.Debug.Log("The right card is card number: " + externalVariable);

因此,第一张卡片将访问由附加到同一场景中存在的不同对象的外部脚本生成的随机数,将其存储,然后通过控制台输出告诉我哪张是正确的卡片。然后,当玩家点击第一张牌时,脚本会比较存储在 externalVariable 上的随机数来检查第一张牌是否真的是正确的牌。无论哪种方式,最后一步都是重新加载相同的场景以重新开始。

场景加载的第一时间,一切运行完美。我的问题从第二次加载场景开始:externalVariable 始终为零。现在对于棘手的部分,如果我将完全相同的代码放在 Update() 部分而不是 Start() 部分中,externalVariable 保持为零一两秒,然后更改为生成的随机数。

我的猜测是,当我重新加载场景以重新开始时,我做错了,但我不知道是什么。

关于为什么代码第一次在 Start() 部分和每次在 Update() 部分都能正常工作的任何想法?

更新更新更新更新更新。

附在card1上的全部代码

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.IO;
using System;
using System.Threading;

public class Card1: MonoBehaviour
{
   private string querySeleccionar = "SELECT Nivel FROM LevelAndDifficultyWHERE id=1;";
   Text textoSilaba1;
 public GameObject cardImage1;
 public int level;
 public int externalVariable;
 public GameObject objetoExterno;

 public void SeleccionarSilaba()
 {
     switch (externalVariable)
     {
         case 1:
             UnityEngine.Debug.Log("You win a point!");
             Application.LoadLevel("Mini Juego 1");
             break;

         case 2:
             UnityEngine.Debug.Log("You lose a life!!!");
             Application.LoadLevel("Mini Juego 1");
             break;

         case 3:
             UnityEngine.Debug.Log("You lose a life!!!");
             Application.LoadLevel("Mini Juego 1");
             break;

         case 4:
             UnityEngine.Debug.Log("You lose a life!!!");
             Application.LoadLevel("Mini Juego 1");
             break;

         case 5:
             UnityEngine.Debug.Log("You lose a life!!!");
             Application.LoadLevel("Mini Juego 1");
             break;
     }
 }

 public void OnMouseDown()
 {

 }

 // Use this for initialization
 void Start ()
 {
     //lot of database stuff

     switch (level)
     {
         case 1:

         //lots of cases
     }
     externalVariable= externalObject.GetComponent<MiniGame1RightCard>().rightCard;
     UnityEngine.Debug.Log("The right card is card number: " + externalVariable);
     }

// Update is called once per frame
void Update ()
 {

 }
}

生成随机数的脚本

     using UnityEngine;
 using System.Collections;

 public class MiniGame1RightCard: MonoBehaviour
 {
     public int rightCard;

     // Use this for initialization
     void Start ()
     {
         silabaCorrecta = UnityEngine.Random.Range(1, 5);
         UnityEngine.Debug.Log("The right card is card number " + rightCard);
     }

     // Update is called once per frame
     void Update ()
     {

     }
 }

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    正如 Neeraj 已经提到的,您正在生成随机数并尝试在同一个游戏周期(每个对象创建只运行一次)中获取它的值,并且 Unity 可以按任何顺序执行它们(在它们两者之间任何都可以先运行,所以如果 Unity 在您的随机生成器之前运行您的卡片脚本,它将无法工作,因为您尚未创建随机值)。

    简单的解决方案是在 Awake() 方法而不是 Start() 中运行随机生成器逻辑。

    此外,您可以查看一些良好的编程实践,因为我看到您评论说您的条件开关中有很多情况,也许您可​​以正确使用多态性来应用更好的建模。 (只是谷歌诸如“改变多态性开关”之类的东西或类似这样的想法并进行一些研究)

    【讨论】:

    • 谢谢,对随机数生成器使用 Awake() 方法效果很好。关于您的建议,我使用开关是因为它是针对唐氏综合症儿童的阅读游戏,并且我正在按照音节法教他们如何阅读。基于此,我需要将单词分成音节。在第一级,音节遵循声-辅音或辅音-声的规则,因为音节仅由两个字母组成,但在第二级,它们遵循声-辅-声或声-声-辅音或辅音的规则-声-辅音,或辅-辅-声,
    • 或consonant-vocal-vocal,或vocal-consonant-consonant,因为音节由三个字母组成。我的问题是,在西班牙语中,有时音节没有单词,例如“ox”,西班牙语中没有以音节 ox 开头的单词。因此,使用自动规则生成音节并不适合我。多态性的原理相同。但是,嘿,我到底知道什么?,也许是可能的。到目前为止,我有 400 个案例,我刚开始字母 P,我猜剩下的 11 个字母会增加到... IDK,700 个案例?
    【解决方案2】:

    这是统一的预期行为,因为每当加载场景时,以前的游戏对象和脚本总是会被销毁并重新创建。如果要保留生成随机数的脚本文件或游戏对象,则必须使该类成为持久类,这样它就不会在场景加载时被破坏。

    这是通用持久类的示例 使用 UnityEngine;

    //This is the parent class of all the singlton classes
    public class Persistent<T> : MonoBehaviour
        where T : Component
    {
        private static T instance;
        public static T Instance {
            get {
                if (instance == null) {
                    instance = FindObjectOfType<T> ();
                    if (instance == null) {
                        GameObject obj = new GameObject ();
                        //obj.hideFlags = HideFlags.HideAndDontSave;
                        instance = obj.AddComponent<T> ();
                    }
                }
                return instance;
            }
        }
    
        public virtual void Awake ()
        {
            //DontDestroyOnLoad (this.gameObject);
            if (instance == null) {
                instance = this as T;
            } else {
                Destroy (gameObject);
            }
        }
    }
    

    现在,如果您从此类继承任何类,则不会在场景加载时破坏。这就是你可以从这个类继承的方式。

    public class MiniGame1RightCard : Persistent<MiniGame1RightCard>
    

    【讨论】:

    • 好的,我确实理解加载场景时所有对象和脚本都会被销毁的事实。当我的场景重新加载生成随机数的脚本时,它实际上会毫无问题地生成随机数。当我尝试从另一个脚本访问包含随机数的变量时,我的问题就开始了。根据您刚才告诉我的内容,当重新加载场景时,所有内容都会重新创建,因此,如果重新创建了我用来访问该变量的脚本,那么在重新加载脚本时它应该访问该变量。到目前为止,它似乎确实如此,但不知何故
    • 它的值为零。在运行时我观察变量并且不是零,而是随机数。脚本 B 上的变量 Y 将包含脚本 A 生成的随机数,存储在变量 X 上,总是用零值填充,即使 X 的值是一个数字,任何数字。如果问题是由场景的重新加载以及所有对象和脚本的破坏引起的,那么为什么它在 Update() 部分中可以正常工作?是的,对于我需要做的事情,我可以使用 Update() 调用,但随后脚本将每分钟用 Y 的内容填充 X 3600 次
    • 您是在启动函数还是唤醒函数中生成随机数?好像你有执行顺序问题。您需要发布脚本以查找可能的问题。
    • 我认为 MiniGame1RightCard 类中缺少某些代码,我可以看到您将随机数存储在“silabaCorrecta”中,而不是在 rightCard 中。如果您在 Start 函数中为 rightCard 分配随机数,那么这就是问题所在。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多