文章目錄
- 11.1 山崗的星光
- 11.2 Unity貓咪救濟管理系統
- 11.3 設定UI攝像機
- 11.4 設定Canvas
- 11.5 制作登錄界面預設
- 11.6 制作大廳界面預設
- 11.7 制作資訊界面預設
- 11.8 UI界面管理器:UIManager
- 11.9 封裝貓資訊的類:CatInfo
- 11.10 貓資訊管理器:CatManager
- 11.11 資料存盤:CatDataBase
- 11.12 Json庫:LitJson
- 11.13 觀察者模式
- 11.14 登錄界面代碼:LoginPanel
- 11.15 大廳界面代碼:PlazaPanel
- 11.16 資訊界面代碼:InfoPanel
簡介:我是一名Unity游戲開發工程師,皮皮是我養的貓,會講人話,它接到了喵星的特殊任務:學習編程,學習Unity游戲開發,
于是,發生了一系列有趣的故事,

11.1 山崗的星光
稀疏的星光,清輝灑地,流浪貓小花凝望著窗外,它沒有想到一個月前它還是一只無家可歸的流浪小貓,此時已經有了一個溫暖的家,
事情要回到一個月前的那個夜晚,秋風瑟瑟,小花在路邊蜷縮著身子,有個人類經過它的身旁,那個人站住了,嘴里發出蹩腳的喵喵聲,慢慢想要靠近,小花見狀立刻躲進了斜坡中的草叢里,那人停留片刻后便離開了,
兩天后,小花又看到了那個人,而且還帶著一只貓一臺電腦,那只貓朝著小花揮手:“喂,過來這邊,不要怕,我們不是壞人,”
小花不敢靠前,那只貓又喊道:“我叫皮皮,這個是我的鏟屎官,這里有吃的,快過來,”
后來,小花不僅飽飽的吃了一餐,還得知了他們正在做一個貓咪救濟管理系統,皮皮是專案的策劃貓,它希望可以為那些流浪貓提供基礎的保障,實名登記流浪貓,統一管理,調度資源,在設定的救濟點投放食物和過冬物資,并與人類鏟屎官合作,希望可以給流浪貓尋找合適的家,
每一只來到地球的喵星人都有一個唯一的編號,只要登記了這個編號,就可以隨時隨地通過貓電波進行通信,小花成為了救濟系統的第一只貓,
很快便有人類來領養了小花,以前,小花總是坐在小斜坡上望著星星,它不知道自己從哪里來的,那里還有很多和它一樣的貓,有的從來沒見過,有的離開了又回來了,有的離開了就再也沒有回來,只有星星一直陪著它,現在它有了家,它也想和皮皮它們一起,幫助流離失所的貓尋找溫暖的家,
山崗的星光,愿你不再流浪,被世界溫柔以待,
11.2 Unity貓咪救濟管理系統
貓咪救濟管理系統,模塊設計如下:

運行效果如下:

本工程使用的Unity版本為2020.1.14f1c1 (64-bit),工程已上傳到GitHub,感興趣的同學可以下載下來學習,
GitHub地址:https://github.com/linxinfa/Unity-CatInfoSystem
11.3 設定UI攝像機
創建一個攝像機,重命名為UICamera,

設定Culling Mask只渲染UI層,

設定視口Projection為正交視口Orthographic,

設定Main Camera不渲染UI層,

11.4 設定Canvas
創建Canvas,并設定Render Mode為Screen Space -Camera,設定Render Camera為UICamera,再把Canvas Scaler組件的UI Scale Mode設定為Scale With Screen Size,

11.5 制作登錄界面預設
LoginPanel.prefab


兩個Input Field組件,用來輸入賬號和密碼(account和password),一個Button組件作為登錄按鈕(LoginButton),
11.6 制作大廳界面預設
PlazaPanel.prefab


一個Button組件作為登記按鈕(AddButton),一個Scroll View組件作為拖拉串列,一個Item作為串列的項,一個Button組件作為退出登錄按鈕(LogoutButton),其中,Item中使用多個Text組件作為資訊顯示,
11.7 制作資訊界面預設
InfoPnel.prefab


使用三個Button組件作為確定、洗掉、關閉按鈕,使用多個Input Field組件和一個Drop Down組件作為資訊輸入,
11.8 UI界面管理器:UIManager
UI預設資源放在Resources目錄中,

封裝一個UIManager類,用來加載界面預設資源和顯示界面,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIManager
{
public void Init(Canvas canvas)
{
m_canvasTrans = canvas.transform;
}
/// <summary>
/// 顯示界面
/// </summary>
/// <param name="panelName">界面名稱</param>
/// <returns></returns>
public GameObject ShowPanel(string panelName)
{
GameObject prefabObj = null;
if (m_panelRes.ContainsKey(panelName))
{
prefabObj = m_panelRes[panelName];
}
else
{
prefabObj = Resources.Load<GameObject>(panelName);
m_panelRes[panelName] = prefabObj;
}
GameObject panelObj = Object.Instantiate(prefabObj);
panelObj.transform.SetParent(m_canvasTrans, false);
return panelObj;
}
private Transform m_canvasTrans;
/// <summary>
/// 界面資源快取
/// </summary>
private Dictionary<string, GameObject> m_panelRes = new Dictionary<string, GameObject>();
/// <summary>
/// 單例模式
/// </summary>
private static UIManager s_instance;
public static UIManager Instance
{
get
{
if (null == s_instance)
s_instance = new UIManager();
return s_instance;
}
}
}
/// <summary>
/// 界面名稱,對應預設檔案名稱
/// </summary>
public class PanelName
{
public const string LOGIN_PANEL = "LoginPanel";
public const string PLAZA_PANEL = "PlazaPanel";
public const string INFO_PANEL = "InfoPanel";
}
11.9 封裝貓資訊的類:CatInfo
貓的資訊中有個uuid是系統生成的,id是貓星人的編號,由喵星人手動輸入,
/// <summary>
/// 貓咪資訊
/// </summary>
public class CatInfo
{
public CatInfo()
{
uuid = System.Guid.NewGuid().ToString("N");
}
/// <summary>
/// 系統唯一識別符號
/// </summary>
public string uuid;
/// <summary>
/// 喵星身份編號
/// </summary>
public string id;
/// <summary>
/// 昵稱
/// </summary>
public string nickname;
/// <summary>
/// 品種
/// </summary>
public string kind;
/// <summary>
/// 毛色
/// </summary>
public string color;
/// <summary>
/// 性別,0:母,1:公
/// </summary>
public int gender;
/// <summary>
/// 出生
/// </summary>
public string birth;
/// <summary>
/// 流浪原因
/// </summary>
public string reason;
}
11.10 貓資訊管理器:CatManager
封裝一個貓資訊的管理類,CatManager,負責資料加載和增刪改查,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CatManager
{
public void Init()
{
// 從資料庫加載資料
m_datas = CatDataBase.QueryDatas();
}
/// <summary>
/// 新增或修改貓資訊
/// </summary>
/// <param name="info"></param>
public void AddOrModify(CatInfo info)
{
CatDataBase.AddOrModify(info);
// 拋出事件,更新界面
EventDispatcher.instance.DispatchEvent(EventNameDef.EVENT_ADD_OR_MODIFY_CAT, info);
}
/// <summary>
/// 洗掉貓資訊
/// </summary>
/// <param name="uuid"></param>
public void Del(string uuid)
{
CatDataBase.Del(uuid);
// 拋出事件,更新界面
EventDispatcher.instance.DispatchEvent(EventNameDef.EVENT_DEL_CAT, uuid);
}
public Dictionary<string, CatInfo> data
{
get { return m_datas; }
}
/// <summary>
/// 貓資訊資料快取
/// </summary>
private Dictionary<string, CatInfo> m_datas = null;
/// <summary>
/// 單例模式
/// </summary>
private static CatManager s_instance;
public static CatManager Instance
{
get
{
if (null == s_instance)
s_instance = new CatManager();
return s_instance;
}
}
}
11.11 資料存盤:CatDataBase
封裝一個CatDataBase類,負責資料的本地寫入和讀取,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LitJson;
using System.IO;
/// <summary>
/// 貓資料庫
/// </summary>
public class CatDataBase
{
/// <summary>
/// 新增或修改資料
/// </summary>
/// <param name="info"></param>
public static void AddOrModify(CatInfo info)
{
if (s_datas.ContainsKey(info.uuid))
{
s_datas[info.uuid] = info;
}
else
{
s_datas.Add(info.uuid, info);
}
SaveData();
}
/// <summary>
/// 刪資料
/// </summary>
/// <param name="uuid"></param>
public static void Del(string uuid)
{
if (!s_datas.ContainsKey(uuid)) return;
s_datas.Remove(uuid);
SaveData();
}
/// <summary>
/// 查詢所有貓資訊
/// </summary>
/// <returns></returns>
public static Dictionary<string, CatInfo> QueryDatas()
{
string jsonStr = PlayerPrefs.GetString("cats", null);
if (string.IsNullOrEmpty(jsonStr))
{
s_datas = new Dictionary<string, CatInfo>();
}
else
{
s_datas = JsonMapper.ToObject<Dictionary<string, CatInfo>>(jsonStr);
}
return s_datas;
}
/// <summary>
/// 使用PlayerPrefs將資料寫入本地
/// </summary>
public static void SaveData()
{
string jsonStr = JsonMapper.ToJson(s_datas);
PlayerPrefs.SetString("cats", jsonStr);
}
private static Dictionary<string, CatInfo> s_datas = new Dictionary<string, CatInfo>();
}
其中寫入本地資料用到了Unity提供的PlayerPrefs類,
讀取資料介面
public static string GetString(string key, string defaultValue);
寫入資料介面
public static void SetString(string key, string value);
11.12 Json庫:LitJson
需要將資料序列號到本地檔案中,采用Json的格式,所以需要匯入一個Json庫,從GitHub下載LitJson原始碼:
https://github.com/LitJSON/litjson/releases/tag/0.15.0

下載后將原始碼匯入到工程中,

使用時引入命名空間,
using LitJson;
主要用到JsonMapper的兩個介面,
object轉json字串介面
public static string ToJson (object obj)
json字串轉object介面
public static T ToObject<T> (string json)
11.13 觀察者模式
資料更新的時候要更新ui的顯示,這里采用觀察者模式,ui界面的代碼監聽事件,資料變化時拋出事件,從而實作ui的顯示重繪,
封裝一個事件訂閱和發送的類:EventDispatcher,
using UnityEngine;
using System.Collections.Generic;
public delegate void MyEventHandler(params object[] objs);
public class EventDispatcher
{
/// <summary>
/// 注冊事件的回應函式
/// </summary>
/// <param name="type"></param>
/// <param name="handler"></param>
public void Regist(string type, MyEventHandler handler)
{
if (handler == null)
return;
if (!listeners.ContainsKey(type))
{
listeners.Add(type, new Dictionary<int, MyEventHandler>());
}
var handlerDic = listeners[type];
var handlerHash = handler.GetHashCode();
if (handlerDic.ContainsKey(handlerHash))
{
handlerDic.Remove(handlerHash);
}
listeners[type].Add(handler.GetHashCode(), handler);
}
/// <summary>
/// 注銷事件的回應函式
/// </summary>
/// <param name="type"></param>
/// <param name="handler"></param>
public void UnRegist(string type, MyEventHandler handler)
{
if (handler == null)
return;
if (listeners.ContainsKey(type))
{
listeners[type].Remove(handler.GetHashCode());
if (null == listeners[type] || 0 == listeners[type].Count)
{
listeners.Remove(type);
}
}
}
/// <summary>
/// 拋出事件,觸發之前注冊過的回應函式
/// </summary>
/// <param name="evt"></param>
/// <param name="objs"></param>
public void DispatchEvent(string evt, params object[] objs)
{
if (listeners.ContainsKey(evt))
{
var handlerDic = listeners[evt];
if (handlerDic != null && 0 < handlerDic.Count)
{
var dic = new Dictionary<int, MyEventHandler>(handlerDic);
foreach (var f in dic.Values)
{
try
{
f(objs);
}
catch (System.Exception ex)
{
Debug.LogErrorFormat(szErrorMessage, evt, ex.Message, ex.StackTrace);
}
}
}
}
}
/// <summary>
/// 清理事件
/// </summary>
/// <param name="key"></param>
public void ClearEvents(string key)
{
if (listeners.ContainsKey(key))
{
listeners.Remove(key);
}
}
/// <summary>
/// 事件監聽快取
/// </summary>
private Dictionary<string, Dictionary<int, MyEventHandler>> listeners = new Dictionary<string, Dictionary<int, MyEventHandler>>();
private readonly string szErrorMessage = "DispatchEvent Error, Event:{0}, Error:{1}, {2}";
/// <summary>
/// 單例模式
/// </summary>
private static EventDispatcher s_instance;
public static EventDispatcher instance
{
get
{
if (null == s_instance)
s_instance = new EventDispatcher();
return s_instance;
}
}
}
定義事件
public class EventNameDef
{
/// <summary>
/// 新增或修改一只貓的資訊
/// </summary>
public const string EVENT_ADD_OR_MODIFY_CAT = "EVENT_ADD_OR_MODIFY_CAT";
/// <summary>
/// 洗掉一只貓的資訊
/// </summary>
public const string EVENT_DEL_CAT = "EVENT_DEL_CAT";
}
11.14 登錄界面代碼:LoginPanel
登錄界面代碼LoginPanel,掛在LoginPanel.prefab上,
簡單判斷下賬號和密碼,如果賬號為admin且密碼為123456則進入大廳界面,
(實際開發需要有賬號注冊,與服務器通信才能完成登錄,這里只是演示效果),
using UnityEngine;
using UnityEngine.UI;
public class LoginPanel : MonoBehaviour
{
public InputField nameInput;
public InputField pwdInput;
public Button loginBtn;
void Start()
{
loginBtn.onClick.AddListener(() =>
{
if ("admin" == nameInput.text && "123456" == pwdInput.text)
{
Destroy(gameObject);
UIManager.Instance.ShowPanel(PanelName.PLAZA_PANEL);
}
});
}
}
系結ui物件

11.15 大廳界面代碼:PlazaPanel
大廳界面代碼PlazaPanel,掛在PlazaPanel.prefab上,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlazaPanel : MonoBehaviour
{
public Button logoutBtn;
public Button signBtn;
public GameObject catItemObj;
private Transform listRoot;
void Awake()
{
// 注冊事件
EventDispatcher.instance.Regist(EventNameDef.EVENT_ADD_OR_MODIFY_CAT, OnEventAddOrModifyCat);
EventDispatcher.instance.Regist(EventNameDef.EVENT_DEL_CAT, OnEventDelCat);
CatManager.Instance.Init();
catItemObj.SetActive(false);
listRoot = catItemObj.transform.parent;
}
void Start()
{
// 退出登錄
logoutBtn.onClick.AddListener(() =>
{
Destroy(gameObject);
UIManager.Instance.ShowPanel(PanelName.LOGIN_PANEL);
});
// 登記新資訊
signBtn.onClick.AddListener(() =>
{
UIManager.Instance.ShowPanel(PanelName.INFO_PANEL);
});
// 遍歷資料,創建串列
foreach (CatInfo catInfo in CatManager.Instance.data.Values)
{
CreateItem(catInfo);
}
}
/// <summary>
/// 創建資訊串列的一行ui
/// </summary>
/// <param name="info"></param>
void CreateItem(CatInfo info)
{
var obj = Instantiate(catItemObj);
obj.SetActive(true);
obj.transform.SetParent(listRoot, false);
var itemUi = obj.GetComponent<CatListItem>();
// 使用資料更新ui
itemUi.UpdateUi(info);
// 快取,方便后面更新ui
m_catUiList[info.uuid] = itemUi;
}
/// <summary>
/// 資料發生變化,更新ui
/// </summary>
/// <param name="args"></param>
void OnEventAddOrModifyCat(params object[] args)
{
var info = args[0] as CatInfo;
if (m_catUiList.ContainsKey(info.uuid))
{
m_catUiList[info.uuid].UpdateUi(info);
}
else
{
// 創建多一行
CreateItem(info);
}
}
/// <summary>
/// 資訊被洗掉,洗掉對應的ui
/// </summary>
/// <param name="args"></param>
void OnEventDelCat(params object[] args)
{
var uuid = (string)args[0];
if (m_catUiList.ContainsKey(uuid))
{
var ui = m_catUiList[uuid];
if(null != ui)
{
Destroy(ui.gameObject);
}
m_catUiList.Remove(uuid);
}
}
/// <summary>
/// 界面被銷毀
/// </summary>
private void OnDestroy()
{
// 注銷事件
EventDispatcher.instance.UnRegist(EventNameDef.EVENT_ADD_OR_MODIFY_CAT, OnEventAddOrModifyCat);
EventDispatcher.instance.UnRegist(EventNameDef.EVENT_DEL_CAT, OnEventDelCat);
}
private Dictionary<string, CatListItem> m_catUiList = new Dictionary<string, CatListItem>();
}
系結PlazaPanel組件的ui物件,

其中,串列的行ui單獨封裝成一個組件CatListItem,掛在Item節點上,
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 串列的一行ui
/// </summary>
public class CatListItem : MonoBehaviour
{
public Text idText;
public Text nameText;
public Text kindText;
public Text colorText;
public Text genderText;
public Text birthText;
public Text resonText;
public Button itemBtn;
public void Start()
{
// 串列的行被點擊,打開資訊界面
itemBtn.onClick.AddListener(() =>
{
var panelObj = UIManager.Instance.ShowPanel(PanelName.INFO_PANEL);
var infoPanel = panelObj.GetComponent<InfoPanel>();
infoPanel.Init(m_info);
});
}
/// <summary>
/// 更新ui
/// </summary>
/// <param name="info"></param>
public void UpdateUi(CatInfo info)
{
m_info = info;
idText.text = info.id;
nameText.text = info.nickname;
kindText.text = info.kind;
colorText.text = info.color;
genderText.text = 0 == info.gender ? "母" : "公";
birthText.text = info.birth;
resonText.text = info.reason;
}
private CatInfo m_info;
}
系結CatListItem組件的ui物件,

11.16 資訊界面代碼:InfoPanel
資訊界面代碼InfoPanel,掛在InfoPanel.prefab上,
using UnityEngine;
using UnityEngine.UI;
public class InfoPanel : MonoBehaviour
{
public InputField idInput;
public InputField kindInput;
public InputField nameInput;
public InputField colorInput;
public Dropdown genderDropdown;
public InputField birthInput;
public InputField reasonInput;
public Button okBtn;
public Button delBtn;
public Button closeBtn;
public CatInfo m_catInfo;
public void Init(CatInfo info)
{
m_catInfo = info;
idInput.text = info.id;
kindInput.text = info.kind;
nameInput.text = info.nickname;
colorInput.text = info.color;
genderDropdown.value = info.gender;
birthInput.text = info.birth;
reasonInput.text = info.reason;
}
private CatInfo MakeCatInfo()
{
if (null == m_catInfo)
m_catInfo = new CatInfo();
m_catInfo.id = idInput.text;
m_catInfo.kind = kindInput.text;
m_catInfo.nickname = nameInput.text;
m_catInfo.color = colorInput.text;
m_catInfo.gender = genderDropdown.value;
m_catInfo.birth = birthInput.text;
m_catInfo.reason = reasonInput.text;
return m_catInfo;
}
void Start()
{
okBtn.onClick.AddListener(() =>
{
// 新增或修改
CatManager.Instance.AddOrModify(MakeCatInfo());
Destroy(gameObject);
});
delBtn.onClick.AddListener(() =>
{
// 洗掉
if(null != m_catInfo)
{
CatManager.Instance.Del(m_catInfo.uuid);
}
Destroy(gameObject);
});
closeBtn.onClick.AddListener(() =>
{
Destroy(gameObject);
});
}
}
系結ui物件,

完成,
如果有任何疑問歡迎留言或私信,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/229955.html
標籤:其他
上一篇:關于go并發的實體及理解
