【转】Unity3d的单例及场景间的数据传递

  http://blog.csdn.net/zy19940906/article/details/47724387

           单例是场景间切换时传递数据的最常见的方式之一,在unity中,很多方法被封装,有时候感觉不知道从何处看起,只能从官方文档上去根据功能找类了。个人感觉u3d可视化太过强烈,许多自定义的一些功能似乎让人无从下手,当然也可能是自己水平不够,不太熟悉。比如说场景间的数据传递,在cocos2dx时,我一般会在director里边创建一个单例Interface,用以游戏中的从数据库读取玩家信息,关卡信息,场景间的数据同步等;要么就是在场景间切换的时候直接用带参数的构造函数实现,在u3d就不用说了,场景一般是直接在界面上创建了,切换场景时也只是简单的一句 Application.LoadLevel(scene);,没法在另一个场景创建时传递数据,因为它的创建场景函数是这样的:

[csharp] view plain copy
 
  1. // 摘要:   
  2.         //     Create a new scene.  
  3.         [WrapperlessIcall]  
  4.         public static void NewScene();  

因而只好用单例去实现了:

            关于单例也很多种实现形式,参考了网上一些别人的方法,自己实践整理出三种较为便捷的方法,比较简单

方法一:纯c#单例,这个单例正常是不需要使用unity的接口和方法,当然,如果要读取文件用它的也是更方便

[csharp] view plain copy
 
  1. using UnityEngine;  
  2. using System.Collections;  
  3. //用以存放数据测试用的结构体  
  4. public struct Tollgate_Date  
  5. {  
  6.   public  int index;  
  7.   public   int playerhealth;  
  8. }  
  9.   
  10. public class MyInterface/* : MonoBehaviour*/  
  11. {  
  12.     private  static MyInterface myinterface = null;  
  13.     public Tollgate_Date[] date = new Tollgate_Date[10];  
  14.       
  15.     // Use this for initialization  
  16.     void Start () {  
  17.       
  18.     }  
  19.    public  static MyInterface getInstance()  
  20.     {  
  21.         if(myinterface==null)  
  22.         {  
  23.             myinterface=new MyInterface();  
  24.             myinterface.init();  
  25.   
  26.         }  
  27.         return myinterface;  
  28.     }  
  29.     public void init()   
  30.     {  
  31.           
  32.         for (int i = 0; i < date.Length;i++ )  
  33.         {  
  34.            date[i].index = 1;  
  35.            date[i].playerhealth = 1;  
  36.         }  
  37.          
  38.     }  
  39.     // Update is called once per frame  
  40.     void Update ()   
  41.     {  
  42.       
  43.     }  
  44. }  

这个方法,就不能再继承基类MonoBehaviour了,继承之后它默认需要挂在在一个对象身上,所以入过不给对象,那么将赋值不了,myinterface一直为空。这样只需要在第一个场景任意一个object的脚本中初始化下就行了:MyInterface.getInstance();

方法二:手动创建一个对象挂载

[csharp] view plain copy
 
  1. </pre><pre name="code" class="csharp">using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class MyDate : MonoBehaviour {  
  5.       
  6.     private static MyDate mydate = null;  
  7.     public Tollgate_Date[] tollgatedate = new Tollgate_Date[10];  
  8.     public static GameObject obj;  
  9.     // Use this for initialization  
  10.     void Start () {  
  11.       
  12.     }  
  13.   
  14.     public static MyDate getInstance()  
  15.     {  
  16.         if(mydate==null)  
  17.         {  
  18.   
  19.             obj = new GameObject("MyDate");//创建一个带名字的对象  
  20.             mydate = obj.AddComponent(typeof(MyDate)) as MyDate;  
  21.             mydate.init();  
  22.             DontDestroyOnLoad(obj);  
  23.         }  
  24.         return mydate;  
  25.     }  
  26.     void init()  
  27.     {  
  28.         for (int i = 0; i < tollgatedate.Length; i++)  
  29.         {  
  30.             tollgatedate[i].index = 1;  
  31.             tollgatedate[i].playerhealth = 1;  
  32.         }  
  33.     }  
  34.     // Update is called once per frame  
  35.     void Update () {  
  36.       
  37.     }  
  38. }  
[csharp] view plain copy
 
  1.   

使用方法同方法一,仅仅在脚本中创建一个对象,而这个对象因为DontDestroyOnLoad函数将一直不会被释放,同时再次执行时也因为非空而保证不会再创建

其中

[csharp] view plain copy
 
  1. mydate = obj.AddComponent(typeof(MyDate)) as MyDate;  
[csharp] view plain copy
 
  1. </pre><pre name="code" class="csharp">通过底层可以看到意思是添加一个名称为className的组件到游戏物体,把这个单例对象和GameObject对象关联起来。  

方法三:对象方法

[csharp] view plain copy
 
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class TestInstance : MonoBehaviour   
  5. {  
  6.     private static TestInstance testinsatnce = null;  
  7.     public Tollgate_Date[] tollgatedate = new Tollgate_Date[10];  
  8.     // Use this for initialization  
  9.     void Start ()   
  10.     {  
  11.     }  
  12.     void Awake()  
  13.     {  
  14.         if (testinsatnce == null)  
  15.         {  
  16.             testinsatnce = this;  
  17.             testinsatnce.init();  
  18.             //  
  19.             DontDestroyOnLoad(gameObject);    
  20.   
  21.         }  
  22.         else  
  23.         {  
  24.             Destroy(gameObject);  
  25.         }  
  26.     }  
  27.     public static TestInstance getInstance()  
  28.     {  
  29.         return testinsatnce;  
  30.   
  31.     }  
  32.     void init()  
  33.     {  
  34.         for (int i = 0; i < tollgatedate.Length; i++)  
  35.         {  
  36.             tollgatedate[i].index = 1;  
  37.             tollgatedate[i].playerhealth = 1;  
  38.         }  
  39.     }  
  40.     // Update is called once per frame  
  41.     void Update () {  
  42.       
  43.     }  
  44. }  

这个方法与第二个方法最大区别就是它是在场景中建立一个GameObject,把脚本挂载上去,而不是通过手动创建关联实现,在这里该对象在别处使用时,通过getinstance来取得当前的单例对象。

原文地址:https://www.cnblogs.com/mimime/p/6798957.html