强化界面布局如下
StrengthenView 1 2 3 4 5 6 7 8 9 [BindPrefab(Path.STRENGTHEN_VIEW) ] public class StrengthenView : ViewBase { protected override void InitChild () { UIUtil.Get("Switchplayer" ).Go.AddComponent<SwitchPlayer>(); } }
Path
内的路径自己添加即可
给SwitchPlayer对象添加SwitchPlayer
脚本,SwitchPlayer
脚本也是一个继承了ViewBase
的脚本
修改ViewBase的逻辑 switchPlayer虽然是StrengthView的子物体,但我们依然可以给它单独添加脚本,同样继承ViewBase
。只不过我们此时需要修改ViewBase
,比如父物体的View被设定为Hide时,所有子物体的View也要被设定Hide。否则子物体肯定会出现问题。
我们先给ViewBase
添加InitSubView
方法,每个父UI元素动态挂载View脚本时,都会调用这个方法来缓存自己子物体中的View脚本。并且使用HashSet来缓存。
但是InitSubView
方法需要在Init
里面调用,并且必须在子物体都动态挂载完毕View脚本后才能调用InitSubView
,很容易被忽略,所以我们可以在ViewBase
里面添加抽象方法,强制View脚本首先实现动态挂载的逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 using System.Collections.Generic;using UnityEngine;public abstract class ViewBase : MonoBehaviour , IView { private HashSet<ViewBase> _views; private UIUtil m_UIUtil; protected UIUtil UIUtil { get { if (m_UIUtil == null ) { m_UIUtil = gameObject.AddComponent<UIUtil>(); m_UIUtil.Init(); } return m_UIUtil; } } public virtual void Init () { InitChild(); InitSubView(); foreach (ViewBase view in _views) { view.Init(); } } protected abstract void InitChild () ; private void InitSubView () { _views = new HashSet<ViewBase>(); ViewBase view = null ; foreach (Transform trans in transform) { view = trans.GetComponent<ViewBase>(); if (view != null ) { _views.Add(view); } } } public virtual void Hide () { foreach (ViewBase view in _views) { view.Hide(); } gameObject.SetActive(false ); } public virtual void Show () { gameObject.SetActive(true ); foreach (ViewBase view in _views) { view.Show(); } } }
修改SelectedHeroView
,Init
方法不需要重载了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 using UnityEngine;[BindPrefab(Path.SELECT_HERO_VIEW) ] public class SelectedHeroView : ViewBase { protected override void InitChild () { UIUtil.Get("Heros" ).Go.AddComponent<SelectHero>(); UIUtil.Get("OK/Start" ).AddListener(() => { }); UIUtil.Get("Exit" ).AddListener(() => { #if UNITY_EDITOR UnityEditor.EditorApplication.ExitPlaymode(); #endif Application.Quit(); }); UIUtil.Get("Strengthen" ).AddListener(() => { }); } }
修改StartView
1 2 3 4 5 6 7 8 9 10 11 [BindPrefab(Path.START_VIEW) ] public class StartView : ViewBase { protected override void InitChild () { UIUtil.Get("Start" ).AddListener(() => { UIMgr.Instance.Show(Path.SELECT_HERO_VIEW); }); } }
SwitchPlayer 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 using System;using System.Collections.Generic;using UnityEngine;public class SwitchPlayer : ViewBase { private int _id; private Dictionary<int ,List<Sprite>> _planeSprites; private Action<int > _onSwitch; protected override void InitChild () { UIUtil.Get("Left" ).AddListener(() => { Switch(ref _id, -1 ); }); UIUtil.Get("Right" ).AddListener(() => { Switch(ref _id, 1 ); }); LoadSprite(); } private void LoadSprite () { _planeSprites = new Dictionary<int ,List<Sprite>>(); Sprite[] sprites = LoadMgr.Instance.LoadAll<Sprite>(Path.PLAYER_PICTURE_FOLDER); foreach (Sprite sprite in sprites) { string [] idData = sprite.name.Split('_' ); int playerId = int .Parse(idData[0 ]); if (!_planeSprites.ContainsKey(playerId)) { _planeSprites.Add(playerId, new List<Sprite>()); } _planeSprites[playerId].Add(sprite); } } public override void Show () { _id = DataMgr.Instance.Get<int >(DataKeys.PLANE_ID); Switch(ref _id, 0 ); } private void Switch (ref int id,int direction ) { UpdateId(ref id,direction); UpdateSprite(id); _onSwitch?.Invoke(id); } private void UpdateId (ref int id,int direction ) { int min = 0 ; int max = _planeSprites.Count; id += direction; id = id < 0 ? min : id >= max ? max - 1 : id; } public void OnSwitchAction (Action<int > action ) { _onSwitch = action; } private void UpdateSprite (int id ) { int level = DataMgr.Instance.Get<int >(DataKeys.LEVEL); UIUtil.Get("Icon" ).SetSprite(_planeSprites[id][level]); } }
我们的飞机有4个种类,每个种类有4个等级。先用_planeSprites
字典把所有的飞机都缓存起来,这个字典的Count代表了所有飞机种类(4个)。按照这个数值来确定选择飞机的边界。
在LoadSprite
方法中,初始化_planeSprites
字典
在UpdateId
方法中检测当前选择的id,确保不会越界,注意方法内使用了嵌套的三元运算。
在UpdateSprite
方法中确定当前选择的战机的等级,并显示。
注意这里重载了Show
方法,但是没有调用base.Show
,可能会出现问题
DataKeys 在配置文件中的变量名,我们自己写一个文件对应好。在Scripts——Const文件夹内新建DataKeys
1 2 3 4 5 6 7 8 9 10 public class DataKeys { public const string LIFE = "life" ; public const string ATTACK = "attack" ; public const string FIRE_RATE = "direRate" ; public const string STAR = "star" ; public const string DIAMOND = "diamond" ; public const string PLANE_ID = "PlaneId" ; public const string LEVEL = "level" ; }
增加加载API 给ILoader
、ResourceLoader
和LoadMgr
添加加载任意类型的API
1 2 3 4 5 6 7 8 9 10 using System;using UnityEngine;public interface ILoader { public GameObject LoadPrefab (string path, Transform parent = null ) ; void LoadConfig (string path,Action<object > onComplete ) ; T Load <T >(string path ) where T : UnityEngine.Object ; T[] LoadAll <T >(string path ) where T: UnityEngine.Object ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class ResourceLoader : ILoader { public T Load <T >(string path ) where T : UnityEngine.Object { T item = Resources.Load<T>(path); if (item == null ) { Debug.LogError("未在路径中找到对象:" + path); return null ; } else return item; } public T[] LoadAll <T >(string path ) where T : UnityEngine.Object { T[] items = Resources.LoadAll<T>(path); if (items == null || items.Length == 0 ) { Debug.LogError("未在路径中找到对象:" + path); return null ; } else return items; } }
1 2 3 4 5 6 7 8 9 10 11 12 public class LoadMgr : NormalSingleton <LoadMgr >, ILoader { public T Load <T >(string path ) where T : UnityEngine.Object { return m_Loader.Load<T>(path); } public T[] LoadAll <T >(string path ) where T : UnityEngine.Object { return m_Loader.LoadAll<T>(path); } }
SelectedHeroView 在其中添加打开强化界面的逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 using UnityEngine;[BindPrefab(Path.SELECT_HERO_VIEW) ] public class SelectedHeroView : ViewBase { protected override void InitChild () { UIUtil.Get("Strengthen" ).AddListener(() => { UIMgr.Instance.Show(Path.STRENGTHEN_VIEW); }); } }