通过委托与事件监听状态改变来更新UI

来源:互联网 发布:闪电地震流数据 编辑:程序博客网 时间:2024/05/21 02:19

该博文涵盖的知识点

1. C# 委托
2. 如何利用委托监听事件以此更新显示

所要完成目标

我们刚开始做好的部分UI界面如下图所示:


观察左边的红色方框,我们先做了实例的姓名,头像,slider,和Label等,在运行游戏时候需要更新相应的属性。

在下面的脚本中,我们分别更新:左边方框中的nameLabel(黄晓明),energyLabel(50/100),toughenLabel(32/50)以及levelLabel(89);和右边的两个Label(12345678和12345678)。如何更新呢?我们借助委托注册事件来监听属性的改变,下面不再做解释,脚本中注释说明了一切!!!!

脚本、Unity相关设置


这里只使用三个脚本来学习如何使用委托来注册事件,以此监听属性的变化。如上图所示,PlayerBar脚本绑定在player-bar上,PlayerInfo脚本绑定在GameObject(空的游戏物体,作为控制)上,TopBar脚本绑定在top-bar上,分别在这些脚本中获取Unity Hierarchy中的相关属性,然后进行更新。下面分别是三个脚本:PlayerInfo,PlayerBar以及TopBar
using UnityEngine;using System.Collections;public enum InfoType{Name,HeadPortrait,Level,Power,Exp,Diamond,Coin,Energy,Toughen,All}public class PlayerInfo : MonoBehaviour {// 创建该类 为单例模式、public static PlayerInfo _instance;#region propertyprivate string _name;private string _headPortrait;private int _level = 1;private int _power = 1;private int _exp = 0;private int _diamond;private int _coin;private int _energy;private int _toughen;#endregion// 体力和历练的计时器;一分钟体力加1private float energyTimer = 0;private float toughenTimer = 0;// ----------------- 委托 -----------------------------------public delegate void OnPlayerInfoChangedEvent(InfoType type);// 利用委托定义事件,通过事件监听属性的更改public event OnPlayerInfoChangedEvent OnPlayerInfoChanged;#region get set methodpublic string Name{get{ return _name; }set{ _name = value; }}public string HeadPortrait{get { return _headPortrait; }set { _headPortrait = value; }}public int Level{get { return _level; }set { _level = value; }}public int Power{get { return _power; }set { _power = value; }}public int Exp{get { return _exp; }set { _exp = value; }}public int Diamond{get { return _diamond; }set { _diamond = value; }}public int Coin{get { return _coin; }set { _coin = value; }}public int Energy{get { return _energy; }set { _energy = value; }}public int Toughen{get { return _toughen; }set { _toughen = value; }}#endregionvoid Start(){Init ();// 初始化}void Awake(){_instance = this;}void Update(){// ------------- 实现体力和历练的自由增长 ---------------------------- // 每一分钟体力和历练增长1,其中体力总数为100,历练总是为50// 实现体力的自动增长if (this.Energy < 100) {energyTimer += Time.deltaTime;if (energyTimer > 60) {Energy += 1;energyTimer -= 60;OnPlayerInfoChanged (InfoType.Energy);}} else {energyTimer = 0;}// 实现历练的自由增长if (this.Toughen < 50) {toughenTimer += Time.deltaTime;if (toughenTimer > 60) {Toughen += 1;toughenTimer -= 60;OnPlayerInfoChanged (InfoType.Toughen);}} else {toughenTimer = 0;}// ------------- ----------------------- ---------------------------- }// 初始化属性void Init(){this.Coin = 9870;this.Diamond = 1234;this.Energy = 78;this.Exp = 123;this.HeadPortrait = "头像底板女性";this.Level = 12;this.Name = "千颂伊";this.Power = 1745;this.Toughen = 34;OnPlayerInfoChanged (InfoType.All);}}
using UnityEngine;using System.Collections;/**2016-5-13 By BigoSprite * 设置PlayerBar脚本的执行顺序次于PlayerInfo脚本 * 步骤如下: * Edit>Project Settings>Script Execution Order * 注意:值小的,先执行*/public class PlayerBar : MonoBehaviour {// 该脚本用于更新左上角这一区域的属性private UISprite headSprite;private UILabel nameLabel;private UILabel energyLabel;private UISlider energySlider;private UILabel levelLabel;private UILabel toughenLabel;private UISlider toughenSlider;private UIButton energyPlusButton;private UIButton toughenPlusButton;void Awake(){headSprite = transform.Find ("head-sprite").GetComponent<UISprite> ();nameLabel = transform.Find ("name-label").GetComponent<UILabel> ();energyLabel = transform.Find("energy-progressBar/Label").GetComponent<UILabel> ();energySlider = transform.Find ("energy-progressBar").GetComponent<UISlider> ();levelLabel = transform.Find ("level-label").GetComponent<UILabel> ();toughenLabel = transform.Find ("toughen-progressBar/Label").GetComponent<UILabel> ();toughenSlider = transform.Find ("toughen-progressBar").GetComponent<UISlider> ();energyPlusButton = transform.Find ("energyPlusButton").GetComponent<UIButton> ();toughenPlusButton = transform.Find ("toughenPlusButton").GetComponent<UIButton> ();energyPlusButton = transform.Find ("energyPlusButton").GetComponent<UIButton> ();toughenPlusButton = transform.Find("toughenPlusButton").GetComponent<UIButton> ();// 使用单例模式前,要保证先初始化。因为我们设置PlayerInfo脚本先执行,后执行PlayerBar脚本// 而已经在PlayerInfo脚本中的Awake方法中初始化了,因此可保证_instance肯定存在。// ------- 注册PlayerInfo中的委托事件(+=), PlayerInfo是单例模式,公有的类,所以 ----------PlayerInfo._instance.OnPlayerInfoChanged += this.OnPlayerInfoChanged;}// 注销事件 -=void OnDestory(){PlayerInfo._instance.OnPlayerInfoChanged -= this.OnPlayerInfoChanged;}// 当我们的主角信息发生改变的时候,会触发这个方法void OnPlayerInfoChanged(InfoType type){// 首先判断角色的哪部分信息改变了// 注意这个脚本(PlayerBar)绑定在PlayerBar身上,即左上角的区域if(type == InfoType.All ||type == InfoType.Name || type == InfoType.Level || type == InfoType.Energy || type == InfoType.Toughen){UpdateShow();// 更新信息的显示}}// 更新显示// 如何更新信息的显示?怎么确定具体哪一个信息改变了???// 这里管他具体哪个改变了,全部给他更新,哈哈!!!void UpdateShow(){PlayerInfo info = PlayerInfo._instance;// 初始化一个对象headSprite.spriteName = info.HeadPortrait;// 头像levelLabel.text = info.Level.ToString();nameLabel.text = info.Name;// 注意: 这里需要除以100f和50f,得到浮点型;如果除以100和50,slider不会显示!energySlider.value = info.Energy / 100f;// energy SliderenergyLabel.text = info.Energy.ToString () + "/100";toughenSlider.value = info.Toughen / 50f;// toughen SlidertoughenLabel.text = info.Toughen.ToString()+"/50";}}
using UnityEngine;using System.Collections;public class TopBar : MonoBehaviour {private UILabel coinLabel;private UILabel diamondLabel;private UIButton coinPlusButton;private UIButton diamondPlusButton;void Awake(){coinLabel = transform.Find ("coin-bg/Label").GetComponent<UILabel> ();diamondLabel = transform.Find ("diamond-bg/Label").GetComponent<UILabel> ();coinPlusButton = transform.Find ("coin-bg/coinPlusButton").GetComponent<UIButton> ();diamondPlusButton = transform.Find ("diamond-bg/diamondPlusButton").GetComponent<UIButton> ();// 1. 注册事件,同样是在设置脚本执行次序的前提下// 加入未设置执行次序,PlayerInfo不先于TopBar执行,会报错:说// Object reference not set to an instance of an object.// 即PlayerInfo脚本中的_instance = this;次于TopBar脚本执行,TopBar脚本使用实例,但实例还未初始化呢?所以需要指定次序。PlayerInfo._instance.OnPlayerInfoChanged += this.OnPlayerInfoChanged;}// 注销事件void OnDestory(){PlayerInfo._instance.OnPlayerInfoChanged -= this.OnPlayerInfoChanged;}// ---------------------------------------------------------------------// 1. 注册和注销事件// 2. 更新显示// 注意:更改脚本执行顺序,PlayerInfo先于TopBar执行void OnPlayerInfoChanged(InfoType type){if(type == InfoType.All || type == InfoType.Coin || type == InfoType.Diamond){UpdateShow ();}}void UpdateShow(){PlayerInfo info = PlayerInfo._instance;coinLabel.text = info.Coin.ToString ();diamondLabel.text = info.Diamond.ToString ();}}
其中,设置脚本执行次序如下图所示:

运行Unity,效果如下图所示:


注:本博文参考SIKI老师的《泰斗破坏神》,用于学习


0 0
原创粉丝点击