仿LOL项目开发第六天

                              by草帽

OK,因为更新模块已经处理好了,接着开始登陆的编写。那么我们就需要状态机的管理。

所谓状态机就是在哪个状态执行那个状态的代码逻辑:

那么我们开始编写GameStateManager来管理:

我们先在DefineCommon里面定义游戏状态类型:

    /// <summary>/// 游戏状态/// </summary>public enum GameStateType{GS_Continue,//中间状态,也就是说介于两个状态转换的中间状态GS_Login,//登陆状态GS_User,//创建用户状态GS_Lobby,//大厅,类似于LOL主界面状态GS_Room,//创建房间状态GS_Hero,//选择英雄GS_Loading,//加载状态GS_Play,//对战状态GS_Over,//对战结束}

有分这么多个状态,如果还有其他状态以后再加:

然后在GameStateManager里面搞个字典缓存这些状态。这个管理方式和WindowManage十分的相似。

using UnityEngine;
using System.Collections.Generic;
using Game;
using Game.Common;
/// <summary>
/// 游戏状态管理器
/// </summary>
public class GameStateManager : Singleton<GameStateManager>
{public Dictionary<GameStateType, IGameState> m_dicGameStates;IGameState m_oCurrentState;public IGameState CurrentState {get { return this.m_oCurrentState; }}public GameStateManager(){m_dicGameStates = new Dictionary<GameStateType, IGameState>();m_dicGameStates.Add(GameStateType.GS_Login, new LoginState());}/// <summary>/// 改变游戏状态/// </summary>/// <param name="stateType"></param>public void ChangeGameStateTo(GameStateType stateType){if (m_oCurrentState != null && m_oCurrentState.GetStateType() != GameStateType.GS_Loading && m_oCurrentState.GetStateType() == stateType)return;if (m_dicGameStates.ContainsKey(stateType)){if (m_oCurrentState != null){m_oCurrentState.Exit();//先退出上个状态}m_oCurrentState = m_dicGameStates[stateType];m_oCurrentState.Enter();//进入这个状态}}/// <summary>/// 进入默认状态,默认为登陆状态/// </summary>public void EnterDefaultState(){ChangeGameStateTo(GameStateType.GS_Login);}public void FixedUpdate(float fixedDeltaTime){if (m_oCurrentState != null){m_oCurrentState.FixedUpdate(fixedDeltaTime);}}public void Update(float fDeltaTime){GameStateType nextStateType = GameStateType.GS_Continue;if (m_oCurrentState != null){nextStateType = m_oCurrentState.Update(fDeltaTime);}if (nextStateType > GameStateType.GS_Continue){ChangeGameStateTo(nextStateType);}}public IGameState getState(GameStateType type){if (!m_dicGameStates.ContainsKey(type)){return null;}return m_dicGameStates[type];}
}

我们抽象出所有的状态公有的方法属性:IGameState接口:

也符合面向接口编程原则。好处我之前讲过了。

IGameState:

using UnityEngine;
using System.Collections;
using Game.Common;
/// <summary>
/// 游戏状态接口
/// </summary>
public interface IGameState
{GameStateType GetStateType();//获取实现类的状态类型void SetStateTo(GameStateType gsType);//设置实现类的状态类型(改变状态)void Enter();//进入实现类的状态,做主要状态的逻辑处理GameStateType Update(float fDeltaTime);//状态改变,返回改变后的状态void FixedUpdate(float fixedDeltaTime);//固定更新状态void Exit();//退出该状态
}

然后编写实现接口的子实现类,这里我们先写LoginState:

using UnityEngine;
using System.Collections;
using Game.Common;
/// <summary>
/// 登陆游戏状态
/// </summary>
public class LoginState : IGameState
{GameStateType m_eStateTo;public LoginState(){}public GameStateType GetStateType() {return GameStateType.GS_Login;}public void SetStateTo(GameStateType stateType){this.m_eStateTo = stateType;}public void Enter(){SetStateTo(GameStateType.GS_Continue);LoginCtrl.singleton.Enter();}public void Exit(){LoginCtrl.singleton.Exit();}public void FixedUpdate(float fixedDeltaTime){}public GameStateType Update(float fDeltaTime){return m_eStateTo;}
}

然后在GameStateManager的构造方法,添加到缓存字典里面。

OK,这个状态机,假如说我们调用GameStateManager的ChangeStateTo(你想要的状态类型),那么就会执行你想要的状态实现类的Enter方法。

所以我们在LoginState的Enter编写我们登陆的逻辑,因为LoginState主要是管理状态改变的,所以我们为了类的单一职责,吧所有登陆逻辑放在:LoginCtrl控制类里面。

    public void Enter(){SetStateTo(GameStateType.GS_Continue);//先转到中间状态LoginCtrl.singleton.Enter();}

LoginCtrl:

OK,写到这里,我们之后当我知道版本更新完成或者根本不需要更新,就直接弹出登陆UI的用户名输入框界面。

那么,我们就得写个LoginWindow来管理登陆UI,所以先写LoginWindow:

using UnityEngine;
using System.Collections;
using Game.Common;
using Utility;
using System;
/// <summary>
/// 登陆界面UI
/// </summary>
public class LoginWindow : BaseWindow
{public LoginWindow(){this.mResName = "Guis/LoginWindow";this.mResident = false;}public override void Init(){EventCenter.AddListener(EGameEvent.eGameEvent_LoginEnter, Show);EventCenter.AddListener(EGameEvent.eGameEvent_LoginExit, Hide);}public override void Realse(){EventCenter.RemoveListener(EGameEvent.eGameEvent_LoginEnter, Show);EventCenter.RemoveListener(EGameEvent.eGameEvent_LoginExit,Hide);}protected override void InitWidget(){}protected override void RealseWidget(){}protected override void OnAddListener(){}protected override void OnRemoveListener(){}public override void OnEnable(){}public override void OnDisable(){}public override void Update(float deltaTime){base.Update(deltaTime);}
}

OK,我们在LoginWindow里面添加显示登陆界面和隐藏登陆界面事件监听。

首先,我们知道,玩LOL的时候,当我们登陆成功之后,还要选择游戏大区服务器。所以我们把选择服务器归入到登陆界面来管理。

所以我们还是需要制作一个SelectServer界面,这里我也随便搞了下界面:

未完待续。。。。。。没时间以后继续

OK,终于暑假了,又有时间来写了,隔了好久的时间,我可能落下很多步骤,如果有不明白的童鞋,欢迎在下方留言。

接着讲,我们选择服务器的界面还没有制作,所以首先我们先来制作这个界面。

粗略的看下这界面的结构:

1.背景图片

2.左边的服务器列表

3.右边的图标和各个按钮

4.蓝色的服务器背景

大致就是这些,OK,我们看下Unity中的Hire窗口物体结构:

我们着重来看下ServerList的制作,其他的读者可以自行理解,然后搭建起来。

首先来看下ServerList:

我将他分为两个部分,第一个部分是上面的推荐服,第二个部分是下面的电信联通具体服。

制作好之后,吧他拖到Prefabs文件夹下面,然后拖到我们之前做好的登陆界面当做子物体。

然后把他的Panel设置为不激活状态。因为我们默认进入到登陆界面只显示输入用户名和密码,不显示选择服务器界面。等到我们正确的验证密码之后,然后才进入到选择服务器界面。

OK,大致的界面讲解完成了,我们开始写代码。在写代码之前,先来分析下看,因为这个服务器动态的,也就是说假如一个服务器进行维护或者繁忙,我们这边应该实时的知道。

所以,当我们进入到选择服务器界面的时候,应该接收到服务器发送来的服务器实时的数据信息,然后客户端才动态加载这些服务器列表。

所以我们代码怎么写?怎么样才能做到动态加载不确定数量的服务器列表。这里NGUI的UITable和UIGrid有点坑,我们如果想实例化一个子物体给UITable,他是不会动态刷新的,所以我决定自己再封装一层NGUI的代码,形成自己的一套UI管理。

我们在Window文件夹下面,新建一个UIObject文件夹,里面存放着所以和UI相关的接口和类,如XUISprite.cs实际上就是封装的NGUi的UISprite脚本。

可以看到我已经封装了这么多,可能有些童鞋会问了,既然NGui的都可以用,为什么还这么麻烦,自己封装一层。

这个封装确实很有必要:

1.方便操作,可以根据我们需要的功能进行扩展。就拿这个UITable来说,如果我们需要实时更新里面的Item,我们每在一处添加,都要得写好多代码,如果我们封装起来,一个方法就搞定。

2.可扩展性强。可以看到我们每个UI都有自己的一个接口,实现了依赖倒置原则。如果我们想要使用UGUi作为UI框架,我们只需要修改下,底层的代码,高层调用者就不需要改动代码,如果不使用的话,高层要高到死为止。

好处大致就是这么多。OK,我先来贴贴代码,我把所有的代码贴出来:

IXUIObject.cs

using UnityEngine;
using System.Collections;
/// <summary>
/// 所有UI物体公共的接口
/// </summary>
public interface IXUIObject
{Transform CacheTransform{get;}GameObject CacheGameObject{get;}IXUIObject Parent{get;set;}string Tip{get;set;}object TipParam{get;set;}bool IsVisible();void SetVisible(bool bVisible);IXUIObject GetUIObject(string strPath);void Highlight(bool bTrue);
}

XUIObjectBase.cs:

using UnityEngine;
using System.Collections;
/// <summary>
/// 继承MOnoBehavior的UI物体
/// </summary>
public abstract class XUIObjectBase : MonoBehaviour,IXUIObject
{private bool m_bInit = false;public string m_strTipText = "";protected float m_fAlpha = 1f;private Transform m_cacheTransform;private GameObject m_cacheGameObject;private IXUIObject m_parent;public Transform CacheTransform{get {if (this.m_cacheTransform == null) {this.m_cacheTransform = base.transform;}return this.m_cacheTransform;}}public GameObject CacheGameObject{get {if (this.m_cacheGameObject == null){this.m_cacheGameObject = base.gameObject;}return this.m_cacheGameObject;}}public object TipParam{get;set;}public string Tip {get { return this.m_strTipText; }set { this.m_strTipText = value; }}public virtual float Alpha {get {return this.m_fAlpha;}set {this.m_fAlpha = value;}}public virtual IXUIObject Parent {get {return this.m_parent;}set {this.m_parent = value;}}public bool IsInited {get { return this.m_bInit; }set { this.m_bInit = value; }}public virtual void Init(){this.m_bInit = true;}public bool IsVisible(){return base.gameObject.activeInHierarchy;}public virtual void SetVisible(bool bVisible){}public virtual void Highlight(bool bTrue){}public virtual IXUIObject GetUIObject(string strPath) {return null;}public virtual void OnAwake(){}public virtual void OnStart(){}public virtual void OnUpdate(){}public virtual void _OnClick(){}private void Awake(){OnAwake();}private void Start(){if (!this.m_bInit){Init();}OnStart();}private void Update(){OnUpdate();}private void OnClick(){this._OnClick();}private void OnEnable(){}private void OnDisable(){}
}

这个脚本是每个UI必须的,比如NGUi的脚本都是挂在UI物体上的。所以我们自己封装的脚本也是如此。

注意到没有中间有用到:

TipParam:这个是提示参数类

using UnityEngine;
using System.Collections;
using Game.Common;
/// <summary>
/// 提示参数类
/// </summary>
public class TipParam
{//提示信息public string Tip{get;set;}//提示类型,有普通提示(技能装备等)和标题提示(没有带复杂内容,只有一行字)public TipEnumType TipType{get;set;}public TipParam(){TipType = TipEnumType.eTipType_Common;}
}

这个主要是处理界面提示用的。

XUIObject.cs:

using UnityEngine;
using System.Collections;public abstract class XUIObject : XUIObjectBase
{public override void OnAwake(){base.OnAwake();}public override void OnStart(){base.OnStart();}public override void OnUpdate(){base.OnUpdate();}public override void Init(){base.Init();}public override void SetVisible(bool bVisible){NGUITools.SetActiveSelf(base.gameObject, bVisible);}
}

OK,我们开始写具体的UI类:先写UIList和UIListItem也就是Table或者Grid他对应着UIList,他下面的子物体对应着UIListItem。

由于UIListItem可能他的子物体有UISprite和UILabel等等,所以我们在写他之前先写UISprite:

因为我们写程序最好要依赖接口编程,所以写个IXUISprite接口:

using UnityEngine;
using System.Collections;public interface IXUISprite : IXUIObject
{Color Color{get;set;}string SpriteName{get;}IXUIAtlas UIAtlas{get;}/// <summary>/// 播放UI动画/// </summary>/// <param name="bLoop"></param>/// <returns></returns>bool PlayFlash(bool bLoop);void SetEnable(bool bEnable);/// <summary>/// 设置UISprite/// </summary>/// <param name="strSpriteName"></param>/// <returns></returns>bool SetSprite(string strSpriteName);bool SetSprite(string strSpriteName, string strAtlas);/// <summary>/// 停止UI动画/// </summary>/// <returns></returns>bool StopFlash();
}  

注意到没有,我们Sprite可能会用到UIAtlas,所以我们得再写个UIAtlas:

IXUIAtlas:

using UnityEngine;
using System.Collections;
public interface IXUIAtlas
{   UIAtlas Atlas{get;set;}
}

XUIAtlas:

using UnityEngine;
using System.Collections;public class XUIAtlas : MonoBehaviour,IXUIAtlas
{private UIAtlas m_uiAtlas;public UIAtlas Atlas {get{return this.m_uiAtlas;}set{this.m_uiAtlas = value;}}private void Awake(){this.m_uiAtlas = base.GetComponent<UIAtlas>();if (null == this.m_uiAtlas){Debug.LogError("null == m_uiAtlas");}}
}

XUISprite:

using UnityEngine;
using System.Collections;
using Game.Common;
[AddComponentMenu("XUI/XUISprite")]
public class XUISprite : XUIObject,IXUIObject,IXUISprite
{private string m_spriteNameCached = string.Empty;private string m_atlasNameCached = string.Empty;private UISprite m_uiSprite;private UISpriteAnimation m_uiSpriteAnimation;private ResourceUnit m_oAltasUnit;private IXLog m_log = XLog.GetLog<XUISprite>();public override float Alpha{get{if (null != this.m_uiSprite){return this.m_uiSprite.alpha;}return 0f;}set{if (null != this.m_uiSprite){this.m_uiSprite.alpha = value;}}}public Color Color {get {if (this.m_uiSprite != null){return this.m_uiSprite.color;}return Color.white;}set {if (this.m_uiSprite != null){this.m_uiSprite.color = value;}}}public string SpriteName{get{if (null != this.m_uiSprite){return this.m_uiSprite.spriteName;}return null;}}public IXUIAtlas UIAtlas {get {if (null == this.m_uiSprite){return null;}if (null == this.m_uiSprite.atlas){return null;}return this.m_uiSprite.atlas.GetComponent<XUIAtlas>();}}public override void Init(){base.Init();this.m_uiSprite = base.GetComponent<UISprite>();if (null == this.m_uiSprite){Debug.LogError("null == m_uiSprite");}this.m_uiSpriteAnimation = base.GetComponent<UISpriteAnimation>();}/// <summary>/// 播放动画/// </summary>/// <param name="bLoop"></param>/// <returns></returns>public bool PlayFlash(bool bLoop){if (null == this.m_uiSpriteAnimation){return false;}this.m_uiSpriteAnimation.loop = bLoop;this.m_uiSpriteAnimation.ResetToBeginning();this.m_uiSpriteAnimation.enabled = true;this.m_uiSprite.enabled = true;return true;}/// <summary>/// 停止动画/// </summary>/// <returns></returns>public bool StopFlash(){if (null == this.m_uiSpriteAnimation){return false;}this.m_uiSpriteAnimation.enabled = false;return true;}/// <summary>/// 设置UISprite/// </summary>/// <param name="strSprite"></param>/// <param name="strAltas"></param>/// <returns></returns>public bool SetSprite(string strSprite, string strAltas){if (null == this.m_uiSprite){return false;}//如果缓存图集已经存在了,那么就直接设置if (this.m_atlasNameCached.Equals(strAltas)){this.m_spriteNameCached = strSprite;this.m_uiSprite.spriteName = strSprite;this.m_uiSprite.enabled = true;return true;}this.m_spriteNameCached = strSprite;this.m_atlasNameCached = strAltas;this.PrepareAtlas(strAltas, strSprite);return true;}/// <summary>/// 设置默认图集的UISprite/// </summary>/// <param name="strSpriteName"></param>/// <returns></returns>public bool SetSprite(string strSpriteName){if (null == this.m_uiSprite){return false;}if (!string.IsNullOrEmpty(this.m_atlasNameCached)){this.SetSprite(this.m_atlasNameCached, strSpriteName);}else {this.m_uiSprite.spriteName = strSpriteName;}return true;}public void SetEnable(bool bEnable){Collider compent = base.GetComponent<Collider>();if (compent != null){compent.enabled = bEnable;}}private void OnDestroy(){if (this.m_oAltasUnit != null){this.m_oAltasUnit.Dispose();this.m_oAltasUnit = null;}}private void PrepareAtlas(string strAltas, string strSprite){m_oAltasUnit = ResourceManager.Instance.LoadImmediate(strAltas, ResourceType.PREFAB);GameObject obj = m_oAltasUnit.Asset as GameObject;UIAtlas uiAtals = obj.GetComponent<UIAtlas>();if (null == uiAtals){this.m_log.Error("加载图集的时候出错!!");return;}this.m_uiSprite.atlas = uiAtals;this.m_uiSprite.spriteName = strSprite;this.m_uiSprite.enabled = true;}
}

可以看到XUISprite提供4个主要接口:

1.SetSprite(string strSpriteName)---->设置Sprite,在默认的Alta中

2.SetSprite(string strSpriteName,string strAtlas)---->设置Sprite,在指定的Atlas中

3.PlayFlash(bool bLoop)---->是否播放UI帧动画

4.StopFlash()----->停止播放UI帧动画

写完Sprite之后,我们写

IXUIListItem:

using UnityEngine;
using System.Collections.Generic;
public interface IXUIListItem :IXUIObject
{int Id{get;set;}long GUID{get;set;}int Index{get;set;}bool IsSelected{get;set;}Dictionary<string, XUIObjectBase> AllXUIObject{get;}bool SetText(string strId,string strContent);void SetSelected(bool bTrue);void SetEnableSelect(bool bEnable);void SetIconSprite(string strSprite);void SetIconSprite(string strSprite, string strAtlas);void SetIconTexture(string strTexture);void SetColor(Color color);void SetEnable(bool bEnable);void Clear();
}

XUIListItem.cs:

using UnityEngine;
using System.Collections.Generic;
using UILib;
using Game.Common;
[AddComponentMenu("XUI/XUIListItem")]
public class XUIListItem : XUIObject,IXUIObject,IXUIListItem
{private UISprite m_uiSpriteIcon;private UILabel[] m_uiLabels;private UITexture m_uiTextureIcon;private UIButton m_uiButton;private UIToggle m_uiToggle;private UITexture[] m_uiTextures;private UISprite[] m_uiSprites;private XUISprite m_uiSpriteFlash;private Dictionary<string, XUIObjectBase> m_dicId2UIObject = new Dictionary<string, XUIObjectBase>();protected Collider m_colldier;private Color m_highlightColor = Color.clear;public int m_unId;private int m_unIndex = -1;private long m_GUID;public int Id {get { return this.m_unId; }set { this.m_unId = value;}}public int Index {get { return this.m_unIndex; }set { this.m_unIndex = value; }}public long GUID {get { return this.m_GUID; }set { this.m_GUID = value; }}public XUIList ParentXUIList {get {XUIList xUIlist = this.Parent as XUIList;if (null == xUIlist){Debug.LogError("null == uiList");}return xUIlist;}}public bool IsSelected {get {return this.m_uiToggle != null && this.m_uiToggle.value;}set{if (this.m_uiToggle != null && this.m_uiToggle.value != value){this.m_uiToggle.Set(value);if (value){this.ParentXUIList.SelectItem(this, false);}else{this.ParentXUIList.UnSelectItem(this, false);}}}}public Dictionary<string, XUIObjectBase> AllXUIObject{get { return this.m_dicId2UIObject; }}public void SetSelected(bool bTrue){if (this.m_uiToggle != null && this.m_uiToggle.value != bTrue){this.m_uiToggle.Set(bTrue);}}public void SetEnableSelect(bool bEnable){if (!bEnable && this.m_uiToggle != null){this.m_uiToggle.value = false;}this.Highlight(bEnable);if (this.m_uiToggle != null){this.m_uiToggle.enabled = bEnable;}}private void OnSelectStateChange(){bool bSelected = this.m_uiToggle.value;if (bSelected){//List选择该itemthis.ParentXUIList.OnSelectItem(this);}else {//List不选择该itemthis.ParentXUIList.OnUnSelectItem(this);}}public void SetIconSprite(string strSprite){if (null != this.m_uiSpriteIcon){this.m_uiSpriteIcon.spriteName = strSprite.Substring(strSprite.LastIndexOf("\\") + 1);this.m_uiSpriteIcon.enabled = true;}XUISprite xUISprite = this.GetUIObject("Sprite_Icon") as XUISprite;if (null != xUISprite){xUISprite.SetSprite(strSprite);}}public void SetIconSprite(string strSprite, string strAtlas){XUISprite xUISprite = this.GetUIObject("Sprite_Icon") as XUISprite;if (null != xUISprite){xUISprite.SetSprite(strSprite, strAtlas);}}public void SetIconTexture(string strTexture){XUITexture xUITexture = this.GetUIObject("Texture_Icon") as XUITexture;if (xUITexture != null){xUITexture.SetTexture(strTexture);}}public bool SetText(string strId, string strText){IXUILabel label = this.GetUIObject(strId) as IXUILabel;if (label != null){label.SetText(strText);return true;}return false;}public void SetColor(Color color){if (this.m_uiSpriteIcon != null){this.m_uiSpriteIcon.color = color;}if (this.m_uiTextureIcon != null){this.m_uiTextureIcon.color = color;}}public void SetEnable(bool bEnable){if (this.m_colldier != null){this.m_colldier.enabled = bEnable;}if (this.m_uiButton != null){this.m_uiButton.enabled = bEnable;}}public void Clear(){this.m_unId = 0;UILabel[] uiLabels = this.m_uiLabels;for (int i = 0; i < uiLabels.Length; i++){UILabel uILabel = uiLabels[i];uILabel.text = string.Empty;}if (null != this.m_uiSpriteIcon){this.m_uiSpriteIcon.enabled = false;}if (null != this.m_uiTextureIcon){this.m_uiTextureIcon.enabled = false;}this.Tip = string.Empty;this.TipParam = null;}public override void Init(){base.Init();WidgetFactory.FindAllUIObjects(base.transform, this, ref m_dicId2UIObject);foreach (var uiObject in this.m_dicId2UIObject.Values){uiObject.Parent = this;if (!uiObject.IsInited){uiObject.Init();}}if (null == this.m_uiSpriteIcon){Transform tran = base.transform.FindChild("Sprite_Icon");if (tran != null){this.m_uiSpriteIcon = tran.GetComponent<UISprite>();}}if (null == this.m_uiTextureIcon){Transform tran1 = base.transform.FindChild("Texture_Icon");if (tran1 != null){this.m_uiTextureIcon = tran1.GetComponent<UITexture>();}}this.m_colldier = base.GetComponent<Collider>();this.m_uiLabels = base.GetComponentsInChildren<UILabel>();this.m_uiToggle = base.GetComponent<UIToggle>();this.m_uiButton = base.GetComponent<UIButton>();this.m_uiSprites = base.GetComponentsInChildren<UISprite>(true);this.m_uiTextures = base.GetComponentsInChildren<UITexture>(true);this.m_uiSpriteFlash = this.GetUIObject("Sprite_Flash") as XUISprite;if (this.m_uiToggle != null){EventDelegate.Add(this.m_uiToggle.onChange, this.OnSelectStateChange);}this.Highlight(false);}public override IXUIObject GetUIObject(string strPath){if (strPath == null){return null;}string key = strPath;int num = strPath.LastIndexOf('/');if (num >= 0){key = strPath.Substring(num + 1);}XUIObjectBase result = null;if (this.m_dicId2UIObject.TryGetValue(key, out result)){return result;}return null;}public override void Highlight(bool bTrue){base.Highlight(bTrue);if (this.m_uiSpriteFlash != null){if (!bTrue){this.m_uiSpriteFlash.StopFlash();}else {this.m_uiSpriteFlash.PlayFlash(true);}}}public override void _OnClick(){base._OnClick();this.ParentXUIList._OnClick(this);}
}

注意了,细心的童鞋可能看到,这个Item他的子物体假如是Sprite,那么他的命名必须是:

Sprite_Icon

如果子物体是Texture,那么命名必须是:

Texture_Icon

如果子物体是有带动画的Sprite,必须命名为:

Sprite_Flash

还有如果这个Item是可以选择的,必须添加UIToggle脚本,具体读者自己看代码。OK,接着我们写

IXUIList:

using UnityEngine;
using System.Collections.Generic;
using Game.Common;
public interface IXUIList : IXUIObject
{int Count{get;}int GetSelectedIndex();void SetSelectedIndex(int nIndex);void SetSelectedItemByIndex(List<int> listItemIndex);void SetSelectedItemById(int unId);void SetSelectedItemById(List<int> listItemId);IXUIListItem GetSelectedItem();IXUIListItem[] GetSelectedItems();IXUIListItem GetItemById(int unId, bool bVisible);IXUIListItem GetItemByGUID(long ulId);IXUIListItem[] GetAllItems();IXUIListItem GetItemByIndex(int nIndex);IXUIListItem AddListItem(GameObject obj);IXUIListItem AddListItem();bool DelItemById(int unId);bool DelItemByIndex(int nIndex);bool DelItem(IXUIListItem iUIListItem);void SetEnable(bool bEnable);void SetEnableSelect(bool bEnable);void SetEnableSelect(List<int> listIds);void Highlight(List<int> listIds);void Refresh();void OnSelectItem(XUIListItem listItem);void SelectItem(XUIListItem listItem, bool bTrigerEvent);void OnUnSelectItem(XUIListItem listItem);void UnSelectItem(XUIListItem listItem, bool bTrigerEvent);void RegisterListOnSelectEventHandler(ListSelectEventHandler handler);void RegisterListOnUnSelectEventHandler(ListSelectEventHandler handler);void RegisterListOnClickEventHandler(ListOnClickEventHandler handler);void Clear();
}

可能会有出错,因为我们ListSelectEventHandler委托类型还没有声明,我们到DefineCommon中定义这两个委托类型:

public delegate bool ListSelectEventHandler(IXUIListItem listItem);
public delegate bool ListOnClickEventHandler(IXUIListItem listItem);

XUIList.cs:

using UnityEngine;
using System.Collections.Generic;
using System;
using Game.Common;
[AddComponentMenu("XUI/XUIList")]
public class XUIList : XUIObject, IXUIObject,IXUIList
{public GameObject m_prefabListItem;public bool m_bMultiSelect;private bool m_bHasAddItem;private List<XUIListItem> m_listXUIListItem = new List<XUIListItem>();private List<XUIListItem> m_listXUIListItemSelected = new List<XUIListItem>();private ListSelectEventHandler m_eventhandlerOnSelect;private ListSelectEventHandler m_eventhandlerOnUnSelect;private ListOnClickEventHandler m_eventhandlerOnClick;private UIGrid m_uiGrid;private UITable m_uiTable;public int Count {get{if (null == this.m_listXUIListItem){return 0;}return this.m_listXUIListItem.Count;}}public override void Init(){base.Init();this.m_listXUIListItem.Clear();this.m_listXUIListItemSelected.Clear();for (int i = 0; i < base.transform.childCount; i++){Transform child = base.transform.GetChild(i);XUIListItem component = child.GetComponent<XUIListItem>();if (component == null){Debug.LogError("null == uiListitem");}else {component.Parent = this;this.m_listXUIListItem.Add(component);}this.m_listXUIListItem.Sort(new Comparison<XUIListItem>(XUIList.SortByName));int num = 0;foreach (XUIListItem current in this.m_listXUIListItem){current.name = string.Format("{0:0000}", num);current.Index = num;current.Id = num;if (!current.IsInited){current.Init();}UIToggle component2 = current.GetComponent<UIToggle>();if (current.IsSelected){this.m_listXUIListItemSelected.Add(current);}num++;}this.m_uiGrid = base.GetComponent<UIGrid>();if (null != this.m_uiGrid){this.m_uiGrid.Reposition();}this.m_uiTable = base.GetComponent<UITable>();if (null != this.m_uiTable){this.m_uiTable.Reposition();}}}public int GetSelectedIndex(){if (this.m_listXUIListItemSelected.Count > 0){return this.m_listXUIListItemSelected[0].Index;}return -1;}public void SetSelectedIndex(int nIndex){XUIListItem selectedItem = this.GetItemByIndex(nIndex) as XUIListItem;this.SetSelectedItem(selectedItem);//this.FocusIndex(nIndex);}public void SetSelectedItemByIndex(List<int> listItemIndex){if (this.m_bMultiSelect){this.m_listXUIListItemSelected.Clear();foreach (XUIListItem current in this.m_listXUIListItem){if (listItemIndex != null && listItemIndex.Contains(current.Index)){current.SetSelected(true);this.m_listXUIListItemSelected.Add(current);}else{current.SetSelected(false);}}}else{Debug.LogError("false == m_bMultiSelect");}}public void SetSelectedItemById(int unId){XUIListItem selectedItem = this.GetItemById(unId) as XUIListItem;this.SetSelectedItem(selectedItem);}public void SetSelectedItemById(List<int> listItemId){if (this.m_bMultiSelect){this.m_listXUIListItemSelected.Clear();foreach (XUIListItem current in this.m_listXUIListItem){if (listItemId != null && listItemId.Contains(current.Id)){current.SetSelected(true);this.m_listXUIListItemSelected.Add(current);}else{current.SetSelected(false);}}}else{Debug.LogError("false == m_bMultiSelect");}}public void SetSelectedItem(XUIListItem uiListItem){foreach (XUIListItem current in this.m_listXUIListItemSelected){current.SetSelected(false);}this.m_listXUIListItemSelected.Clear();if (null != uiListItem){uiListItem.SetSelected(true);this.m_listXUIListItemSelected.Add(uiListItem);}}public IXUIListItem GetItemByIndex(int nIndex){if (this.m_listXUIListItem == null){return null;}if (0 > nIndex || nIndex >= this.m_listXUIListItem.Count){return null;}return this.m_listXUIListItem[nIndex];}public IXUIListItem GetSelectedItem(){if (this.m_listXUIListItemSelected.Count > 0){return this.m_listXUIListItemSelected[0];}return null;}public IXUIListItem[] GetSelectedItems(){return this.m_listXUIListItemSelected.ToArray();}public IXUIListItem GetItemById(int unId){foreach (XUIListItem current in this.m_listXUIListItem){if (unId == current.Id){return current;}}return null;}public IXUIListItem GetItemById(int unId, bool bVisible){foreach (XUIListItem current in this.m_listXUIListItem){if (unId == current.Id && current.IsVisible() == bVisible){return current;}}return null;}public IXUIListItem GetItemByGUID(long ulId){foreach (XUIListItem current in this.m_listXUIListItem){if (ulId == current.GUID){return current;}}return null;}public IXUIListItem[] GetAllItems(){return this.m_listXUIListItem.ToArray();}public IXUIListItem AddListItem(GameObject obj){if (null == obj){return null;}GameObject gameObject = UnityEngine.Object.Instantiate(obj) as GameObject;gameObject.name = string.Format("{0:0000}", this.Count);gameObject.transform.parent = base.transform;gameObject.transform.localPosition = Vector3.zero;gameObject.transform.localScale = Vector3.one;gameObject.transform.localRotation = Quaternion.identity;NGUITools.SetLayer(gameObject, this.CacheGameObject.layer);UIToggle component = gameObject.GetComponent<UIToggle>();XUIListItem xUIListItem = gameObject.GetComponent<XUIListItem>();if (null == xUIListItem){//Debug.LogError("null == uiListItem");xUIListItem = gameObject.AddComponent<XUIListItem>();}xUIListItem.Index = this.Count;xUIListItem.Id = xUIListItem.Index;xUIListItem.Parent = this;if (!xUIListItem.IsInited){xUIListItem.Init();}this.m_listXUIListItem.Add(xUIListItem);this.m_bHasAddItem = true;this.Refresh();return xUIListItem;}public IXUIListItem AddListItem(){if (null != this.m_prefabListItem){return this.AddListItem(this.m_prefabListItem);}return null;}public bool DelItemById(int unId){IXUIListItem itemById = this.GetItemById(unId);return this.DelItem(itemById);}public bool DelItemByIndex(int nIndex){IXUIListItem itemByIndex = this.GetItemByIndex(nIndex);return this.DelItem(itemByIndex);}public bool DelItem(IXUIListItem iUIListItem){XUIListItem xUIListItem = iUIListItem as XUIListItem;if (null == xUIListItem){return false;}this.m_listXUIListItemSelected.Remove(xUIListItem);int index = xUIListItem.Index;for (int i = index + 1; i < this.Count; i++){this.m_listXUIListItem[i].name = string.Format("{0:0000}", i - 1);this.m_listXUIListItem[i].Index = i - 1;}this.m_listXUIListItem.Remove(xUIListItem);xUIListItem.gameObject.transform.parent = null;UnityEngine.Object.Destroy(xUIListItem.gameObject);this.Refresh();return true;}public void Clear(){if (this.m_listXUIListItem == null){return;}foreach (XUIListItem current in this.m_listXUIListItem){current.gameObject.transform.parent = null;UnityEngine.Object.Destroy(current.gameObject);}this.m_listXUIListItemSelected.Clear();this.m_listXUIListItem.Clear();this.Refresh();}public void SetEnable(bool bEnable){foreach (XUIListItem current in this.m_listXUIListItem){current.SetEnable(bEnable);}}public void SetEnableSelect(bool bEnable){foreach (XUIListItem current in this.m_listXUIListItem){current.SetEnableSelect(bEnable);}if (!bEnable){this.m_listXUIListItemSelected.Clear();}}public void SetEnableSelect(List<int> listIds){if (listIds == null){return;}foreach (XUIListItem current in this.m_listXUIListItem){if (listIds.Contains(current.Id)){current.SetEnableSelect(true);}else{current.SetEnableSelect(false);}}this.m_listXUIListItemSelected.RemoveAll((XUIListItem x) => !listIds.Contains(x.Id));}public override void Highlight(bool bTrue){foreach (XUIListItem current in this.m_listXUIListItem){current.Highlight(bTrue);}}public void Highlight(List<int> listIds){this.Highlight(false);if (listIds == null){return;}foreach (XUIListItem current in this.m_listXUIListItem){if (listIds.Contains(current.Id)){current.Highlight(true);}}}public void Refresh(){if (null != this.m_uiGrid){this.m_uiGrid.repositionNow = true;}if (null != this.m_uiTable){this.m_uiTable.repositionNow = true;}this.RefreshAllItemStatus();}public void OnSelectItem(XUIListItem listItem){this.SelectItem(listItem, true);}public void SelectItem(XUIListItem listItem, bool bTrigerEvent){if (null == listItem){return;}if (this.m_listXUIListItemSelected.Contains(listItem)){return;}if (!this.m_bMultiSelect){this.m_listXUIListItemSelected.Clear();}this.m_listXUIListItemSelected.Add(listItem);//触发选择委托if (bTrigerEvent && this.m_eventhandlerOnSelect != null){this.m_eventhandlerOnSelect(listItem);}}public void OnUnSelectItem(XUIListItem listItem){this.UnSelectItem(listItem, true);}public void UnSelectItem(XUIListItem listItem, bool bTrigerEvent){if (null == listItem){return;}if (!this.m_listXUIListItemSelected.Contains(listItem)){return;}this.m_listXUIListItemSelected.Remove(listItem);//不选择委托if (bTrigerEvent && this.m_eventhandlerOnUnSelect != null){this.m_eventhandlerOnUnSelect(listItem);}}public void RegisterListOnSelectEventHandler(ListSelectEventHandler handler){this.m_eventhandlerOnSelect = handler;}public void RegisterListOnUnSelectEventHandler(ListSelectEventHandler handler){this.m_eventhandlerOnUnSelect = handler;}public void RegisterListOnClickEventHandler(ListOnClickEventHandler handler){this.m_eventhandlerOnClick = handler;}public void _OnClick(XUIListItem item){if (this.GetSelectedIndex() != item.Index){this.SelectItem(item, false);}if (this.m_eventhandlerOnClick != null){this.m_eventhandlerOnClick(item);}}public static int SortByName(XUIListItem a, XUIListItem b){return string.Compare(a.name, b.name);}private void RefreshAllItemStatus(){int num = this.GetSelectedIndex();if (num < 0){this.SetSelectedIndex(0);}}
}

  

可以看都XUIList封装了好多处理Item的方法,具体的读者可以自行阅读代码,这里我们只需要知道怎么用就行了。

OK,封装好了之后,我们回到UI界面,把我们自己定义的这些组件添加到对应的UI组件中。

这里我们电信的Grid,我添加自己定义的XUIList组件。

然后他的子物体Item,我添加了XUIListItem组件和UIToggle组件。

然后将Item拖到Prefab当成预制物,然后到XUiList中设置Prefab ListItem变量为这个预制物。可以看上图的XUIList我已经添加了。

这个Prefab ListItem有什么用呢?

这要是我们动态添加item的时候,他就会实例化这个预制物。也就是我们前提设置好要动态添加的item。

OK,其他的组件自己自行添加。

同理,联通的那个UIGrid也是类似的。讲完这个自己封装的UI框架,我们继续回到游戏主题。

开始写LoginWindow.cs

这节一多,下节继续。。。。。。

转载于:https://www.cnblogs.com/CaomaoUnity3d/p/5487343.html

仿LOL项目开发第六天相关推荐

  1. 仿LOL项目开发第五天

    仿LOL项目开发第五天 by草帽 今天呢,我们看下能开发什么内容,首先上节我们已经讲了UI框架的搭建,上节还遗留下很多问题,比如说消息的字符是代码里面自己赋值的. 那么就比较死板,按照正常的逻辑,那些 ...

  2. 仿LOL项目开发第一天

    ---恢复内容开始--- 仿LOL项目开发第一天 by---草帽 项目源码研究群:539117825 最近看了一个类似LOL的源码,颇有心得,所以今天呢,我们就来自己开发一个类似于LOL的游戏demo ...

  3. 仿LOL项目开发第二天

    仿LOL项目开发第二天 by草帽 接着上节来讲,上节更新还没开始写代码逻辑,今天我们补充完整. 我们找到VersionManager脚本里面的CheckVersion方法: 首先我们想到检测版本,需要 ...

  4. 仿LOL项目开发第四天

    ---恢复内容开始--- 仿LOL项目开发第四天 by草帽 上节讲了几乎所有的更新版本的逻辑,那么这节课我们来补充界面框架的搭建的讲解. 我们知道游戏中的每个界面都有自己的一个类型:比如登陆界面,创建 ...

  5. 高仿百思不得姐项目开发(粗略笔记,后期规范排版和更新)

    转载于:https://www.cnblogs.com/goodboy-heyang/p/5150102.html

  6. vue项目开发实录--仿去哪儿网App-张鹏-专题视频课程

    vue项目开发实录--仿去哪儿网App-160人已学习 课程介绍         本课程为vue项目开发实录(仿去哪儿网App)其中涉及到知识点有:组件搭建,路由,vuex,axios,webpack ...

  7. android app开发混合开发,混合开发入门 Vue结合Android/iOS开发仿京东项目App

    download:混合开发入门 Vue结合Android/iOS开发仿京东项目App 无需原生开发基础,也能完美呈现京东商城.本课程融合vue.Android.IOS等目前流行的前端和移动端技术,混合 ...

  8. 仿微信的网络聊天室项目开发【完整源码讲解】

    目录 总体开发思路 服务器端 服务器界面设计 建立TCP服务器端通信 建立服务器消息发送输出流 建立服务器消息接收输入流 建立服务器实时消息通信线程 设置服务器通信自由断开 客户端 客户端界面设计 建 ...

  9. IOS仿[自选股]项目开发

    [自选股]手机客户端致力于通过先进的移动互联技术,让广大投资者尊享更便捷的证券投资服务.其简约易用 功能特点 一:界面简洁 登录人性化 用户可通过QQ账户登录软件,无需注册登录.登录后,软件会自动同步 ...

最新文章

  1. 别再SOTA了,那叫“微调”!Science发文炮轰论文灌水
  2. Win2008 r2 iis7/iis7.5系统下HTTP重定向(301重定向)图文方法
  3. 运行sp_xp_cmdshell_proxy_account 出现的错误
  4. 【模型解读】“不正经”的卷积神经网络
  5. AdapterView及其子类之三:基于ListView及ArrayAdapter实现列表
  6. 【小记】-005--纯CSS实现的小玩意儿
  7. Linux 基本操作--文件查看 (day3)
  8. php 复选框 未选,php – 在表单发布时如何获取复选框元素中未选中复选框的值?...
  9. UVA10267 Graphical Editor【模拟】
  10. bash实现自动补全
  11. 京东后台:订单履约系统设计(上)
  12. 利用快递100api查询快递信息
  13. 【原创】高精度好题 Heaven Cow与God Bull
  14. Qt的对话框与窗口--Qt中主要的窗体类及其用途
  15. Python搭建tensorflow三层神经网络
  16. eclipse安装WindousBuilder为什么在项目里不显示
  17. Word里面文字怎么修改字体
  18. JavaScript内存溢出
  19. jmeter压测学习28-监听器之用表格察看结果(View Results in Table)
  20. 2023 绿茶小说网站系统PHP自适应源码

热门文章

  1. tgz文件在Windows系统上解压缩
  2. VS2017配置最新版PCL1.9.1(win10)
  3. 建立任务,OSTaskCreate()源码解析
  4. 检索 : Approximate Nearest Neighbor NSW + HNSW
  5. js ajax contenttype,ajax中设置contentType: application/json的作用(图文教程)
  6. PHP 字符串超出长度用省略号,PHP字符串截取长度自定义方法cut_带省略号
  7. 华硕天选笔记本系统损坏怎么U盘重装系统教学
  8. 深挖Openstack Cinder - CLI命令(3)
  9. anonymous implementation of android.content.DialogInterface$OnDismissListener
  10. JAVA1.6 API中文版