仿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选择该item
this.ParentXUIList.OnSelectItem(this);
}
else
{
//List不选择该item
this.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

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

仿LOL项目开发第六天的更多相关文章

  1. 仿LOL项目开发第五天

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

  2. 仿LOL项目开发第九天

    仿LOL项目开发第九天 by 草帽 OK,今天我们完全换了一种风格,抛弃了Unity3d的c#语法,我们来写写java的项目. 说到java服务器,当然有些人可能鄙视java的服务器速度太慢,但是相对 ...

  3. 仿LOL项目开发第八天

    仿LOL项目开发第八天 by 草帽 这节我们继续上节所讲的内容,上节我们初始化好了LoginWindow,当我们点击确认选择服务器按钮的时候,就发送服务器id给游戏服务器. 这里就开始涉及到客户端需要 ...

  4. 仿LOL项目开发第七天

    仿LOL项目开发第七天 by 草帽 不知不觉已经写到了第七篇这种类型的博客,但是回过头看看之前写的,发现都只能我自己能看懂. 我相信在看的童鞋云里雾里的,因为我基本上没怎么详细讲一个脚本怎么用?但是你 ...

  5. 仿LOL项目开发第四天

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

  6. 仿LOL项目开发第三天

    仿LOL项目开发第二天 by草帽 昨个我们已经实现了下载功能,但是发现没有,下载的包是压缩的,没有解压开,那么Unity是识别不了的. 所以今个我们来讲讲如何实现解压文件. 还记得吗,我们在Downl ...

  7. 仿LOL项目开发第二天

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

  8. 仿LOL项目开发第一天

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

  9. java项目开发第六天——天若有情天亦老,人间正道是沧桑

    今天讲解的东西是数据库连接,一天下来还是相对轻松的,这个组长也是够轻松的,队员加载的界面自己也是导入不了,最后也是不了了之,还是加油赶赶吧.看看严嘉那组的界面,最后就是呵呵.但是学长看完后(研究生,同 ...

随机推荐

  1. Mysql中的Btree与Hash索引

    B-Tree 索引特征 B-Tree索引可以被用在像=,>,>=,<,<=和BETWEEN这些比较操作符上.而且还可以用于LIKE操作符,只要它的查询条件是一个不以通配符开头的 ...

  2. Cookie/Session的认识

    Cookie 1.cookie是什么? cookie是一小段文本,伴随着用户请求和页面在web服务器和浏览器之间传递,cookie包含每次用户访问站点时,web应用程序都可以读取的信息 2.为什么需要 ...

  3. oracle 12C安装问题

    1. 先弄好c$ share的问题  2. 测试一下 c$ share 是否成功. 方法是在cmd里打net use \\localhost\c$ 失败会是这样子...: 系统错误53  The ne ...

  4. electron写俄罗斯方块游戏(Tetris)

    背景 在折腾ES6,突然想起大学时用c语言写过俄罗斯方块,本项目中主要是利用ES6的Class特性进行面向对象编程.项目采用node.js v6.2.0 + electron v1.1.0 进行桌面开 ...

  5. java总结(二)(运算符)

    算数和赋值运算符 1.变量类型溢出时候,会直接取反:出现x>x+1 2.知道a++和++a 3.知道a/0错误 a/0.0无穷大 字符串 1.知道栈区.堆区和方法区 2.知道new String ...

  6. ref:Web Service 渗透测试从入门到精通

    ref:https://www.anquanke.com/post/id/85910 Web Service 渗透测试从入门到精通 发布时间:2017-04-18 14:26:54 译文声明:本文是翻 ...

  7. 洛谷P3292 [SCOI2016] 幸运数字 [线性基,倍增]

    题目传送门 幸运数字 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的 ...

  8. React Native踩坑之Unable to load script from assets

    报错: Unable to load script from assets 'index.android.bundle'. Make sure your bundle is packaged corr ...

  9. 最短路 之 floyd 算法

    Floyd 在我认为这是最短路算法中最简单的一个,也是最low的一个. 所以我们组一位大佬给他起了一个新的名字,叫做超时!!! (其实如果数据范围很小的话,这个算法还是蛮好用的!!) 这个算法比较简单 ...

  10. 搭建samba 共享openstack开发环境

    centos7.2 openstack环境为allinone 模式,这样跑代码好处理 安装smb [root@controller ~]# yum install -y samba samba-cli ...