对场景进行重新编码不会从另一个脚本

时间:2015-08-02 22:19:58

标签: c# unity3d

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

这是我的情况:

我在桌子上有5张牌。一张牌将为分数添加一个点,而另外一张将夺走生命。正确的卡片可以选择连接到场景中不同物体的脚本。

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

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,如果选择第一张牌,玩家将获得一分,但如果随机数不同且玩家选择第一张牌,他将失去生命。

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

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

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

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

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

有关为什么代码在Start()部分第一次正常工作以及Update()部分每次都正常工作的想法???

UPDATE UPDATE UPDATE UPDATE 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 ()
     {

     }
 }

2 个答案:

答案 0 :(得分:1)

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

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

另外,你可以看看一些好的编程实践,因为我看到你评论你的条件开关中有很多情况,也许你可以正确地使用多态来应用更好的建模。 (只是像谷歌那样&#34;改变多态性的开关&#34;或者像这样思考并稍微研究一下)

答案 1 :(得分:0)

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

这是通用持久化类的示例 使用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>