300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > unity网络实战开发(丛林战争)-正式开发阶段(015-游戏场景及开始界面UI搭建)

unity网络实战开发(丛林战争)-正式开发阶段(015-游戏场景及开始界面UI搭建)

时间:2020-06-17 15:29:32

相关推荐

unity网络实战开发(丛林战争)-正式开发阶段(015-游戏场景及开始界面UI搭建)

使用工具:VS,unity3d

使用语言:c#

作者:Gemini_xujian

参考:siki老师-《丛林战争》视频教程

上一篇文章中,我已经完成了游戏客户端与服务器端的初步连接,接下来将开始进行游戏场景与开始界面UI的搭建。

01-控制场景的视野漫游动画作为菜单界面背景

首先,需要将资源包中的一个scene场景作为游戏的主场景,这里,提供一下资源的下载地址(/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);//TODOBasePanel 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 initializationvoid Start() {InitManager();}// Update is called once per framevoid 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组件(例如按钮)注册事件时为了防止重复,防止重复的原因是多次重复可能会导致事件执行多次,例如点击按钮时重复注册事件会导致事件中的方法多次执行,可能会发生不可预料的错误。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。