unity網路實戰開發(叢林戰爭)-正式開發階段(015-遊戲場景及開始介面UI搭建)
使用工具:VS2017,unity3d
使用語言:c#
作者:Gemini_xujian
參考:siki老師-《叢林戰爭》視訊教程
上一篇文章中,我已經完成了遊戲客戶端與伺服器端的初步連線,接下來將開始進行遊戲場景與開始介面UI的搭建。
01-控制場景的視野漫遊動畫作為選單介面背景
首先,需要將資源包中的一個scene場景作為遊戲的主場景,這裡,提供一下資源的下載地址(https://download.csdn.net/download/gemini_xujian/10465872),如果有需要的同學可以下載一下去使用。
接下來開始製作漫遊動畫。選中主攝像機,點選Windows選單下面的animation選項,點選中間的create按鈕,將animation檔案儲存在新建的animations目錄下,命名為CameraWander,如圖所示:
然後在animation編輯器中新增需要變化的屬性,這裡我們只需要修改position和rotation即可,如圖:
新增完成之後是這樣子的:
然後按照自己的想法修改位置和旋轉,我在這裡讓攝像機圍繞場景旋轉一週回到起點,並調節幀率為4。如圖:
這樣就實現了開場動畫的製作,附畫面截圖:
02-開發登入按鈕
首先在Hierarchy檢視下右鍵UI->Image與Text,修改image名字為startpanel並將錨點設定為全屏四角,再建立好text,將text做為startpanel的子物體,調整字型大小以及位置,並將字型選擇為自己喜歡的一種字型,這裡我是用資源提供的方正胖娃字型,調整好後,為字型新增shadow元件,使字型看起來更有立體感,然後為字型新增一個button元件,並將元件下的Transition選擇為Animation,點選下面的Auto Generate Animation按鈕,會彈出animation檔案儲存位置,我放在了animations資料夾下,並改名為button,然後開啟animation編輯器,新增變化屬性rect transform裡面的scale,在中間位置將scale的x和y改為1.2,儲存並檢視效果,這樣就完成了登入按鈕的製作。如圖:
03-設計登入面板UI
右鍵canvas,選擇UI->image,作為登入面板的背景,然後將輸入框以及按鈕等元件做為其子物體,完成效果如圖所示:
目前的UI層級為:
04-開發註冊面板及提示資訊面板
直接複製loginpanel修改成registerpanel,然後再搭建一個提示面板,效果如圖:
UI面板層級結構如圖:
05-建立面板指令碼
將我們之前搭建好的UI框架中的base資料夾拖拽到scripts目錄下,改名為uipanel,然後我們給每一個面板都建立一個指令碼,命名方式與每個面板名稱相同,建立好後,將這些指令碼都繼承自basepanel這個類,實現效果如圖:
每個指令碼繼承自basepanel(以startpanel為例):
06-建立面板的prefab並修改json和paneltype
將所有的UI面板做成prefab並放入resources目錄的uipanel資料夾下,在UIFramework/UIPanel資料夾下找到UIPanelType,然後刪除原來的列舉值,新增上我們剛才建立的幾個面板的列舉值,分別是Start,Message,Login,Register,然後修改json檔案,json檔案位於UIFramework/Resources目錄下,按照原來的命名方式進行修改,修改後的程式碼如下:
UIPanelType.json:
{
"infoList":
[
{"panelTypeString":"Message",
"path":"UIPanel/MessagePanel"},
{"panelTypeString":"Start",
"path":"UIPanel/StartPanel"},
{"panelTypeString":"Login",
"path":"UIPanel/LoginPanel"},
{"panelTypeString":"Register",
"path":"UIPanel/RegisterPanel"}
]
}
UIPanelType.cs:
using UnityEngine;
using System.Collections;
using System;
public enum UIPanelType {
Message,
Start,
Login,
Register,
}
07-開發提示資訊模組
先上程式碼:
MessagePanel.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class MessagePanel : BasePanel
{
private Text text;
private float showTime=1f;
public override void OnEnter()
{
base.OnEnter();
text = GetComponent<Text>();
text.enabled = false;
uiMng.InjectMsgPanel(this);
}
public override void OnExit()
{
base.OnExit();
}
public override void OnPause()
{
base.OnPause();
}
public override void OnResume()
{
base.OnResume();
}
public void ShowMessage(string msg)
{
text.CrossFadeAlpha(1,0.2f,true);
text.text = msg;
text.enabled = true;
Invoke("Hide", showTime);
}
private void Hide()
{
text.CrossFadeAlpha(0, showTime, true);
}
}
UIManager.cs:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class UIManager:BaseManager {
///
/// 單例模式的核心
/// 1,定義一個靜態的物件 在外界訪問 在內部構造
/// 2,構造方法私有化
//private static UIManager _instance;
//public static UIManager Instance
//{
// get
// {
// if (_instance == null)
// {
// _instance = new UIManager();
// }
// return _instance;
// }
//}
private Transform canvasTransform;
private Transform CanvasTransform
{
get
{
if (canvasTransform == null)
{
canvasTransform = GameObject.Find("Canvas").transform;
}
return canvasTransform;
}
}
private Dictionary<UIPanelType, string> panelPathDict;//儲存所有面板Prefab的路徑
private Dictionary<UIPanelType, BasePanel> panelDict;//儲存所有例項化面板的遊戲物體身上的BasePanel元件
private Stack<BasePanel> panelStack;
private MessagePanel msgPanel;
public UIManager(GameFacade facade) : base(facade)
{
ParseUIPanelTypeJson();
}
/// <summary>
/// 把某個頁面入棧, 把某個頁面顯示在介面上
/// </summary>
public void PushPanel(UIPanelType panelType)
{
if (panelStack == null)
panelStack = new Stack<BasePanel>();
//判斷一下棧裡面是否有頁面
if (panelStack.Count > 0)
{
BasePanel topPanel = panelStack.Peek();
topPanel.OnPause();
}
BasePanel panel = GetPanel(panelType);
panel.OnEnter();
panelStack.Push(panel);
}
/// <summary>
/// 出棧 ,把頁面從介面上移除
/// </summary>
public void PopPanel()
{
if (panelStack == null)
panelStack = new Stack<BasePanel>();
if (panelStack.Count <= 0) return;
//關閉棧頂頁面的顯示
BasePanel topPanel = panelStack.Pop();
topPanel.OnExit();
if (panelStack.Count <= 0) return;
BasePanel topPanel2 = panelStack.Peek();
topPanel2.OnResume();
}
/// <summary>
/// 根據面板型別 得到例項化的面板
/// </summary>
/// <returns></returns>
private BasePanel GetPanel(UIPanelType panelType)
{
if (panelDict == null)
{
panelDict = new Dictionary<UIPanelType, BasePanel>();
}
//BasePanel panel;
//panelDict.TryGetValue(panelType, out panel);//TODO
BasePanel panel = panelDict.TryGet(panelType);
if (panel == null)
{
//如果找不到,那麼就找這個面板的prefab的路徑,然後去根據prefab去例項化面板
//string path;
//panelPathDict.TryGetValue(panelType, out path);
string path = panelPathDict.TryGet(panelType);
GameObject instPanel = GameObject.Instantiate(Resources.Load(path)) as GameObject;
instPanel.transform.SetParent(CanvasTransform,false);
instPanel.GetComponent<BasePanel>().UIMng = this;
panelDict.Add(panelType, instPanel.GetComponent<BasePanel>());
return instPanel.GetComponent<BasePanel>();
}
else
{
return panel;
}
}
[Serializable]
class UIPanelTypeJson
{
public List<UIPanelInfo> infoList;
}
private void ParseUIPanelTypeJson()
{
panelPathDict = new Dictionary<UIPanelType, string>();
TextAsset ta = Resources.Load<TextAsset>("UIPanelType");
UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);
foreach (UIPanelInfo info in jsonObject.infoList)
{
//Debug.Log(info.panelType);
panelPathDict.Add(info.panelType, info.path);
}
}
public void InjectMsgPanel(MessagePanel msgPanel)
{
this.msgPanel = msgPanel;
}
public void ShowMessage(string msg)
{
if (msg == null)
{
Debug.Log("無法顯示提示資訊,msgpanel為空");
return;
}
msgPanel.ShowMessage(msg);
}
/// <summary>
/// just for test
/// </summary>
//public void Test()
//{
// string path ;
// panelPathDict.TryGetValue(UIPanelType.Knapsack,out path);
// Debug.Log(path);
//}
}
BasePanel.cs:
using UnityEngine;
using System.Collections;
public class BasePanel : MonoBehaviour {
protected UIManager uiMng;
public UIManager UIMng
{
set
{
uiMng = value;
}
}
/// <summary>
/// 介面被顯示出來
/// </summary>
public virtual void OnEnter()
{
}
/// <summary>
/// 介面暫停
/// </summary>
public virtual void OnPause()
{
}
/// <summary>
/// 介面繼續
/// </summary>
public virtual void OnResume()
{
}
/// <summary>
/// 介面不顯示,退出這個介面,介面被關係
/// </summary>
public virtual void OnExit()
{
}
}
GameFacade.cs:
using Common;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameFacade : MonoBehaviour {
private static GameFacade _instance;
public static GameFacade Instance
{
get
{
return _instance;
}
}
private UIManager uiMng;
private AudioManager audioMng;
private PlayerManager playerMng;
private RequestManager requestMng;
private CameraManager cameraMng;
private ClientManager clientMng;
private void Awake()
{
if (_instance != null)
{
Destroy(this.gameObject);
return;
}
_instance = this;
}
// Use this for initialization
void Start() {
InitManager();
}
// Update is called once per frame
void Update() {
}
private void InitManager()
{
uiMng = new UIManager(this);
audioMng = new AudioManager(this);
playerMng = new PlayerManager(this);
requestMng = new RequestManager(this);
cameraMng = new CameraManager(this);
clientMng = new ClientManager(this);
uiMng.OnInit();
audioMng.OnInit();
playerMng.OnInit();
requestMng.OnInit();
cameraMng.OnInit();
clientMng.OnInit();
}
private void DestroyManager()
{
uiMng.OnDestory();
audioMng.OnDestory();
playerMng.OnDestory();
requestMng.OnDestory();
cameraMng.OnDestory();
clientMng.OnDestory();
}
private void OnDestroy()
{
DestroyManager();
}
public void AddRequest(ActionCode actionCode, BaseRequest request)
{
requestMng.AddRequest(actionCode, request);
}
public void RemoveRequest(ActionCode actionCode)
{
requestMng.RemoveRequest(actionCode);
}
public void HandleResponse(ActionCode actionCode, string data)
{
requestMng.HandleResponse(actionCode, data);
}
public void ShowMessage(string msg)
{
uiMng.ShowMessage(msg);
}
}
說明:首先,我們對messagepanel進行實現,通過showmessage方法來顯示提示資訊,在showmessage中呼叫invoke方法,來呼叫hide方法,invoke方法的兩個引數分別表示將要呼叫的方法名以及多長時間後呼叫,crossfadealpha的三個引數分別表示目標的透明度值,過渡完成的時間長短以及是否忽略時間的大小快慢。之後,我們想要讓其他面板可以呼叫showmsaage方法,那麼,我們可以在basepanel中得到uimanager,通過uimanager這個類來排程所有的UI面板對外的方法,我們在uimanager呼叫messagepanel中的方法之前,需要先得到messagepanel的例項,這裡通過messagepanel面板呼叫顯示資訊方法時將自身傳遞給uimanager,這樣我們就可以方便的得到messagepanel例項並使用他的方法,除了在UI面板中呼叫外,我們還想要在其他的模組中也可以呼叫顯示提示資訊的方法,那麼,我們就可以將gamefacade類作為中介,用它來完成對messagepanel中showmessage方法的呼叫。
08-開發開始介面和麵板進入的動畫
在使用dotween動畫之前,需要先進行初始化,初始化的方法可以通過使用dotween提供的視覺化介面進行初始化,在工具欄有會有一個tools選單欄選項,這個選項是在匯入dotween後出現的,我們點選Tools->demigiant->dotween utility panel選項,會彈出來一個面板,點選面板中的setup dotween按鈕。這樣就完成了dotween外掛初始化工作。
先上修改的程式碼:
StartPanel.cs:
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class StartPanel : BasePanel {
private Button loginbtn;
private Animator btnAnimator;
private void Start()
{
loginbtn = transform.Find("loginbtn").GetComponent<Button>();
loginbtn.onClick.AddListener(OnLoginClick);
btnAnimator = transform.Find("loginbtn").GetComponent<Animator>();
}
public override void OnEnter()
{
base.OnEnter();
if (loginbtn == null)
{
loginbtn = transform.Find("loginbtn").GetComponent<Button>();
loginbtn.onClick.AddListener(OnLoginClick);
}
if(btnAnimator==null)
btnAnimator = transform.Find("loginbtn").GetComponent<Animator>();
}
public override void OnExit()
{
base.OnExit();
}
public override void OnPause()
{
base.OnPause();
btnAnimator.enabled = false;
loginbtn.transform.DOScale(0, 0.4f).OnComplete(() => loginbtn.gameObject.SetActive(false));
}
public override void OnResume()
{
base.OnResume();
loginbtn.gameObject.SetActive(true);
loginbtn.transform.DOScale(1, 0.4f).OnComplete(()=> btnAnimator.enabled = true);
}
public void OnLoginClick()
{
uiMng.PushPanel(UIPanelType.Login);
}
}
LoginPanel.cs:
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LoginPanel : BasePanel
{
private Button closebtn;
private void Start()
{
closebtn = transform.Find("closebtn").GetComponent<Button>();
closebtn.onClick.AddListener(OnCloseClick);
}
public override void OnEnter()
{
base.OnEnter();
gameObject.SetActive(true);
if (closebtn == null)
{
closebtn = transform.Find("closebtn").GetComponent<Button>();
closebtn.onClick.AddListener(OnCloseClick);
}
transform.localScale = Vector3.zero;
transform.localPosition = new Vector3(800,0,0);
transform.DOScale(1, 0.4f);
transform.DOLocalMove(Vector3.zero, 0.4f);
}
public override void OnExit()
{
base.OnExit();
gameObject.SetActive(false);
}
public override void OnPause()
{
base.OnPause();
}
public override void OnResume()
{
base.OnResume();
}
public void OnCloseClick()
{
transform.DOScale(0, 0.4f);
transform.DOLocalMove(new Vector3(800,0,0), 0.4f).OnComplete(()=> { uiMng.PopPanel(); });
}
}
說明:當我們點選開始面板的登入按鈕的時候,需要顯示出來下一個面板並將當前的面板隱藏,因為我們繼承了basepanel,所以我們可以通過定義的四種面板狀態進行一些動畫的接入,動畫效果的實現是由dotween實現的,我們在得到一些物體或者元件時,需要同時在start方法以及enter方法中得到,要注意的是,在enter中得到物體或者元件時需要判斷是否已經得到了,尤其是對UI元件(例如按鈕)註冊事件時為了防止重複,防止重複的原因是多次重複可能會導致事件執行多次,例如點選按鈕時重複註冊事件會導致事件中的方法多次執行,可能會發生不可預料的錯誤。
相關推薦
unity網路實戰開發(叢林戰爭)-正式開發階段(015-遊戲場景及開始介面UI搭建)
使用工具:VS2017,unity3d使用語言:c#作者:Gemini_xujian參考:siki老師-《叢林戰爭》視訊教程上一篇文章中,我已經完成了遊戲客戶端與伺服器端的初步連線,接下來將開始進行遊戲場景與開始介面UI的搭建。01-控制場景的視野漫遊動畫作為選單介面背景首先
unity網路實戰開發(叢林戰爭)-前期知識準備(003-開發伺服器端的傳送資料和接收資料)
使用工具:VS2015使用語言:c#作者:Gemini_xujian參考:siki老師-《叢林戰爭》視訊教程繼上一篇文章內容,這節課講解一下伺服器端的傳送資料和接收資料。上篇文章完成了ip和埠號的繫結,接下來,我們首先需要監聽埠並接收客戶端的連線serverSocket.Li
unity網路實戰開發(叢林戰爭)-前期知識準備(011-c#連線資料庫並實現增刪改查以及sql注入問題)
使用工具:VS2015,Mysql使用語言:c#作者:Gemini_xujian參考:siki老師-《叢林戰爭》視訊教程繼上一篇文章內容,這節課講解一下資料庫的前期連線準備以及通過c# 實現資料庫的增刪改擦操作。首先你需要自行安裝Mysql以及它的workbench元件。然後
unity網路實戰開發(叢林戰爭)-正式開發階段(018-聲音管理器模組的完善)
使用工具:VS2017,unity3d 使用語言:c# 作者:Gemini_xujian 參考:siki老師-《叢林戰爭》視訊教程 上一篇文章中,已經完成了註冊事件的處理,接下來將完善聲音管理器模組。 01-開發聲音管理器 為了使遊戲執行起來更加富有活力,接下來,
unity網路實戰開發(叢林戰爭)-正式開發階段(016-資料庫設計以及登入處理)
使用工具:VS2017,unity3d使用語言:c#作者:Gemini_xujian參考:siki老師-《叢林戰爭》視訊教程上一篇文章中,已經完成了遊戲場景與開始介面UI的搭建,接下來將對資料庫和登入請求響應等操作進行處理。01-設計資料庫表(使用者表和戰績表)首先,我們需要
unity網路實戰開發(叢林戰爭)-正式開發階段(013-遊戲伺服器端框架搭建)
使用工具:VS2015使用語言:c#作者:Gemini_xujian參考:siki老師-《叢林戰爭》視訊教程繼上一篇文章內容,這節課講解一下游戲伺服器端的開發。01-專案目錄結構建立:首先開啟VS並建立一個c#控制檯應用程式專案,起名為“遊戲伺服器端”,建立好後,右鍵專案-&
資料庫操作之增加資料(叢林戰爭專案)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MySql.Data.MyS
遊戲開發,叢林戰爭3
34.訊息面板的顯示 首先的話,我們建立我們的MessagePanel指令碼,這裡我們提供了建立,顯示,隱藏三個方法,並且的話我們這個面板指令碼的控制是交給Uimanager進行管理的 publicclassMessagePanel : BasePanel { pr
Node教程——API介面開發(Node版的CRUD通用介面的搭建)(MangoDB+Express_Version2)
# 1. 概述 > 時間跨度有點大,之前就跟大家嘮嗑過一些知識點,也開啟了一個Node書寫一個後臺api專案的開始,出於各種原因,遲遲沒有更新博文。現在我把這個坑填上,如果你還有閱讀過我之前的文章,我建議你先閱讀一下 *博文地址https://www.cnblogs.com/BM-laoli/p/12708
負載均衡(集群介紹,lvs介紹,LVS調度算法,NAT模式搭建)
bottom table all lvs dr 有一個 gen 輪詢 chang 定向 一、負載均衡集群介紹負載均衡集群:簡單地說就是讓多臺服務器均衡地去承載壓力。實現負載均衡的開源軟件有:LVS,keepalived,haproxy,nginx等其中相對於(網絡OSI七層
CF1007D. Ants(樹鏈剖分+線段樹+2-SAT及字首優化建圖)
題目連結 https://codeforces.com/problemset/problem/1007/D 題解 由於問題的本質是給定許多二元集合,判斷是否能從每一個二元集合中選出一個元素,使得所有選出的元素合法,因此考慮使用 2-SAT 解決該問題。 不難發現,使用 2-SAT 解決該問題的複雜度瓶
VS2010/MFC入門程式設計十七(多執行緒的建立,包括工作執行緒和使用者介面執行緒)
1.MFC多執行緒簡介 MFC對多執行緒進行了一層簡單的封裝,在Visual C++中每個執行緒都是從CWinThread類繼承而來的。每一個應用程式的執行都有一個主執行緒,這個主執行緒也是從CWinThread類繼承而來的。可以利用CWinThread物件建立應用程式執行的其它執行緒。 MFC用CW
Vue從入門到精通(5)--第四階段(上):Vue入門及Vue-cli上手教程
第四階段 vue2.0語法 vue2.0+webpack搭建開發環境 官方腳手架vue-cli Vue的作者尤雨溪大神寫了一篇《新手向:Vue 2.0 的建議學習順序》來介紹Vue及相關知識點的學習路線,主要列出了知識點概要,如果你覺得略
rabbitmq系列(二)幾種常見模式的應用場景及實現
一、簡單模式 原理:生產者將訊息交給預設的交換機,交換機獲取訊息後交給繫結這個生產者的佇列(投遞規則為佇列名稱和routing key 相同的佇列),監聽當前佇列的消費者獲取資訊並執行消費邏輯。 場景:有一個oa系統,使用者通過接收手機驗證碼進行註冊,頁面上點選獲取驗證碼後,將驗證碼放到訊息佇列,然後簡訊
【微信小遊戲實戰】零基礎製作《歡樂停車場》三、遊戲場景製作
1、遊戲立項 微信小遊戲中有一款《歡樂停車場Plus》的小遊戲,大家可以搜尋玩下。這是一款益智類的小遊戲,遊戲中有紅、黃、綠、藍、紫5輛豪車6個停車位,玩家通過可行走路線移動小車,最終讓各顏色的小車停到對應的顏色車位,則完成本關挑戰。接下來的日子,我將同大家一步一步的來實現這款小遊戲,從零基礎入門微信小遊戲
網路遊戲《叢林戰爭》開發與學習之(二):粘包分包現象以及服務端解析資料
1. 粘包和分包 粘包和分包是利用Socket在TCP協議下內部的優化機制。粘包指的是傳送資料比較頻繁,但資料量較少,此時客戶端不會直接將資料包傳送給伺服器,而是會與其它的資料包進行一個結合,例如遊戲中的位置資訊就是屬於頻繁傳送但資料量小的資訊,此時如果每條資料都S
網路遊戲《叢林戰爭》開發與學習之(一):網路程式設計的基礎知識
《叢林戰爭》是一款完整的網路遊戲案例,運用U3D開發客戶端,Socket開發服務端,其中涉及到了網路程式設計、資料庫和Unity的功能實現,之前通過U3D開發了一個單機遊戲《黑暗之光》,並沒有涉及網路程式設計的知識,通過《叢林戰爭》這個完整的遊戲,系統性地學習網路程式設計,並
DDD實戰進階第一波(五):開發一般業務的大健康行業直銷系統(實現產品上下文領域層)
討論 clas 基本 ted ctc decimal nco protect pan 從這篇文章開始,我們根據前面的DDD理論與DDD框架的約束,正式進入直銷系統案例的開發。 本篇文章主要講產品上下文中的領域層的主要實現,先簡單講下業務方面的需求:產品SPU與產品SKU,產
Flask框架的學習與實戰(一):開發環境搭建
進行 read 模型 clas tar pychar html itl .html Flask是一個使用 Python 編寫的輕量級 Web 應用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎則使用 Jinja2。很多功能的實現都參考了django框架。由於項
海康威視網路攝像機 SDK二次開發(JAVA)(1-開發環境搭建)
硬體環境 相關的硬體環境準備:攝像機型號:DS-2CD2T25FD-I3,按照說明書搭建好硬體環境 SDK下載 開發工具:IDEA20173.3 , JDK: 9 官網SDK地址:http://www.hikvision.com/cn/download_61.html