Unity3D优化技巧系列五
Posted 海洋_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity3D优化技巧系列五相关的知识,希望对你有一定的参考价值。
笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。
CSDN视频网址:http://edu.csdn.net/lecturer/144
架构设计也是优化的一种,一款游戏如果没有一个好的架构,程序出现问题很难做到及时的响应,读者可以试想一下,如果编程的时候只是为了实现功能而实现功能,到头来就是代码越写越乱,各种功能交织在一起。出现问题后到处找BUG修复,优化就更无从谈起了,谁也不希望把即将上线的项目代码,重新重构一遍,那还不如重新再做一遍,所以架构设计在游戏开发中是非常重要的,而且是必须要掌握的技术。下面重点给读者介绍MVC和FSM架构模式,效果如下所示:
MVC架构模式在前面的优化系列中给读者提过,下面就详细的告诉读者如何编写代码?给读者详细的分析一下,拿窗口的切换进行距离,游戏运行时,首先是创立界面,我们把每个界面作为一个窗口,比如LoginWindow,HeroWindow等。它们也是作为View界面,这样游戏中就会出现很多界面的设计,效果如下所示:
下面分析界面的编写,上文提到的每个UI就是一个Window,也是一个View,这么多View肯定有自己的共性,我们可以将其定义为基类,基类称为BaseWindow,代码编写如下所示:
namespace Game.View
{
public abstract class BaseWindow
{
protected Transform mRoot;
protected EScenesType mScenesType; //场景类型
protected string mResName; //资源名
protected bool mResident; //是否常驻
protected bool mVisible = false; //是否可见
//类对象初始化
public abstract void Init();
//类对象释放
public abstract void Realse();
//窗口控制初始化
protected abstract void InitWidget();
//窗口控件释放
protected abstract void RealseWidget();
//游戏事件注册
protected abstract void OnAddListener();
//游戏事件注消
protected abstract void OnRemoveListener();
//显示初始化
public abstract void OnEnable();
//隐藏处理
public abstract void OnDisable();
//每帧更新
public virtual void Update(float deltaTime) { }
//取得所以场景类型
public EScenesType GetScenseType()
{
return mScenesType;
}
//是否已打开
public bool IsVisible() { return mVisible; }
//是否常驻
public bool IsResident() { return mResident; }
//显示
public void Show()
{
if (mRoot == null)
{
if (Create())
{
InitWidget();
}
}
if (mRoot && mRoot.gameObject.activeSelf == false)
{
mRoot.gameObject.SetActive(true);
mVisible = true;
OnEnable();
OnAddListener();
}
}
//隐藏
public void Hide()
{
if (mRoot && mRoot.gameObject.activeSelf == true)
{
OnRemoveListener();
OnDisable();
if (mResident)
{
mRoot.gameObject.SetActive(false);
}
else
{
RealseWidget();
Destroy();
}
}
mVisible = false;
}
//预加载
public void PreLoad()
{
if (mRoot == null)
{
if (Create())
{
InitWidget();
}
}
}
//延时删除
public void DelayDestory()
{
if (mRoot)
{
RealseWidget();
Destroy();
}
}
//创建窗体
private bool Create()
{
if (mRoot)
{
Debug.LogError("Window Create Error Exist!");
return false;
}
if (mResName == null || mResName == "")
{
Debug.LogError("Window Create Error ResName is empty!");
return false;
}
if (GameMethod.GetUiCamera.transform== null)
{
Debug.LogError("Window Create Error GetUiCamera is empty! WindowName = " + mResName);
return false;
}
GameObject obj = LoadUiResource.LoadRes(GameMethod.GetUiCamera.transform, mResName);
if (obj == null)
{
Debug.LogError("Window Create Error LoadRes WindowName = " + mResName);
return false;
}
mRoot = obj.transform;
mRoot.gameObject.SetActive(false);
return true;
}
//销毁窗体
protected void Destroy()
{
if (mRoot)
{
LoadUiResource.DestroyLoad(mRoot.gameObject);
mRoot = null;
}
}
//取得根节点
public Transform GetRoot()
{
return mRoot;
}
}
}
以上是关于窗体的基类,实现了所有窗体需要创建的方法,创建窗体,销毁窗体,预加载,掩藏 等操作。实行按的具体操作类需要继承该窗体类,比如LoginWindow的写法如下所示:
namespace Game.View
{
public class LobbyWindow : BaseWindow
{
public LobbyWindow()
{
mScenesType = EScenesType.EST_Login; //场景类型
mResName = GameConstDefine.LoadGameLobbyUI; //资源名字
mResident = false; //是否常驻内存
}
继承接口/
//类对象初始化
public override void Init()
{
EventCenter.AddListener(EGameEvent.eGameEvent_LobbyEnter, Show);
EventCenter.AddListener(EGameEvent.eGameEvent_LobbyExit, Hide);
}
//类对象释放
public override void Realse()
{
EventCenter.RemoveListener(EGameEvent.eGameEvent_LobbyEnter, Show);
EventCenter.RemoveListener(EGameEvent.eGameEvent_LobbyExit, Hide);
}
//窗口控件初始化
protected override void InitWidget()
{
mHomepage = mRoot.FindChild("StartMenuManager/StartMenuBtn/Homepage").GetComponent<UIToggle>();
UIGuideCtrl.Instance.AddUiGuideEventBtn(mHomepage.gameObject);
mBattle = mRoot.FindChild("StartMenuManager/StartMenuBtn/Battle").GetComponent<UIToggle>();
mMarket = mRoot.FindChild("StartMenuManager/StartMenuBtn/Market").GetComponent<UIToggle>();
mInteraction = mRoot.FindChild("StartMenuManager/StartMenuBtn/Interaction").GetComponent<UIToggle>();
UIGuideCtrl.Instance.AddUiGuideEventBtn(mMarket.gameObject);
mDiamondText = mRoot.FindChild("Status/Diamond/Label").GetComponent<UILabel>();
mGoldText = mRoot.FindChild("Status/Gold/Label").GetComponent<UILabel>();
mSettingBtn = mRoot.FindChild("Status/Setting").GetComponent<UIButton>();
UIGuideCtrl.Instance.AddUiGuideEventBtn(mBattle.gameObject);
EventDelegate.Add(mHomepage.onChange, OnHomePageChange);
EventDelegate.Add(mBattle.onChange, OnBattleChange);
EventDelegate.Add(mMarket.onChange, OnMarketChange);
EventDelegate.Add(mInteraction.onChange, OnInteractionChange);
UIEventListener.Get(mHeadIcon.transform.parent.gameObject).onClick += InfoPersonPress;
}
private void InfoPersonPress(GameObject go)
{
GameLog.Instance.AddUIEvent(GameLog.UIEventType.UIEventType_PersonalInfo);
LobbyCtrl.Instance.AskPersonInfo();
//PresonInfoCtrl.Instance.Enter();
}
//窗口控件释放
protected override void RealseWidget()
{
}
//游戏事件注册
protected override void OnAddListener()
{
EventCenter.AddListener(EGameEvent.eGameEent_ChangeMoney, RefreshMoney);
EventCenter.AddListener<bool>(EGameEvent.eGameEvent_ReceiveLobbyMsg, NewChat);
EventCenter.AddListener(EGameEvent.eGameEvent_AddNewMailReq, NoticeNewMail);
EventCenter.AddListener(EGameEvent.eGameEvent_ChangeNickName,ChangeNickName);
EventCenter.AddListener(EGameEvent.eGameEvent_ChangeHeadID, ChangeHeadID);
EventCenter.AddListener(EGameEvent.eGameEvent_ChangeUserLevel, ChangeLevel);
}
private void ChangeHeadID()
{
mHeadIcon.spriteName = GameUserModel.Instance.GameUserHead.ToString();
}
//游戏事件注消
protected override void OnRemoveListener()
{
EventCenter.RemoveListener(EGameEvent.eGameEent_ChangeMoney, RefreshMoney);
EventCenter.RemoveListener<bool>(EGameEvent.eGameEvent_ReceiveLobbyMsg, NewChat);
EventCenter.RemoveListener(EGameEvent.eGameEvent_AddNewMailReq, NoticeNewMail);
EventCenter.RemoveListener(EGameEvent.eGameEvent_ChangeNickName, ChangeNickName);
EventCenter.RemoveListener(EGameEvent.eGameEvent_ChangeHeadID, ChangeHeadID);
EventCenter.RemoveListener(EGameEvent.eGameEvent_ChangeUserLevel, ChangeLevel);
}
//显示
public override void OnEnable()
{
}
//隐藏
public override void OnDisable()
{
}
public void ChangeUserLevel()
{
mLevel.text = GameUserModel.Instance.UserLevel.ToString();
}
//回调事件
public void OnHomePageChange()
{
//todo
mLevel.text = GameUserModel.Instance.UserLevel.ToString();
mNickName.text = GameUserModel.Instance.GameUserNick;
mHeadIcon.spriteName = GameUserModel.Instance.GameUserHead.ToString();
mGold.text = GameUserModel.Instance.mGameUserGold.ToString();
mDiamond.text = GameUserModel.Instance.mGameUserDmd.ToString();
VipSignLevel.text = "VIP "+GameUserModel.Instance.GameUserVipLevel.ToString();
int level = GameUserModel.Instance.UserLevel;
mLevel.text = level.ToString();
LevelConfigInfo leveinfo = ConfigReader.GetLevelInfo(level);
if (leveinfo != null)
{
mExp.text = GameUserModel.Instance.GameUserExp + "/" + leveinfo.LevelUpExp;
mExp.transform.parent.GetComponent<UISprite>().fillAmount = GameUserModel.Instance.GameUserExp / leveinfo.LevelUpExp;
if (level >= 29 && GameUserModel.Instance.GameUserExp >= leveinfo.LevelUpExp)
{
level = 30;
mLevel.text = level.ToString();
mExp.gameObject.SetActive(false);
mExp.transform.parent.GetComponent<UISprite>().fillAmount = 1f;
}
}
if (mHomepage.value)
{
GameLog.Instance.AddUIEvent(GameLog.UIEventType.UIEventType_HomePage);
HomePageCtrl.Instance.Enter();
}
else
{
HomePageCtrl.Instance.Exit();
}
}
public void OnBattleChange()
{
if (mBattle.value)
{
GameLog.Instance.AddUIEvent(GameLog.UIEventType.UIEventType_Battle);
BattleCtrl.Instance.Enter();
}
else
{
BattleCtrl.Instance.Exit();
}
}
public void OnMarketChange()
{
if (mMarket.value)
{
GameLog.Instance.AddUIEvent(GameLog.UIEventType.UIEventType_Market);
MarketCtrl.Instance.Enter();
}
else
{
MarketCtrl.Instance.Exit();
}
}
public void OnInteractionChange()
{
if (mInteraction.value)
{
GameLog.Instance.AddUIEvent(GameLog.UIEventType.UIEventType_Friend);
SocialCtrl.Instance.Enter();
}
else
{
SocialCtrl.Instance.Exit();
}
}
public void MailListBtn(GameObject obj)
{
mMailBtnBg.SetActive(false);
MailCtrl.Instance.Enter();
}
}
}
该类主要是实现整个UI的逻辑编写,其他的窗口编写类似。下面编写Control控制类代码的编写,示例代码如下:
public class LoginCtrl : Singleton<LoginCtrl>
{
public void Enter()
{
EventCenter.Broadcast(EGameEvent.eGameEvent_LoginEnter);
}
public void Exit()
{
EventCenter.Broadcast(EGameEvent.eGameEvent_LoginExit);
}
//登陆
public void Login(string account, string pass)
{
}
//登陆错误反馈
public void LoginError(int code)
{
}
//接收GateServer信息
public void RecvGateServerInfo(Stream stream)
{
}
//登陆失败
public void LoginFail()
{
}
//选择LoginServer
public void SelectLoginServer(int i)
{
}
//开始游戏
public void GamePlay()
{
}
}
}
控制类的主要作用是进行一些消息的传递,这也是为了解除模块之间的耦合性,该模块的主要核心是Enter函数和Exit函数。后面继续代码的编写。。。。
以上是关于Unity3D优化技巧系列五的主要内容,如果未能解决你的问题,请参考以下文章