推薦閱讀
- CSDN主頁
- GitHub開源地址
- Unity3D插件分享
- 簡書地址
- 我的個人博客
- QQ群:1040082875
? 一、前言
最近,有粉絲問我:
粉絲:“怎么用單例模式呀?”
我:“https://blog.csdn.net/weixin_43430200/article/details/107459447”
粉絲:“我知道咋寫,就是不知道怎么用”
我:“好家伙,那我就給你演示一下怎么用吧”
? 二、單例模式介紹
首先要了解,單例模式是一種常用的軟體設計模式,定義是單例物件的類只能允許一個實體存在,在許多時候整個系統只需要擁有一個全域物件,有利于協調系統整體的行為,
比如,服務器程式,將配置資訊存放到一個檔案中,然后使用一個單例物件進行讀取,其他服務行程中的其他物件再通過這個單例去獲取這些配置資訊,簡化了配置管理,
單例模式的結構圖如下圖所示:

那么,單例模式在Unity中又有那些應用場景呢:
1、在使用Unity開發專案的時候,經常會遇到需要一個管理類來管理一些全域的變數和方法,比如GameManager用于記錄各種需要在整個游戲中用到資料,
2、一些需要從外部檔案讀取的資料,在其他腳本物件也需要用到的使用,也可以使用單例物件進行讀取,其他物件再通過這個單例物件去獲取資料,
假設有以下需求:
1、整個專案中有且只有一個DataManager單例物件
2、在DataManager單例物件中,需要去讀取檔案的資料,并且保存下載
3、在切換場景的時候DataManager物件不能被銷毀
4、在不同的腳本中可以讀取到DataManager單例物件讀取的值
下面我們就來一步步實作單例物件下的DataManager,
? 三、實作單例模式的DataManager
? 3-1、定義單例物件
我們定義一個DataManager物件,繼承于MonoBehaviour,具體代碼如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DataManager : MonoBehaviour
{
public static DataManager Instance;
private void Awake()
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
}
1、使用靜態的DataManager屬性Instance保證了它可以通過類進行訪問,而不是通過實體化訪問
2、繼承MonoBehaviour類的實體是由Unity進行創建,不能通過建構式創建
3、在Awake函式里面對Instance進行賦值,保證了這個屬性可以第一時間初始化
4、使用DontDestroyOnLoad可以使這個掛載腳本的游戲物件在切換場景中也不會被銷毀
5、DontDestroyOnLoad的引數使用(gameObject),這樣切換場景中游戲物件不會被銷毀,使用this只能保證當前腳本不會被銷毀,但是物件銷毀了,這個腳本也沒有了,
創建完這個物件,在場景中也新建一個DataManager物件,將這個腳本拖到這個物件上:

? 3-2、單例物件去讀取資料保存下來
代碼如下:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class DataManager : MonoBehaviour
{
public static DataManager Instance;
string m_JsonContent;//臨時檔案資料
RootData m_JsonData;//臨時接收JSON決議資料
//資料保存到這個List里面,其他腳本就可以呼叫到了
public List<StationAllInfo> m_StationsAllInfo = new List<StationAllInfo>();
private void Awake()
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
private void Start()
{
ReadJSONData();
}
void ReadJSONData()
{
string pathstations = Application.streamingAssetsPath + "/地鐵站.json";
using (StreamReader SR = new StreamReader(pathstations))
{
m_JsonContent = SR.ReadToEnd();
Debug.Log(m_JsonContent);
SR.Close();
SR.Dispose();
//保存JSON資料
m_JsonData = JsonUtility.FromJson<RootData>(m_JsonContent);
}
for (int i = 0; i < m_JsonData.GisJosnDatas.Count; i++)
{
if (m_JsonData.GisJosnDatas[i].properties.LINE_ID != "")//剔除無用的資訊,保存有用的資訊
{
StationAllInfo item = new StationAllInfo();
item.X = m_JsonData.GisJosnDatas[i].properties.X;
item.Y = m_JsonData.GisJosnDatas[i].properties.Y;
item.STACODE = m_JsonData.GisJosnDatas[i].properties.STACODE;
item.S_NAME = m_JsonData.GisJosnDatas[i].properties.S_NAME;
item.LINE_ID = m_JsonData.GisJosnDatas[i].properties.LINE_ID;
//05 換成 5 (比如05號線 換成5號線)
if (m_JsonData.GisJosnDatas[i].properties.LINE_ID.Substring(0, 1) == "0")
{
item.LINE_NAME = m_JsonData.GisJosnDatas[i].properties.LINE_ID.Substring(1, 1) + "號線";
}
else
{
switch (m_JsonData.GisJosnDatas[i].properties.LINE_ID)//對字母縮寫的站名進行處理
{
case "fs":
item.LINE_NAME = "房山線";
break;
case "bt":
item.LINE_NAME = "八通線";
break;
case "yz":
item.LINE_NAME = "亦莊線";
break;
case "cp":
item.LINE_NAME = "昌平線";
break;
case "jc":
item.LINE_NAME = "機場線";
break;
default:
item.LINE_NAME = m_JsonData.GisJosnDatas[i].properties.LINE_ID + "號線";
break;
}
}
item.STYPE = m_JsonData.GisJosnDatas[i].properties.STYPE;
m_StationsAllInfo.Add(item);
}
}
}
}
? 3-3、在其他腳本中使用資料
我們新建一個UseData.cs腳本去使用資料:
using UnityEngine;
public class UseData : MonoBehaviour
{
private void Update()
{
//點擊鍵盤W 顯示資料
if (Input.GetKeyDown(KeyCode.W))
{
ShowData();
}
}
private void ShowData()
{
for (int i = 0; i < DataManager.Instance.m_StationsAllInfo.Count; i++)
{
Debug.Log(DataManager.Instance.m_StationsAllInfo[i].X + " "
+DataManager.Instance.m_StationsAllInfo[i].Y + " "
+ DataManager.Instance.m_StationsAllInfo[i].STACODE + " "
+ DataManager.Instance.m_StationsAllInfo[i].S_NAME + " "
+ DataManager.Instance.m_StationsAllInfo[i].LINE_ID + " "
+ DataManager.Instance.m_StationsAllInfo[i].LINE_NAME + " "
+ DataManager.Instance.m_StationsAllInfo[i].STYPE + " ");
}
}
}
將這個腳本拖到場景中的物件上:

運行程式,敲擊鍵盤W:

所有的值,都從單例物件DataManager的InStance的m_StationsAllInfo陣列中讀取出來了,
? 3-4、切換場景讀取資料
我們新建兩個場景:Index和Next,然后Index場景中的物件上掛載腳本ChangeScenes.cs腳本,代碼如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class ChangeScenes : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
SceneManager.LoadScene(1);
}
}
}
也就是切換場景,然后在Index場景中新建一個DataManager物件,將DataManager腳本拖上去,
然后Next場景中隨便找一個物件掛載UseData腳本,場景中不需要創建DataManager物件
然后將兩個場景加到Build Setting中:

運行程式:
切換到Next場景,DataManager物件也存在:

敲擊鍵盤W:

所有的值,都從上一個場景中的DataManager物件的掛載腳本的單例物件DataManager.cs的InStance的m_StationsAllInfo陣列中讀取出來了,
? 四、后言
這是Unity使用單例的簡單應用,最主要的幾個知識點是;
1、物件切換場景不銷毀
2、單例物件的靜態屬性
3、資料的保存
4、其他腳本用單例物件的資料的方法
結束,好好學習加油吧!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/287005.html
標籤:其他
上一篇:C語言——三子棋
