单例是场景间切换时传递数据的最常见的方式之一,在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来取得当前的单例对象。