Unity3d的單例及場景間的數據傳遞

           單例是場景間切換時傳遞數據的最常見的方式之一,在unity中,很多方法被封裝,有時候感覺不知道從何處看起,只能從官方文檔上去根據功能找類了。個人感覺u3d可視化太過強烈,許多自定義的一些功能似乎讓人無從下手,當然也可能是自己水平不夠,不太熟悉。比如說場景間的數據傳遞,在cocos2dx時,我一般會在director裏邊創建一個單例Interface,用以遊戲中的從數據庫讀取玩家信息,關卡信息,場景間的數據同步等;要麼就是在場景間切換的時候直接用帶參數的構造函數實現,在u3d就不用說了,場景一般是直接在界面上創建了,切換場景時也只是簡單的一句 Application.LoadLevel(scene);,沒法在另一個場景創建時傳遞數據,因爲它的創建場景函數是這樣的:

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

因而只好用單例去實現了:

            關於單例也很多種實現形式,參考了網上一些別人的方法,自己實踐整理出三種較爲便捷的方法,比較簡單


方法一:純c#單例,這個單例正常是不需要使用unity的接口和方法,當然,如果要讀取文件用它的也是更方便

using UnityEngine;
using System.Collections;
//用以存放數據測試用的結構體
public struct Tollgate_Date
{
  public  int index;
  public   int playerhealth;
}

public class MyInterface/* : MonoBehaviour*/
{
    private  static MyInterface myinterface = null;
    public Tollgate_Date[] date = new Tollgate_Date[10];
    
	// Use this for initialization
	void Start () {
	
	}
   public  static MyInterface getInstance()
    {
        if(myinterface==null)
        {
            myinterface=new MyInterface();
            myinterface.init();

        }
        return myinterface;
    }
    public void init() 
    {
        
        for (int i = 0; i < date.Length;i++ )
        {
           date[i].index = 1;
           date[i].playerhealth = 1;
        }
       
    }
	// Update is called once per frame
	void Update () 
    {
	
	}
}
這個方法,就不能再繼承基類MonoBehaviour了,繼承之後它默認需要掛在在一個對象身上,所以入過不給對象,那麼將賦值不了,myinterface一直爲空。這樣只需要在第一個場景任意一個object的腳本中初始化下就行了:MyInterface.getInstance();




方法二:手動創建一個對象掛載

</pre><pre name="code" class="csharp">using UnityEngine;
using System.Collections;

public class MyDate : MonoBehaviour {
    
    private static MyDate mydate = null;
    public Tollgate_Date[] tollgatedate = new Tollgate_Date[10];
    public static GameObject obj;
	// Use this for initialization
	void Start () {
	
	}

    public static MyDate getInstance()
    {
        if(mydate==null)
        {

            obj = new GameObject("MyDate");//創建一個帶名字的對象
            mydate = obj.AddComponent(typeof(MyDate)) as MyDate;
            mydate.init();
            DontDestroyOnLoad(obj);
        }
        return mydate;
    }
    void init()
    {
        for (int i = 0; i < tollgatedate.Length; i++)
        {
            tollgatedate[i].index = 1;
            tollgatedate[i].playerhealth = 1;
        }
    }
	// Update is called once per frame
	void Update () {
	
	}
}
 

使用方法同方法一,僅僅在腳本中創建一個對象,而這個對象因爲DontDestroyOnLoad函數將一直不會被釋放,同時再次執行時也因爲非空而保證不會再創建

其中

mydate = obj.AddComponent(typeof(MyDate)) as MyDate;
</pre><pre name="code" class="csharp">通過底層可以看到意思是添加一個名稱爲className的組件到遊戲物體,把這個單例對象和GameObject對象關聯起來。

方法三:對象方法

using UnityEngine;
using System.Collections;

public class TestInstance : MonoBehaviour 
{
    private static TestInstance testinsatnce = null;
    public Tollgate_Date[] tollgatedate = new Tollgate_Date[10];
	// Use this for initialization
	void Start () 
    {
	}
    void Awake()
    {
        if (testinsatnce == null)
        {
            testinsatnce = this;
            testinsatnce.init();
            //
            DontDestroyOnLoad(gameObject);  

        }
        else
        {
            Destroy(gameObject);
        }
    }
    public static TestInstance getInstance()
    {
        return testinsatnce;

    }
    void init()
    {
        for (int i = 0; i < tollgatedate.Length; i++)
        {
            tollgatedate[i].index = 1;
            tollgatedate[i].playerhealth = 1;
        }
    }
	// Update is called once per frame
	void Update () {
	
	}
}
這個方法與第二個方法最大區別就是它是在場景中建立一個GameObject,把腳本掛載上去,而不是通過手動創建關聯實現,在這裏該對象在別處使用時,通過getinstance來取得當前的單例對象。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章