單例是場景間切換時傳遞數據的最常見的方式之一,在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來取得當前的單例對象。