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




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

 

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

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

 

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

 


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. 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();

 

 

 

 

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

 


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. new GameObject("MyDate");//创建一个带名字的对象  
20. 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

 




使用方法同方法一,仅仅在脚本中创建一个对象,而这个对象因为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. 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来取得当前的单例对象。