赞
踩
GitHub
//
官网的
全民飞机大战(第一季)-----框架设计篇(Unity 2017.3)
全民飞机大战(第二季)-----游戏逻辑篇(Unity 2017.3)
全民飞机大战(第三季)-----完善功能篇(Unity 2017.3)
全民飞机大战(第四季)-----新手引导篇
//
B站各放几集
全民飞机大战(第一季)-----框架设计篇(Unity 2017.3)
全民飞机大战(第二季)-----游戏逻辑篇(Unity 2017.3)
全民飞机大战(第三季)-----完善功能篇(Unity 2017.3)
全民飞机大战(第四季)-----新手引导篇
534/2(因为.cs.meta)=267个脚本
项目的原始unity版本是2017,对应的的C#版本是4.6,不支持ref,out,这对QF影响大,所以不用unity2017.
2023-06-19 Untiy进阶 C#知识补充2——C#版本与Unity的关系
直接删除using,那里没用掉
看到0引用,先注释掉算了# if false
补上去
删除另外一个
比如拓展方法
transform.Rect()
transform.AddComponent();
transform.Find(path).gameObject.AddComponent();
比如相同的类
Tags
这块报空了
/**************************************************** 文件:Framework_AirCombat.cs 作者:lenovo 邮箱: 日期:2023/7/31 20:29:31 功能: 飞机大战的框架整理汇总 *****************************************************/ using LitJson; using System; using System.Collections; using System.Collections.Generic; using UnityEditor.VersionControl; using UnityEngine; using UnityEngine.UI; using UnityEngine.XR; using static BindUtil; using Random = UnityEngine.Random; public class Framework_AirCombat : MonoBehaviour { #region 生命 /// <summary>首次载入且Go激活</summary> void Start() { //UI { View(); LifeTime(); Controller(); LifeTime_Controller(); SpecificUI_MainUI(); SpecificUI_Effect(); SpecificUI_GameUI(); } Manager(); Reader(); Attribute(); Config(); Util(); Loader(); Data(); TaskQueue(); Message(); Action(); Pool(); Coroutine(); Model(); Singleton(); Test(); //游戏中的 { Path(); Input(); Behaviour(); Ani(); Bullet(); BulletMgr(); Component(); Effect(); EffectView(); EnemyCreater(); GameProcess(); Factory(); Map(); InitGame(); PlayerController(); Trajectory(); SpecialState(); View_Logic(); GameEvent gameEvent; Guide(); } } #endregion #region 辅助 private void SpecialState() { LevelUpState levelUpState; // IBuff iBuff; IBuffCarrier iBuffCarrier; IDebuff iDeff; IDebufferCarrier iDebufferCarrier; ISpecialState iSpecialState; SpecialStateMgrBase specialStateMgrBase; // PlayerBuffMgr playerBuffMgr; } private void Trajectory() { ITrajectory iTrajectory; EllipseTrajectory ellipseTrajectory; RotateTrajectory rotateTrajectory; StraightTrajectory straightTrajectory; VTrajectory vTrajectory; } private void PlayerController() { PlayerController playerController; } private void InitGame() { GameLayerMgr gameLayerMgr; GameRoot gameRoot; } private void Map() { MapCloud mapCloud; MapItem mapItem; MapMgr mapMgr; } private void Factory() { ItemFactory itemFactory; PathFactory pathFactory; SpecialStateFactory specialStateFactory; } private void EnemyCreater() { IEnemyCreater iEnemyCreater; MissileEnemyCreater missileEnemyCreater; PlaneEnemyCreater planeEnemyCreater; // ISubEnemyCreaterMgr iSubEnemyCreaterMgr; BossCreaterMgr bossCreaterMgr; ElitesCreaterMgr elitesCreaterMgr; EnemyCreaterMgr enemyCreaterMgr; MissileCreaterMgr missileCreaterMgr; NormalCreaterMgr normalCreaterMgr; // LoadCreaterData loadCreaterData; GameProcess(); } private void GameProcess() { GameProcessMgr gameProcessMgr; GameProcessNormalEvent gameProcessNormalEvent; GameProcessTriggerEvent gameProcessTriggerEvent; IGameProcessNormalEvent iGameProcessNormalEvent; IGameProcessTriggerEvent iGameProcessTriggerEvent; } private void Component() { AutoDespawnComponent autoDespawnComponent; DestroyDelay autoDestroyComponent; // BossBulletEventComponent bossBulletEventComponent; BulletCollideMsgComponent bulletCollideMsgComponent; CameraMove cameraMove; ColliderComponent colliderComponent; EnemyTypeComponent enemyTypeComponent; IColliderMsg colliderMsg; IComponent iComponent; ItemCollideMsgComponent itemCollideMsgComponent; LifeComponent lifeComponent; MoveComponent moveComponent; PlaneCollideMsgComponent planeCollideMsgComponent; RenderComponent renderComponent; } private void BulletMgr() { BulletEffectMgr bulletEffectMgr; EmitBulletMgr emitBulletMgr; EnemyBulletMgr enemyBulletMgr; SpawnBulletPointMgr spawnBulletPointMgr; } private void Bullet() { IBullet iBullet; Bullet bullet; BulletMgr(); } private void Behaviour() { IBehaviour iBehaviour; PlayerBehaviour playerBehaviour; EnemyBehaviour enemyBehaviour; BulletBehaviour bulletBehaviour; } private void Path() { IPath iPath; PathBase pathBase; EllipsePath ellipsePath; EnterPath enterPath; EnterPath.MoveDirection moveDirection; StayOnTopPath stayOnTopPath; StraightPath straightPath; WPath wPath; PathMgr pathMgr; // IEnterPath iEnetrPath; RightToLeft rightToLeft; LeftToRight leftToRight; UpToDown upToDown; } private void Test() { BulletConfigTest bulletConfigTest; ITest iTest; MsgEventTest msgEventTest; ShowFPS showFPS; } private void Manager() { AudioMgr audioMgr; ConfigMgr configMgr; CoroutineMgr coroutineMgr; DataMgr dataMgr; DelayDetalCoroutineMgr delayDetalCoroutineMgr; InputMgr inputMgr; LifeCycleMgr lifeCycleMgr; LoadMgr loadMgr; MessageMgr messageMgr; PoolMgr poolMgr; ReaderMgr readerMgr; SceneMgr sceneMgr; SubMsgMgr subMsgMgr; TaskQueueMgr taskQueueMgr; TestMgr testMgr; UILayerMgr uiLayerMgr; UIManager uiManager; // PathMgr pathMgr; BulletMgr(); // GameDataMgr gameDataMgr; // GuideMgr guideMgr; } private void SpecificUI_GameUI() { GameResultController gameResultController; GameUIController gameUIController; LifeController lifeController; LifeItemController lifeItemController; PowerController powerController; SettingController settingController; ShieldController shieldController; // GameResultView gameResultView; GameUIView gameUIView; Life life; LifeItem lifeItem; Power power; SettingView settingView; Shield shield; Warning warning; } private void Ani() { AniMgr aniMgr; FrameAni frameAni; PlayerEnterAni playerEnterAni; } private void SpecificUI_Effect() { ItemCDEffect itemCDEffect; ItemEffect itemEffect; } /// <summary>具体的面板</summary> private void SpecificUI_MainUI() { HeroItemController heroItemController; LevelItemController levelItemController; LevelRootController levelRootController; LevelsController levelsController; LoadingController loadingController; PlanePropertyController planePropertyController; PropertyItemController propertyItemController; SelectedHeroController selectedHeroController; SelectHeroController selectHeroController; StartController startController; StrengthenController strengthenController; SwitchPlayerController switchPlayerController; // DialogView dialogView; HeroItem heroItem; LevelItem levelItem; LevelRoot levelRoot; LevelsView levelsView; LoadingView loadingView; Money money; PlaneProperty planeProperty; PropertyItem propertyItem; SelectedHeroView selectedHeroView; SelectHero selectHero; StrengthenView strengthenView; SwitchPlayer switchPlayer; } private void Singleton() { MonoSingleton<AMono> monoSingleton; NormalSingleton<A> normalSingleton; } private void LifeTime_Controller() { IControllerInit iControllerInit; IControllerShow iControllerShow; IControllerHide iControllerHide; IControllerUpdate iControllerUpdate; } private void Controller() { IController iController; LifeTime_Controller(); ControllerBase controllerBase; } private void Model() { GameModel gameModel; GameStateModel gameStateModel; PlaneSpritesModel planeSpritesModel; // IBullet iBullet; IBulletModel iBulletModel; IEnemyBulletModel iEnemyBulletModel; IEnemyBossBulletModel iEnemyBossBulletModel; EnemyBossBulluetModelBase enemyBossBulluetModelBase; EnemyBoss0BulluetModel enemyBoss0BulluetModel; EnemyBoss1BulluetModel enemyBoss1BulluetModel; EnemyBulluetModel enemyBulluetModel; PlayerBulletModel playerBulletModel; PowerBulletModel powerBulletModel; } private void Coroutine() { CoroutineItem.CoroutineState coroutineState; CoroutineItem coroutineItem; DelayDetalCoroutineItem delayDetalCoroutineItem; CoroutineController coroutineController; } private void Pool() { GameObjectPool gameObjectPool; ObjectPool<A> objectPool; } private void Action() { ActionMgr actionMgr; } private void Message() { IMessageSystem iMessageSystem; MessageSystem messageSystem; } private void Input() { IInputModule iInputModule; InputModule inputModule; InputState inputState; InputMgr inputMgr; } private void View() { LifeTime(); IView iView; ViewBase viewBase; // LevelRoot levelRoot; View_Logic(); } void View_Logic() { // Enemy EnemyLifeItem enemyLifeItem; EnemyLifeView enemyLifeView; MissileView missileView; MissileWarning missileWarning; PlaneEnemyView planeEnemyView; // ItemView AddBulletView addBulletView; AddExpView addExpView; ItemViewBase itemViewBase; PowerItemView powerItemView; ShieldItemView shieldItemView; StarView starView; // BulletDestroyAniView bulletDestroyAniView; IGameView iGameView; PlaneDestroyAniView planeDestroyAniView; PlayerView playerView; PowerView powerView; ShieldView shieldView; } private void TaskQueue() { TaskQueue taskQueue; TaskQueueMgr taskQueueMgr; LevelRoot levelRoot; } private void Data() { IDataMemory iDataMemory; PlayerPrefsMemory playerPrefsMemory; JsonMemory jsonMemory; DataMgr dataMgr; // //Logic/Data { AllEnemyData allEnemyData; EnemyData enemyData; // AllBulletData allBulletData; BulletData bulletData; NormalBulletData normalBulletData; BossBulletData bossBulletData; // EnemyCreaterConfigData enemyCreaterConfigData; LevelData levelData; ICreaterData iCreaterData; PlaneCreaterData planeCreaterData; MissileCreaterData missileCreaterData; // GameDataMgr gameDataMgr; // EnemyTrajectoryDataMgr enemyTrajectoryDataMgr; ITrajectoryData iTrajectoryData; StraightTrajectoryData straightTrajectoryData; VTrajectoryData vTrajectoryData; EllipseData ellipseData; RotateData rotateData; } // } private void EffectView() { EffectViewBase effectViewBase; AddBulletEffectView addBulletEffectView; AddExpEffectView addExpEffectView; MissileWarningEffectView missileWarningEffectView; StarEffectView starEffectView; } private void Effect() { IEffect iEffect; IEffectView iEffectView; EffectViewBase effectViewBase; FlyIntoUI flyIntoUI; RotateEffect rotateEffect; ScaleEffect scaleEffect; ShowAndHideEffect showAndHideEffect; SlowSpeedEffect slowSpeedEffect; // } private void Loader() { ILoader loader; ABLoader abLoader; ResourceLoader resourceLoader; } private void Util() { BindUtil bindUtil; BulletUtil bulletUtil; DataMgr.Single.SetJsonData("key", new JsonData());//DataUtil Empty4Raycast empty4Raycast; transform.ButtonAction("xxx", () => { }); GameUtil gameUtil; JsonUtil jsonUtil; KeysUtil keysUtil; UiUtil uiUtil; // BulletTrajectoryDataUtil bulletTrajectoryDataUtil; // Guide_Util(); } void Guide_Util() { GuideGenerateIDTool guideGenerateIDTool; } void Guide() { Guide_Util(); // Guide_Frame(); Guide_Business(); GuideMgr guideMgr; } void Guide_Frame() { IGuide iGuide; IGuideRoot iGuideRoot; GuideBase guideBase; // IGuideBehaviour iGuideBehaviour; GuideBehaviourBase guideBehaviourBase; // IGuideGroup iGuideGroup; GuideGroupBase<IGuideGroup> guideGroupBase; // GuideMgr guideMgr; } void Guide_Business() { //Module ExplainDialogModule explainDialogModule; HandModule handModule; HighLightModule highLightModule; //Guide SelectedHeroViewGuide selectedHeroViewGuide; StartViewGuide startViewGuide; //Group ShowHerosGroup showHerosGroup; StartViewGroup startViewGroup; //Demo TestDemo.StartViewGuide testDemo_StartViewGuide; TestDemo.DemoGuideGroupA testDemo_DemoGuideGroupA; TestDemo.Demo1GuideGroup testDemo_Demo1GuideGroup; TestDemo.Demo2GuideGroup testDemo_Demo2GuideGroup; TestDemo.ClickButtonA testDemo_ClickButtonA; // TestDemo.GuideMgr testDemo_MuideMgr; //Behaviour ShowHerosBehaviour showHerosBehaviour; StartGameBehaviour startGameBehaviour; WelcomeGuideBehaviour welcomeGuideBehaviour; } private void Config() { BulletEffectPoolConfig bulletEffectPoolConfig; LifeCycleAddConfig lifeCycleAddConfig; LifeCycleConfig lifeCycleConfig; PoolConfig poolConfig; ReaderConfig readerConfig; SceneConfig sceneConfig; UILayerConfig uiLayerConfig; } void Reader() { IReader reader; JsonReader jsonReader; ReaderMgr readerMgr; ReaderConfig readerConfig; // 数据单位 IKey iKey; Key key; KeyQueue keyQueue; } void Attribute() { InitCustomAttributes initCustomAttributes; BindPrefabAttribute bindPrefabAttribute; BulletAttribute bulletAttribute; // BindUtil bindUtil; BindPriorityComparer bindPriorityComparer; } void LifeTime() { IInit init; IInitParent iInitParent; IShow show; IHide hide; IUpdate update; IDestroy destroy; } #endregion #region 内部类(举例,没有实际用处) class A { } class AMono:MonoBehaviour { } #endregion }
/// <summary>轨迹</summary> private void Trajectory() { ITrajectory iTrajectory; EllipseTrajectory ellipseTrajectory; RotateTrajectory rotateTrajectory; StraightTrajectory straightTrajectory; VTrajectory vTrajectory; TrajectoryData(); Path(); } void TrajectoryData() { EnemyTrajectoryDataMgr enemyTrajectoryDataMgr; ITrajectoryData iTrajectoryData; StraightTrajectoryData straightTrajectoryData; VTrajectoryData vTrajectoryData; EllipseData ellipseData; RotateData rotateData; } private void Path() { IPath iPath; PathBase pathBase; EllipsePath ellipsePath; StayOnTopPath stayOnTopPath; StraightPath straightPath; WPath wPath; PathMgr pathMgr; // IEnterPath iEnetrPath; EnterPath enterPath; EnterPath.MoveDirection moveDirection; RightToLeft rightToLeft; LeftToRight leftToRight; UpToDown upToDown; }
PathMgr中用了PathFactory的GetDir(),就是将变化最频繁的部分摘了出来
public class PathFactory { public static IPath GetPath(TrajectoryType trajectoryType) { switch (trajectoryType) { case TrajectoryType.STRAIGHT: return new StraightPath(); case TrajectoryType.W: return new WPath(); case TrajectoryType.STAY_ON_TOP: return new StayOnTopPath(); case TrajectoryType.ELLIPSE: return new EllipsePath(); case TrajectoryType.ROTATE: Debug.LogError("PathFactory未初始该轨道:" + trajectoryType); return null; default: Debug.LogError("PathFactory的当前轨迹未添加,名称:" + trajectoryType); return null; } } }
可以看到LifeCycleMgr 初始化时就会读取json
优先用PlayerPrefers拿不到就去取json的
private void GetDataByPlayerPrefersOrJson()
{
LifeCycleMgr lifeCycleMgr;
LifeCycleAddConfig lifeCycleAddConfig;
ConfigMgr configMgr;
DataMgr dataMgr;
DataMgr.Single.SetObject("key",new object()); //PlayerPrefers
DataMgr.Single.SetJsonData("key", new JsonData());//DataUtil
}
这段主要在强化面板时用到
它会这么存
key,value
0level,0
0attackTime,1
0atttack,后面那串json
0attackname,攻击
0attackvalue,5
…
以此类推
{
"planes": [
{
"planeId": 0,
"level": 0,
"attackTime":1,
"attack": {"name":"攻击","value":5,"cost":180,"costUnit":"star","grouth":10,"maxVaue": 500},
"fireRate": {"name":"攻速","value":80,"cost":200,"costUnit":"star","grouth":1,"maxVaue": 100},
"life": {"name":"生命","value":100,"cost":200,"costUnit":"star","grouth":50,"maxVaue": 1000},
"upgrades": {"name":"升级","coefficient": 2,"max":4,"0": 100,"1": 200,"2": 300,"3": 400,"costUnit":"diamond"}
},
按图二的位置去改成相应的 大写+_(因为前面改了枚举)
但是枚举关联着资源,也就是资源名称,没必要让资源名称也变成枚举的格式,这些就不先不改,主要是AudioVolume
两个脚本,两张图轮换
private void Map()
{
MapMgr mapMgr;
MapItem mapItem;
}
private void Effect()
{
BulletDestroyAniView bulletDestroyAniView;
PlaneDestroyAniView planeDestroyAniView;
FrameAni frameAni;
}
生成脚本的命名空间
改写其中的逻辑
/// <summary>基于参照物baseRect(和放置物不同面板placeParent)和间隔offset,上下左右放置物体placeRect</summary> public static Component BaseBy(this Component t , RectTransform placeParent , RectTransform baseRect , Dir dir , float offset) { RectTransform placeRect = t.GetComponent<RectTransform>(); LayoutElement placeLayout = placeRect.GetComponent<LayoutElement>();//placeRect要有组件。 // float horizontal_LocalX = 0f; float horizontal_LocalY=0f; float vertical_LocalY=0f; float vertical_LocalX = 0f; if (dir == Dir.LEFT || dir == Dir.RIGHT) { float base_HalfW = Mathf.Abs(baseRect.rect.xMin); float panel_HalfW = placeParent.rect.width / 2; float text_AfterW = panel_HalfW - (base_HalfW + offset); placeLayout.preferredWidth = (text_AfterW < placeParent.rect.width) ? text_AfterW : -1; // horizontal_LocalX = (panel_HalfW - text_AfterW / 2); horizontal_LocalY = placeRect.transform.World2Local(baseRect).y; } if (dir == Dir.UP || dir == Dir.DOWN) { float base_HalfH = Mathf.Abs(baseRect.rect.yMin); float panel_HalfH = placeParent.rect.height / 2; float text_AfterH = panel_HalfH - (base_HalfH + offset); placeLayout.preferredWidth = (text_AfterH < placeParent.rect.width) ? text_AfterH : -1; // vertical_LocalY = (panel_HalfH - text_AfterH / 2); vertical_LocalX = placeRect.transform.World2Local(baseRect).x; } switch (dir) { case Dir.LEFT: { placeRect.transform.localPosition = new Vector3(-horizontal_LocalX, horizontal_LocalY); } break; case Dir.RIGHT: { placeRect.transform.localPosition = new Vector3(horizontal_LocalX, horizontal_LocalY); } break; case Dir.UP: { placeRect.transform.localPosition = new Vector3(vertical_LocalX, vertical_LocalY); } break; case Dir.DOWN: { placeRect.transform.localPosition = new Vector3(vertical_LocalX, -vertical_LocalY); } break; default: break; } return placeRect; }
using UnityEngine; using UnityEngine.UI; using QFramework; namespace QFramework.Example { public class StartGamePanelData : UIPanelData { } public partial class StartGamePanel : UIPanel { protected override void OnInit(IUIData uiData = null) { mData = uiData as StartGamePanelData ?? new StartGamePanelData(); // please add init code here ResKit.Init(); if (true) { StartGameBtn.onClick.AddListener(() => { UIKit.OpenPanel<SelectHeroPanel>(); CloseSelf(); }); } else //原来的写法。重名了报错 { //UIManager.Single.Show(Paths.PREFAB_SELECTED_HERO_VIEW); } AudioMgr.Single.PlayBGM(); } protected override void OnOpen(IUIData uiData = null) { } protected override void OnShow() { } protected override void OnHide() { } protected override void OnClose() { } } }
图一是无效的
图二不加就可以设置
AudioMgr
LoadMgr
ResourceLoade
ILoader
private void InitClips()
{
var clips = LoadMgr.Single.LoadAll<AudioClip>(Paths.AUDIO_FOLDER);
foreach (var clip in clips)
{
_clips.Add(clip.name, clip);
}
}
public interface ILoader
{
GameObject LoadPrefab(string path);
GameObject LoadPrefabAndInstantiate(string path, Transform parent = null);
void LoadConfig(string path, Action<object> complete);
T Load<T>(string path) where T : Object;
T[] LoadAll<T>(string path) where T : Object;
}
ResourceLoader
CoroutineMgr
CoroutineController
CoroutineItem
CoroutineState
相应脚本
Assets/Scripts/Manager/TestMgr.cs
Assets/Scripts/Test
01 类名与脚本名不一致
02 节点上加的脚本与已有的冲突(两个脚本都:Graphic)
对相应的脚本进行Reimport
目前遇到的两个拼UI
01 Andy使用的父节点是有一定的宽和高的(改动过)
02 忘记了是哪个视频(好像是siki学院,Plane的暗黑破坏神教程),他采用的是LeftTopPin(命名方式)的父节点,父节点的高宽都是默认的(100高,100宽)。就是你在某一个分辨率(指Game窗口下的那个分辨率)随便拼UI,最后用空节点(默认)锚定(左上,右上等),将随便拼的UI(在左上,右下等),拖到那个空节点
发现QF有两种UI思路。
一种是IController+Command,Event
一种是能自动生成Desigher的那种,就没有继承IController
主要是这3个属性。整个框架也是复制QF的PointGame的
/// <summary>实际使用的是在父节点中的索引</summary>
BindableProperty<int> SelectHeroID { get; }
/// <summary>选中后变化的颜色</summary>
BindableProperty<Color> SelectHeroColor { get; }
/// <summary>选中后变化颜色需要的时间</summary>
BindableProperty<float> SelectHeroColorTime { get; }
#region Model internal class PlaneModel { } internal interface IPlaneModel { } // 1. 定义一个 Model 对象 public interface IAirCombatAppModel : IModel { BindableProperty<int> Star { get; } BindableProperty<int> Diamond { get; } BindableProperty<int> SelectPlaneID { get; } /// <summary>实际使用的是在父节点中的索引</summary> BindableProperty<int> SelectHeroID { get; } BindableProperty<Color> SelectHeroColor { get; } BindableProperty<float> SelectHeroColorTime { get; } } public class AirCombatAppModel : AbstractModel, IAirCombatAppModel { public BindableProperty<int> Star { get; } = new BindableProperty<int>(); public BindableProperty<int> Diamond { get; } = new BindableProperty<int>(); public BindableProperty<int> SelectPlaneID { get; } = new BindableProperty<int>(); public BindableProperty<int> SelectHeroID { get; } = new BindableProperty<int>(); public BindableProperty<Color> SelectHeroColor { get; } = new BindableProperty<Color>(); public BindableProperty<float> SelectHeroColorTime { get; } = new BindableProperty<float>(); protected override void OnInit() { IStorage storage = this.GetUtility<IStorage>(); // 设置初始值(不触发事件) Star.SetValueWithoutEvent(storage.LoadInt(nameof(Star))); Diamond.SetValueWithoutEvent(storage.LoadInt(nameof(Diamond))); SelectHeroID.SetValueWithoutEvent(storage.LoadInt(nameof(SelectHeroID))); SelectPlaneID.SetValueWithoutEvent(storage.LoadInt(nameof(SelectPlaneID))); SelectHeroColor.SetValueWithoutEvent(storage.LoadString(nameof(SelectHeroColor)).ToColor()); SelectHeroColorTime.SetValueWithoutEvent(storage.LoadFloat(nameof(SelectHeroColorTime))); // 当数据变更时 存储数据 Star.Register(newCount => { storage.SaveInt(nameof(Star), newCount); }); Diamond.Register(newCount => { storage.SaveInt(nameof(Diamond), newCount); }); SelectHeroID.Register(newCount => { storage.SaveInt(nameof(SelectHeroID), newCount); }); SelectPlaneID.Register(newCount => { storage.SaveInt(nameof(SelectPlaneID), newCount); }); SelectHeroColor.Register(newCount => { storage.SaveString(nameof(SelectHeroColor), newCount.ToString()); }); SelectHeroColorTime.Register(newCount => { storage.SaveFloat(nameof(SelectHeroColorTime), newCount); }); } } #endregion
主要是
01 Color.gray,0.5f,这个两个参数应该是写死的,但为了方便改动,协程可以设置的
02 HeroSelectable,控制选择效果和其它
this.SendCommand(new SetSelectHeroParaCommand(Color.gray,0.5f));
foreach (RectTransform rect in HeroTrans)
{
_heroRectLst.Add(rect);
}
foreach (var rect in _heroRectLst)
{
rect.AddComponentIfNull<HeroSelectable>();
}
using UnityEngine; using UnityEngine.UI; using QFramework; using System.Collections.Generic; namespace QFramework.AirCombat { public class SelectHeroPanelData : UIPanelData { } public partial class SelectHeroPanel : UIPanel ,IController { List<RectTransform> _heroRectLst = new List<RectTransform>(); protected override void OnInit(IUIData uiData = null) { mData = uiData as SelectHeroPanelData ?? new SelectHeroPanelData(); // please add init code here #region 原文 /** foreach (Transform trans in HeroTrans) { trans.AddComponent<HeroItem>(); trans.AddComponent<HeroItemController>(); } HeroItem heroItem; HeroItemController heroItemController; SelectHero selectHero; SelectHeroController selectHeroController; SelectedHeroView selectedHeroView; SelectedHeroController selectedHeroController; **/ #endregion #region 初始化 this.SendCommand(new SetSelectHeroParaCommand(Color.gray,0.5f)); foreach (RectTransform rect in HeroTrans) { _heroRectLst.Add(rect); } foreach (var rect in _heroRectLst) { rect.AddComponentIfNull<HeroSelectable>(); } #endregion #region 按钮 StartBtn.onClick.AddListener(() => { //UIManager.Single.Show(Paths.PREFAB_LEVELS_VIEW); "进入游戏".LogInfo(); }); StrengthenBtn.onClick.AddListener(() => { this.SendCommand < OpenStrengthenPanelCommand>(); CloseSelf(); }); ExitBtn.onClick.AddListener(() => { this.SendCommand<ExitGameCommand>(); }); #endregion } #region 辅助 protected override void OnOpen(IUIData uiData = null) { } protected override void OnShow() { } protected override void OnHide() { } protected override void OnClose() { } public IArchitecture GetArchitecture() { return AirCombatApp.Interface; } #endregion } }
响应就是 this.RegisterEvent
/**************************************************** 文件:HeroSelectable.cs 作者:lenovo 邮箱: 日期:2023/8/12 19:4:2 功能: *****************************************************/ using QFramework.AirCombat; using QFramework; using System.Collections; using System.Collections.Generic; using UnityEngine; using Random = UnityEngine.Random; using UnityEngine.UI; using DG.Tweening; namespace QFramework.AirCombat { public class HeroSelectable : MonoBehaviour ,IController { #region 属性 #endregion #region 生命 /// <summary>首次载入且Go激活</summary> void Start() { this.RegisterEvent<SelectHeroEvent>( _ => { int idx = transform.GetSiblingIndex(); IAirCombatAppModel model = this.GetModel<IAirCombatAppModel>(); Image image = GetComponent<Image>(); bool selected = idx == model.SelectHeroID; if (selected) { image.DOKill(); image.DOColor(model.SelectHeroColor, model.SelectHeroColorTime); } else { image.DOKill(); image.DOColor(Color.white, model.SelectHeroColorTime); } }); GetComponent<Button>().onClick.AddListener(() => { IAirCombatAppModel model = this.GetModel<IAirCombatAppModel>(); Debug.Log("HeroSelectable"); // this.SendCommand(new SelectHeroCommand(transform.GetSiblingIndex())); }); } #endregion #region 实现 public IArchitecture GetArchitecture() { return AirCombatApp.Interface; } #endregion } }
public class SelectHeroCommand : AbstractCommand { int _heroIdx = 0; public SelectHeroCommand(int heroIdx) { _heroIdx = heroIdx; } protected override void OnExecute() { this.GetModel<IAirCombatAppModel>().SelectHeroID.Value = _heroIdx; this.SendEvent<SelectHeroEvent>(); } }
AudioMgr.Single.Stop(cur.Index2String<Hero>());
public class SelectHeroCommand : AbstractCommand { int _heroIdx = 0; public SelectHeroCommand(int heroIdx) { _heroIdx = heroIdx; } protected override void OnExecute() { int cur = this.GetModel<IAirCombatAppModel>().SelectHeroID.Value; this.GetModel<IAirCombatAppModel>().SelectHeroID.Value = _heroIdx; AudioMgr.Single.Stop(cur.Index2String<Hero>()); this.SendEvent<SelectHeroEvent>(); } }
AudioMgr.Single.Play(idx.Index2String<Hero>());
/**************************************************** 文件:HeroSelectable.cs 作者:lenovo 邮箱: 日期:2023/8/12 19:4:2 功能: *****************************************************/ using QFramework.AirCombat; using QFramework; using System.Collections; using System.Collections.Generic; using UnityEngine; using Random = UnityEngine.Random; using UnityEngine.UI; using DG.Tweening; using System.Runtime.ConstrainedExecution; namespace QFramework.AirCombat { public class HeroSelectable : MonoBehaviour ,IController { #region 属性 #endregion #region 生命 /// <summary>首次载入且Go激活</summary> void Start() { this.RegisterEvent<SelectHeroEvent>( _ => { int idx = transform.GetSiblingIndex(); IAirCombatAppModel model = this.GetModel<IAirCombatAppModel>(); Image image = GetComponent<Image>(); bool selected = idx == model.SelectHeroID; if (selected) { AudioMgr.Single.Play(idx.Index2String<Hero>()); image.DOKill(); image.DOColor(model.SelectHeroColor, model.SelectHeroColorTime); } else { image.DOKill(); image.DOColor(Color.white, model.SelectHeroColorTime); } }); ......
这块是需要 根据英雄的兄弟索引 去转对应值的 Hero枚举 ,枚举对应的字符串
/**************************************************** 文件:ExtendEnum.cs 作者:lenovo 邮箱: 日期:2023/7/24 18:0:35 功能: *****************************************************/ using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using Random = UnityEngine.Random; public static partial class ExtendEnum //转来转去 { public enum ExtendEnum_XXX { A=0, B=1, C=2, } public static void Example() { ExtendEnum_XXX para = ExtendEnum_XXX.A; string str = para.ToString(); int idx = (int)para; Debug.LogFormat("String2Enum:({0}){1}" , str.String2Enum<ExtendEnum_XXX>().GetType() , str.String2Enum<ExtendEnum_XXX>() ); Debug.LogFormat("Index2Enum:({0}){1}" , idx.Index2Enum<ExtendEnum_XXX>().GetType() , idx.Index2Enum<ExtendEnum_XXX>() ); // Debug.LogFormat("String2Index:({0}){1}" , str.String2Index<ExtendEnum_XXX>().GetType() , str.String2Index<ExtendEnum_XXX>() ); Debug.LogFormat("Enum2Index:({0}){1}" , para.Enum2Index().GetType() , para.Enum2Index() ); // Debug.LogFormat("Index2String:({0}){1}" , idx.Index2String<ExtendEnum_XXX>().GetType() , idx.Index2String<ExtendEnum_XXX>() ); Debug.LogFormat("Enum2String:({0}){1}" , para.Enum2String().GetType() , para.Enum2String() ); } /// <summary>字符串转枚举</summary> public static T String2Enum<T>(this string str) where T:Enum { return (T)Enum.Parse(typeof(T), str); } /// <summary.值转枚举</summary> public static T Index2Enum<T>(this int idx) where T : Enum { string str= Enum.GetName(typeof(T), idx); return str.String2Enum <T>(); } public static int String2Index<T>(this string str) where T : Enum { T t= (T)Enum.Parse(typeof(T), str); return (int)Enum.Parse(typeof(T), str); } public static int Enum2Index<T>(this T t) where T : Enum { string str= t.ToString(); return (int)Enum.Parse(typeof(T), str); } public static string Index2String<T>(this int idx) where T : Enum { return Enum.GetName(typeof(T), idx); } public static string Enum2String<T>(this T t) where T : Enum { return t.ToString(); } }
public static ButtonClickedEvent AddListenerAfterRemoveAll(this ButtonClickedEvent onClick
, UnityAction action)
{
onClick.RemoveAllListeners();
onClick.AddListener(action);
return onClick;
}
初始化改成设置父节点时,把数据初始化的方法去掉了
在VS修改脚本后,回到Unity,,此时Unity处于打开带有改脚本的一个预制体中,然后卡死
/// <summary>不为空就执行</summary>
public static Action DoIfNotNull(this Action cb)
{
if (cb != null)
{
cb();
}
return cb;
}
效果
public void UpdateFunc()
{
Image.fillAmount -= Time.deltaTime / Const.CD_EFFECT_TIME;
if (Image.fillAmount <= 0)
{
LifeCycleMgr.Single.Remove(LifeName.UPDATE, this);
_cb.DoIfNotNull();
}
}
ActionMgr.Execute(T t)可以改
public static void Example()
{
Action<int> intAction = (para) => { Debug.Log(para.ToString()); };
intAction.DoIfNotNull<int>(99);
}
public static Action<T> DoIfNotNull<T>(this Action<T> cb,T t)
{
if (cb != null)
{
cb(t);
}
return cb;
}
把主体的代码拆出去以后复用,所以区别就是项目多加了声音事件
using System; using UnityEngine; using UnityEngine.UI; public static class ExtendUtil { /// <summary> /// 类似于 transform.ButtonAction("Add", AddAction); /// <para /> 类似于transform.ButtonAction("OK/Start", () => { UIManager.Single.Show(Paths.PREFAB_LEVELS_VIEW); }); /// </summary> public static void ButtonAction(this Transform trans , string path , Action action , bool useDefaultAudio = true) { if (useDefaultAudio) { action += AddButtonAudio; } trans.ButtonAction_Common(path,action); } private static void AddButtonAudio() { AudioMgr.Single.PlayOnce(UIAduio.UI_ClickButton.ToString()); } }
/// <summary> /// 类似于 transform.ButtonAction("Add", AddAction); /// <para /> 类似于transform.ButtonAction("OK/Start", () => { UIManager.Single.Show(Paths.PREFAB_LEVELS_VIEW); }); /// </summary> public static void ButtonAction_Common(this Transform trans , string path , Action action) { var tar = trans.Find(path); if (tar == null) { Debug.LogError("ButtonAction查找物体为空,路径为:" + path); } else { var button = tar.GetComponent<Button>(); if (button == null) { Debug.LogError("ButtonAction物体上没有Button组件,物体名称:" + tar.name); } else { button.onClick.AddListener(() => action()); } } }
DataMgr.Single.ClearAll();
{ //弄点数据
DataMgr.Single.Set(DataKeys.STAR,666);
DataMgr.Single.Set(DataKeys.DIAMOND,100);
//按他的设置来设置的话
GameStateModel.Single.SetMoney(DataKeys.STAR,666);
GameStateModel.Single.SetMoney(DataKeys.DIAMOND,100);
}
if (false)
{
// Util.Get("Star/BG/Text").SetText(DataMgr.Single.Get<int>(DataKeys.STAR));
//Util.Get("Diamond/BG/Text").SetText(DataMgr.Single.Get<int>(DataKeys.DIAMOND));
}
else
{
StarText.SetText(DataMgr.Single.Get<int>(DataKeys.STAR));
DiamondText.SetText(DataMgr.Single.Get<int>(DataKeys.DIAMOND));
//DataMgr.Single.Get<int>(DataKeys.STAR).LogInfo();
//DataMgr.Single.Get<int>(DataKeys.STAR).LogInfo();
}
DataMgr在PlayerPrefs的数据拿不到就去那Json拿。
方法是ConfigMgr在Init()时,
用到了DataUtil.SetObjectData(string oldkey, JsonData data)。
。。。
ConfigMgr由LifeCycleMgr调用LifeCycleAddConfig时用到
。。
结果是数据初始比较慢,导致打开强化面板时数据还没初始好
private void GetDataByPlayerPrefersOrJson()
{
LifeCycleMgr lifeCycleMgr;
LifeCycleAddConfig lifeCycleAddConfig;
ConfigMgr configMgr;
DataMgr dataMgr;
DataMgr.Single.SetJsonData("key", new JsonData());//DataUtil
}
public static Transform SetText(this Transform trans, object obj) { Text text = trans.GetComponent<Text>(); if (text == null) { throw new System.Exception("SetText异常"); } if (text != null) { text.text = obj.ToString(); } // return trans; } public static GameObject SetText(this GameObject go, object obj) { Text text = go.GetComponent<Text>(); if (text == null) { throw new System.Exception("SetText异常"); } if (text != null) { text.text = obj.ToString(); } // return go; }
InitAddBtn在切换飞机时变,点击 addBtn不变
UodateAllUI在切换飞机和点击addBtn都变
//中间的SwitchPlayer { //默认设置 GameStateModel.Single.SelectedPlaneId = DataMgr.Single.Get<int>(DataKeys.PLANE_ID); int id, level; id = GameStateModel.Single.SelectedPlaneId; level = GameStateModel.Single.PlaneLevel; InitAddBtn(id); UpdateAllUI(id, level); // LeftBtn.onClick.AddListener(() => { id = SwitchPlaneID( id, -1); level = GameStateModel.Single.PlaneLevel; InitAddBtn(GameStateModel.Single.SelectedPlaneId); UpdateAllUI(id, level); }); RightBtn.onClick.AddListener(() => { id = SwitchPlaneID( id, 1); level = GameStateModel.Single.PlaneLevel; InitAddBtn(id); UpdateAllUI(id, level); }); }
using UnityEngine; using UnityEngine.UI; using QFramework; using System.Collections.Generic; using ItemKey = PropertyItem.ItemKey; using LitJson; using System.Numerics; using Newtonsoft.Json.Linq; namespace QFramework.AirCombat { public class StrengthenPanelData : UIPanelData { } public partial class StrengthenPanel : UIPanel { #region 字属 List<RectTransform> _propertyItemLst=new List<RectTransform>(); #endregion protected override void OnInit(IUIData uiData = null) { mData = uiData as StrengthenPanelData ?? new StrengthenPanelData(); _propertyItemLst.Add(PropertyItem_Attack); _propertyItemLst.Add(PropertyItem_FireRate); _propertyItemLst.Add(PropertyItem_Life); #region 原文 // please add init code here //if (false) //{ // Util.Get("Money").Go.AddComponent<Money>(); // Util.Get("Switchplayer").Go.AddComponent<SwitchPlayer>(); // Util.Get("Property").Go.AddComponent<PlaneProperty>(); //Slider //} //else //{ //} //中间的飞机数据,3条Slider。Property做的事 //PlaneProperty,PropertyItem { // _propertyItemLst = new List<PropertyItem>((int)Property.COUNT); //for (Property i = 0; i < Property.COUNT; i++) //{ // GameObject go = LoadMgr.Single.LoadPrefabAndInstantiate(Paths.PREFAB_PROPERTY_ITEM, transform); // PropertyItem item = go.AddComponent<PropertyItem>(); // item.Init(i.ToString()); // _propertyItemLst.Add(item); //} } #endregion //上方的Money if (false) { // Util.Get("Star/BG/Text").SetText(DataMgr.Single.Get<int>(DataKeys.STAR)); //Util.Get("Diamond/BG/Text").SetText(DataMgr.Single.Get<int>(DataKeys.DIAMOND)); } else { UpdateMoneyText(); //DataMgr.Single.Get<int>(DataKeys.STAR).LogInfo(); //DataMgr.Single.Get<int>(DataKeys.STAR).LogInfo(); } //中间的SwitchPlayer { //默认设置 GameStateModel.Single.SelectedPlaneId = DataMgr.Single.Get<int>(DataKeys.PLANE_ID); int id, level; id = GameStateModel.Single.SelectedPlaneId; UpdateAllUI(); // LeftBtn.onClick.AddListener(() => { id = SwitchPlaneID( id, -1); UpdateAllUI(); }); RightBtn.onClick.AddListener(() => { id = SwitchPlaneID( id, 1); UpdateAllUI(); }); } InitBackBtn(); } #region 重写 其它 protected override void OnOpen(IUIData uiData = null) { } protected override void OnShow() { } protected override void OnHide() { } protected override void OnClose() { } #endregion #region 辅助 /// <summary>更细能改界面所有元素</summary> void UpdateAllUI() { int planeId = GameStateModel.Single.SelectedPlaneId; int level = GameStateModel.Single.PlaneLevel; // UpdateMoneyText(); UpdatePlaneSprite(planeId, level); foreach (var rect in _propertyItemLst) { InitAddButton(planeId, rect); UpdateText_Name_Value_Cost(planeId, rect); UpdateSlider_Value_MaxVaue(planeId, rect); } InitUpgradesBtn(planeId, level); UpdateUpgradesText(planeId); } void InitUpgradesBtn(int planeId, int level) { UpgradesBtn.onClick.RemoveAllListeners(); UpgradesBtn.onClick.AddListener(() => { InitUpgradesBtnAction(planeId); UpdateAllUI(); }); } void InitBackBtn() { BackBtn.onClick.AddListener(() => { //SelectHeroPanel的push由SelectHeroPanel操作 UIKit.Back<SelectHeroPanel>(); CloseSelf(); }); } void UpdateMoneyText() { DiamondText.SetText(GameStateModel.Single.GetDiamond()); StarText.SetText(GameStateModel.Single.GetStar()); } private void InitUpgradesBtnAction(int planeId) { string pre = planeId + DataKeys.UPGRADES; // int curMoney = GameStateModel.Single.GetDiamond(); //自己的前不用加pre // int maxLevel = GameStateModel.Single.PlaneLevelMax; int curLevel = GameStateModel.Single.PlaneLevel; int afterLevel = curLevel; // string costKey = KeysUtil.GetPropertyKeys(pre + curLevel);//0upgrades0:300 的冒号左边 int costMoney = DataMgr.Single.Get<int>(costKey); //300 int afterMoney = curMoney - costMoney; if (afterMoney >= 0 && curLevel < maxLevel-1)//有钻石&&上升空间 (0,1,2,3,max=4) { if (afterLevel >= maxLevel)//到顶了 { afterLevel = maxLevel; } else { afterLevel = curLevel + 1; } GameStateModel.Single.SetDiamond(afterMoney); DataMgr.Single.SetObject(planeId + DataKeys.LEVEL, afterLevel); // var key = KeysUtil.GetPropertyKeysWithoutPlaneId(DataKeys.UPGRADES_RATIO); var level = GameStateModel.Single.PlaneLevel; level++; DataMgr.Single.Set(key, level); } else { Debug.Log("你没钻石了或者等级到顶了!"); // UIManager.Single.ShowDialog("你没星星了!"); } } private void InitAddButtonAction(int planeId, RectTransform rect) { string property = (rect.name).TrimName(TrimNameType.DashAfter).LowerFirstLetter();//attack,fireRate,life string pre = planeId + property ; int curMoney = GameStateModel.Single.GetStar(); //自己的前不用加pre // string costKey = KeysUtil.GetPropertyKeys( pre + PropertyItem.ItemKey.cost); int costMoney = DataMgr.Single.Get<int>(costKey); int afterMoney = curMoney - costMoney; // int addValue= DataMgr.Single.Get<int>(pre + ItemKey.grouth); int maxValue= DataMgr.Single.Get<int>(pre + ItemKey.maxVaue); int curValue= DataMgr.Single.Get<int>(pre + ItemKey.value); int afterValue = curValue; if (afterMoney >= 0 && curValue< maxValue)//有钱&&上升空间 { if (afterValue >= maxValue)//到顶了 { afterValue = maxValue; } else { afterValue = curValue + addValue; } GameStateModel.Single.SetStar(afterMoney); DataMgr.Single.SetObject(planeId + property + ItemKey.value, afterValue); UpdateAllUI(); } else { Debug.Log("你没星星了或者数值到顶了!"); // UIManager.Single.ShowDialog("你没星星了!"); } } void InitAddButton(int planeId,RectTransform rect) { Button addBtn = rect.GetComponentDeep<Button>("Add"); addBtn.onClick.RemoveAllListeners();//切换不同id就重置 addBtn.onClick.AddListener(() => { InitAddButtonAction(planeId, rect); }); Debug.Log( "AddBtn数量"+addBtn.onClick.GetPersistentEventCount()) ; } /// <summary>name,value,cost三个文本</summary> private void UpdateText_Name_Value_Cost(int planeId, RectTransform rect) { #region 说明 /** { "planes": [ { "planeId": 0, "level": 0, "attackTime":1, "attack": { "name":"攻击","value":5,"cost":200,"costUnit":"star","grouth":10,"maxVaue": 500}, "fireRate": { "name":"攻速","value":80,"cost":200,"costUnit":"star","grouth":1,"maxVaue": 100}, "life": { "name":"生命","value":100,"cost":200,"costUnit":"star","grouth":50,"maxVaue": 1000}, "upgrades": { "name":"升级","coefficient": 2,"max":4,"0": 100,"1": 200,"2": 300,"3": 400,"costUnit":"diamond"} }, ...... ], "planeSpeed": 1.2 } **/ #endregion // attack,fireRate,life string property = (rect.name).TrimName(TrimNameType.DashAfter).LowerFirstLetter();//attack,fireRate,life //name,value,cost三个文本 for (ItemKey propertyKey = 0; propertyKey < PropertyItem.ItemKey.grouth; propertyKey++) { string transName = PropertyItem.UpperFirstLetter(propertyKey); //Name //例如Name,Value,Cost,这个Transform Transform trans = rect.Find( transName ); if (trans != null) { string key = KeysUtil.GetPropertyKeys(planeId, property + propertyKey); //0attackname Debug.Log("Text:" + key ); object obj = DataMgr.Single.GetObject(key); string value = obj.ToString(); Debug.Log("Text:"+key+","+value); trans.SetText(value); } else { Debug.LogError("属性Slider预制名称错误,正确名称:" + transName); } } } /// <summary>改成根据父节点,去更新子节点</summary> private void UpdateSlider_Value_MaxVaue(int planeId, Transform trans) { string property = (trans.name).TrimName(TrimNameType.DashAfter).LowerFirstLetter();//attack Slider slider = trans.Find("Slider").GetComponent<Slider>(); string maxVaueKey = KeysUtil.GetPropertyKeys(planeId, property+ ItemKey.maxVaue); //0attackmaxVaue(原文没加l) string valueKey = KeysUtil.GetPropertyKeys(planeId , property + ItemKey.value);//0attackvalue Debug.LogFormat("Slider:{0},{1}", valueKey, maxVaueKey); slider.minValue = 0; slider.maxValue = DataMgr.Single.Get<int>(maxVaueKey); slider.value = DataMgr.Single.Get<int>(valueKey); Debug.LogFormat("Slider:{0},{1},{2}", slider.minValue, slider.value,slider.maxValue) ; } void UpdateUpgradesText(int planeId) { string pre = planeId + DataKeys.UPGRADES; int curLevel = DataMgr.Single.Get<int>(planeId + DataKeys.LEVEL); // string costKey = KeysUtil.GetPropertyKeys(pre + curLevel);//0upgrades0:300 的冒号左边 int costMoney = DataMgr.Single.Get<int>(costKey); //300 CostText.SetText(costMoney); } private int SwitchPlaneID( int id, int direction) { string str = (direction == -1) ? "左" : "右"; ( str+"键:" + id).LogInfo(); // var max = PlaneSpritesModel.Single.Count; id += direction; id = id.Clamp(0, max-1); // id = (id < 0 ) ? 0 : id >= max ? id = max - 1 : id; GameStateModel.Single.SelectedPlaneId = id; return id; } void UpdatePlaneSprite(int planeID,int level) { Sprite planeSprite = PlaneSpritesModel.Single[planeID, level]; IconImg.SetSprite(planeSprite); } #endregion } }
using System; using UnityEngine; using UnityEngine.UI; using QFramework; namespace QFramework.AirCombat { // Generate Id:a3f593c2-800c-45b3-96af-41eaf4781fcc public partial class StrengthenPanel { public const string Name = "StrengthenPanel"; [SerializeField] public UnityEngine.UI.Image BGImg; [SerializeField] public UnityEngine.UI.Text StarText; [SerializeField] public UnityEngine.UI.Text DiamondText; [SerializeField] public UnityEngine.UI.Button LeftBtn; [SerializeField] public UnityEngine.UI.Image IconImg; [SerializeField] public UnityEngine.UI.Button RightBtn; [SerializeField] public UnityEngine.UI.Button UpgradesBtn; [SerializeField] public UnityEngine.RectTransform PropertyItem_Attack; [SerializeField] public UnityEngine.RectTransform PropertyItem_FireRate; [SerializeField] public UnityEngine.RectTransform PropertyItem_Life; [SerializeField] public UnityEngine.UI.Text CostText; [SerializeField] public UnityEngine.UI.Button BackBtn; private StrengthenPanelData mPrivateData = null; protected override void ClearUIComponents() { BGImg = null; StarText = null; DiamondText = null; LeftBtn = null; IconImg = null; RightBtn = null; UpgradesBtn = null; PropertyItem_Attack= null; PropertyItem_FireRate= null; PropertyItem_Life= null; CostText = null; BackBtn = null; mData = null; } public StrengthenPanelData Data { get { return mData; } } StrengthenPanelData mData { get { return mPrivateData ?? (mPrivateData = new StrengthenPanelData()); } set { mUIData = value; mPrivateData = value; } } } }
using UnityEngine; using UnityEngine.UI; namespace QFramework.Example { class Framework { void All() { Model(); System(); Utility(); Controller(); Command(); Architecture(); } #region 辅助 void Command() { IncreaseCountCommand increaseCountCommand; DecreaseCountCommand decreaseCountCommand; } void Model() { IModel iModel; AbstractModel abstractModel; IAirCombatAppModel iCounterAppModel; CounterAppModel counterAppModel; } void System() { ISystem iSystem; IAchievementSystem iAchievementSystem; AchievementSystem achievementSystem; } void Utility() { IUtility iIUtility; IStorage iStorage; Storage storage; } void Controller() { CounterAppController counterAppController; } void Architecture() { CounterApp counterApp; } #endregion } #region Model // 1. 定义一个 Model 对象 public interface IAirCombatAppModel : IModel { BindableProperty<int> Star { get; } BindableProperty<int> Diamond { get; } } public class CounterAppModel : AbstractModel,IAirCombatAppModel { public BindableProperty<int> Star { get; } = new BindableProperty<int>(); public BindableProperty<int> Diamond { get; } = new BindableProperty<int>(); protected override void OnInit() { IStorage storage = this.GetUtility<IStorage>(); // 设置初始值(不触发事件) Star.SetValueWithoutEvent(storage.LoadInt(nameof(Star))); Diamond.SetValueWithoutEvent(storage.LoadInt(nameof(Diamond))); // 当数据变更时 存储数据 Star.Register(newCount => { storage.SaveInt(nameof(Star),newCount); }); Diamond.Register(newCount => { storage.SaveInt(nameof(Diamond), newCount); }); } } #endregion #region System public interface IAchievementSystem : ISystem { } public class AchievementSystem : AbstractSystem ,IAchievementSystem { protected override void OnInit() { this.GetModel<IAirCombatAppModel>() // -+ .Star .Register(newCount => { if (newCount == 10) { Debug.Log("触发 点击达人 成就"); } else if (newCount == 20) { Debug.Log("触发 点击专家 成就"); } else if (newCount == -10) { Debug.Log("触发 点击菜鸟 成就"); } }); } } #endregion #region Utility public interface IStorage : IUtility { void SaveInt(string key, int value); int LoadInt(string key, int defaultValue = 0); } public class Storage : IStorage { public void SaveInt(string key, int value) { PlayerPrefs.SetInt(key,value); } public int LoadInt(string key, int defaultValue = 0) { return PlayerPrefs.GetInt(key, defaultValue); } } #endregion #region Architecture // 2.定义一个架构(提供 MVC、分层、模块管理等) public class CounterApp : Architecture<CounterApp> { protected override void Init() { // 注册 System this.RegisterSystem<IAchievementSystem>(new AchievementSystem()); // 注册 Model this.RegisterModel<IAirCombatAppModel>(new CounterAppModel()); // 注册存储工具的对象 this.RegisterUtility<IStorage>(new Storage()); } protected override void ExecuteCommand(ICommand command) { Debug.Log("Before " + command.GetType().Name + "Execute"); base.ExecuteCommand(command); Debug.Log("After " + command.GetType().Name + "Execute"); } protected override TResult ExecuteCommand<TResult>(ICommand<TResult> command) { Debug.Log("Before " + command.GetType().Name + "Execute"); var result = base.ExecuteCommand(command); Debug.Log("After " + command.GetType().Name + "Execute"); return result; } } #endregion #region Command // 引入 Command public class IncreaseCountCommand : AbstractCommand { protected override void OnExecute() { var model = this.GetModel<IAirCombatAppModel>(); model.Star.Value++; } } public class DecreaseCountCommand : AbstractCommand { protected override void OnExecute() { this.GetModel<IAirCombatAppModel>().Star.Value--; // -+ } } #endregion #region Controller // Controller public class CounterAppController : MonoBehaviour , IController /* 3.实现 IController 接口 */ { // View private Button mBtnAdd; private Button mBtnSub; private Text mCountText; // 4. Model private IAirCombatAppModel mModel; void Start() { // 5. 获取模型 mModel = this.GetModel<IAirCombatAppModel>(); // View 组件获取 mBtnAdd = transform.Find("BtnAdd").GetComponent<Button>(); mBtnSub = transform.Find("BtnSub").GetComponent<Button>(); mCountText = transform.Find("CountText").GetComponent<Text>(); // 监听输入 mBtnAdd.onClick.AddListener(() => { // 交互逻辑 this.SendCommand<IncreaseCountCommand>(); }); mBtnSub.onClick.AddListener(() => { // 交互逻辑 this.SendCommand(new DecreaseCountCommand(/* 这里可以传参(如果有) */)); }); // 表现逻辑 mModel.Star.RegisterWithInitValue(newCount => // -+ { UpdateView(); }).UnRegisterWhenGameObjectDestroyed(gameObject); } void UpdateView() { mCountText.text = mModel.Star.ToString(); } // 3. public IArchitecture GetArchitecture() { return CounterApp.Interface; } private void OnDestroy() { // 8. 将 Model 设置为空 mModel = null; } } #endregion }
大部分是复制原来的,修改了这个
public class GameStart03 : MonoBehaviour ,IController
{......
ResKit.Init();
{
this.SendCommand( new OpenStrengthenPanelCommand(() =>
{
//DataMgr.Single.Set(DataKeys.STAR,666);
//DataMgr.Single.Set(DataKeys.DIAMOND,1000);
//按他的设置来设置的话
//GameStateModel.Single.SetStar(800);//有的还没改,注释掉会报错
//GameStateModel.Single.SetDiamond(1000);
this.SendCommand(new SetStarCommand(1002)); //此时强化面板未打开
this.SendCommand(new SetDiamondCommand(1002));
}));
}
using System; using System.Collections; using System.Linq; using LitJson; using QFramework; using QFramework.Example; using UnityEngine; namespace QFramework.AirCombat { public class GameStart03 : MonoBehaviour ,IController { // Use this for initialization /// <summary>首次登录,新手引导</summary> public bool IsFirst = false; private void Start() { if (FindObjectsOfType<LaunchGame>().Length > 1) { Destroy(gameObject); return; } StartCoroutine(Init()); } private void Update() { if (Input.GetKeyDown(KeyCode.P)) //确定是json数据初始慢导致强化面板获取数据失败 { OpenPanelFunc(); } } private IEnumerator Init() { yield return TestMgr.Single.Init(); yield return null; // Transform mgrTrans = transform.FindTop("Mgr"); Transform canvasTrans = transform.FindTop("Canvas"); // GameStateModel.Single.CurScene = SceneName.Main; LifeCycleMgr.Single.Init(mgrTrans); CoroutineMgr.Single.Init(mgrTrans); AudioMgr.Single.Init(mgrTrans); DataMgr.Single.ClearAll(); if (IsFirst) { GuideUiMgr.Single.Init(canvasTrans);//设置Canvas,因为我把启动脚本放外面,不放在Canvas下 GuideMgr.Single.InitGuide(); } yield return new WaitForSeconds(5f);//延时让json数据初始化 if (true) { ResKit.Init(); { this.SendCommand( new OpenStrengthenPanelCommand(() => { //DataMgr.Single.Set(DataKeys.STAR,666); //DataMgr.Single.Set(DataKeys.DIAMOND,1000); //按他的设置来设置的话 //GameStateModel.Single.SetStar(800);//有的还没改,注释掉会报错 //GameStateModel.Single.SetDiamond(1000); this.SendCommand(new SetStarCommand(1002)); //此时强化面板未打开 this.SendCommand(new SetDiamondCommand(1002)); })); } } } void OpenPanelFunc( ) { UIKit.OpenPanel<StrengthenPanel>(); } public IArchitecture GetArchitecture() { return AirCombatApp.Interface; } } }
using UnityEngine; using UnityEngine.UI; using QFramework; using System.Collections.Generic; using ItemKey = PropertyItem.ItemKey; using LitJson; using System.Numerics; using Newtonsoft.Json.Linq; using UniRx.Triggers; using System; using System.Data; namespace QFramework.AirCombat { public class StrengthenPanelData : UIPanelData { } public partial class StrengthenPanel : UIPanel,IController { #region 字属 List<RectTransform> _propertyItemLst=new List<RectTransform>(); #endregion protected override void OnInit(IUIData uiData = null) { mData = uiData as StrengthenPanelData ?? new StrengthenPanelData(); _propertyItemLst.Add(PropertyItem_Attack); _propertyItemLst.Add(PropertyItem_FireRate); _propertyItemLst.Add(PropertyItem_Life); #region Top this.RegisterEvent<ChangeStarEvent>(e => { UpdateStarText(); }); this.RegisterEvent<ChangeDiamondEvent>(e => { UpdateDiamondText(); }); #endregion #region Center //UpdateUpgradesButton(); LeftBtn.onClick.AddListener(() => { this.SendCommand(new SwitchPlaneCommand(-1)); }); RightBtn.onClick.AddListener(() => { this.SendCommand(new SwitchPlaneCommand(1)); }); this.RegisterEvent<SelectPlaneIDEvent>(eventId => { UpdatePlaneSprite(); // UpdatePropertyItems(); UpdateUpgradesButton(); }); this.RegisterEvent<IncreasePlanePropertyEvent>(eventId =>//增加属性时 { UpdateStarText(); // UpdatePropertyItems(); }); this.RegisterEvent<UpgradesPlaneLevelEvent>(eventId =>//升级时 { UpdateDiamondText(); UpdatePlaneSprite(); // UpdatePropertyItems(); UpdateUpgradesButton(); }); #endregion #region Bottom BackBtn.onClick.AddListener(() => { //SelectHeroPanel的push由SelectHeroPanel操作 UIKit.Back<SelectHeroPanel>(); CloseSelf(); }); #endregion #region 初始化 { this.SendCommand(new SetPlaneCommand(0));//在跑一次,去触发Register的 } #endregion } #region 重写 其它 protected override void OnOpen(IUIData uiData = null) { } protected override void OnShow() { } protected override void OnHide() { } protected override void OnClose() { } #endregion #region 辅助 void UpdatePropertyItems() { UpdateValueText(); UpdateSlider(); UpdateAddButton(); UpdateCostStarText(); } private void UpdateAddButton() { foreach (var rect in _propertyItemLst) { string property = (rect.name).TrimName(TrimNameType.DashAfter).LowerFirstLetter();//attack,fireRate,life int planeID = this.GetModel<IAirCombatAppModel>().SelectPlaneID; string pre = planeID + property; // Button addBtn = rect.Find("Add").GetComponent<Button>(); addBtn.onClick.RemoveAllListeners();//切换不同id就重置 addBtn.onClick.AddListener(() => { string costKey = KeysUtil.GetPropertyKeys(pre + PropertyItem.ItemKey.cost); int cost = DataMgr.Single.Get<int>(costKey); bool can = this.SendCommand(new ChangeStarCommand( -cost) ); if ( can ) { this.SendCommand (new IncreasePlanePropertyCommand( property ) ); } }); } } private void UpdateUpgradesText() { int planeID = this.GetModel<IAirCombatAppModel>().SelectPlaneID; int cueLevel = DataMgr.Single.Get<int>(planeID + DataKeys.LEVEL); string costKey = KeysUtil.GetPropertyKeys(planeID + DataKeys.UPGRADES + cueLevel); int cost = DataMgr.Single.Get<int>(costKey); // UpgradesBtn.SetButtonText(cost); } private void UpdateUpgradesButton() { #region 说明 /** "planes": [ "planeId": 0, "level": 0, "attackTime":1, "attack": { "name":"攻击","value":5,"cost":180,"costUnit":"star","grouth":10,"maxVaue": 500}, "fireRate": { "name":"攻速","value":80,"cost":200,"costUnit":"star","grouth":1,"maxVaue": 100}, "life": { "name":"生命","value":100,"cost":200,"costUnit":"star","grouth":50,"maxVaue": 1000}, "upgrades": { "name":"升级","coefficient": 2,"max":4,"0": 100,"1": 200,"2": 300,"3": 400,"costUnit":"diamond"} }, **/ #endregion int planeID = this.GetModel<IAirCombatAppModel>().SelectPlaneID; int cueLevel = DataMgr.Single.Get<int>(planeID + DataKeys.LEVEL); string costKey = KeysUtil.GetPropertyKeys(planeID + DataKeys.UPGRADES + cueLevel); int cost = DataMgr.Single.Get<int>(costKey); // UpdateUpgradesText(); // UpgradesBtn.onClick.RemoveAllListeners(); UpgradesBtn.onClick.AddListener(() => { bool can = this.SendCommand(new ChangeDiamondCommand(-cost)); if (can) { this.SendCommand(new UpgradesPlaneLevelCommand()); } }); } private void UpdateCostStarText() { foreach (var rect in _propertyItemLst) { string property = (rect.name).TrimName(TrimNameType.DashAfter).LowerFirstLetter();//attack,fireRate,life int planeID = this.GetModel<IAirCombatAppModel>().SelectPlaneID; string pre = planeID + property; string key = KeysUtil.GetPropertyKeys(pre + PropertyItem.ItemKey.cost); int value = DataMgr.Single.Get<int>(key); // rect.Find("Cost").SetText(value); } } private void UpdateValueText() { #region 说明 /* "planes": [ { "planeId": 0, "level": 0, "attackTime":1, "attack": {"name":"攻击","value":5,"cost":180,"costUnit":"star","grouth":10,"maxVaue": 500}, "fireRate": {"name":"攻速","value":80,"cost":200,"costUnit":"star","grouth":1,"maxVaue": 100}, "life": {"name":"生命","value":100,"cost":200,"costUnit":"star","grouth":50,"maxVaue": 1000}, "upgrades": {"name":"升级","coefficient": 2,"max":4,"0": 100,"1": 200,"2": 300,"3": 400,"costUnit":"diamond"} }, */ #endregion foreach (var rect in _propertyItemLst) { string property = (rect.name).TrimName(TrimNameType.DashAfter).LowerFirstLetter();//attack,fireRate,life int planeID = this.GetModel<IAirCombatAppModel>().SelectPlaneID; string valueKey = KeysUtil.GetPropertyKeys(planeID + property + PropertyItem.ItemKey.value); int value = DataMgr.Single.Get<int>(valueKey); // rect.Find("Value").SetText(value); } } void UpdatePlaneSprite() { int planeID = this.GetModel<IAirCombatAppModel>().SelectPlaneID; string levelKey = KeysUtil.GetPropertyKeys(planeID+DataKeys.LEVEL); int level= DataMgr.Single.Get<int>(levelKey); Sprite planeSprite = PlaneSpritesModel.Single[planeID, level]; IconImg.SetSprite(planeSprite); } void UpdateStarText() { int star = this.GetModel<IAirCombatAppModel>().Star; StarText.SetText(star); } void UpdateDiamondText() { int diamond = this.GetModel<IAirCombatAppModel>().Diamond; DiamondText.SetText(diamond); } /// <summary>改成根据父节点,去更新子节点</summary> private void UpdateSlider() { foreach (var rect in _propertyItemLst) { int id = this.GetModel<IAirCombatAppModel>().SelectPlaneID; string property = (rect.name).TrimName(TrimNameType.DashAfter).LowerFirstLetter();//attack string pre = id + property; Slider slider = rect.Find("Slider").GetComponent<Slider>(); string maxVaueKey = KeysUtil.GetPropertyKeys(pre + ItemKey.maxVaue); //0attackmaxVaue(原文没加l) string valueKey = KeysUtil.GetPropertyKeys(pre + ItemKey.value);//0attackvalue float maxValue=DataMgr.Single.Get<int>(maxVaueKey); float value= DataMgr.Single.Get<int>(valueKey); Debug.LogFormat("Slider:{0},{1}", valueKey, maxVaueKey); slider.minValue = 0; slider.maxValue = maxValue; slider.value = value; Debug.LogFormat("Slider:{0},{1},{2}", slider.minValue, slider.value, slider.maxValue); } } #endregion #region QF IArchitecture IBelongToArchitecture.GetArchitecture() { return AirCombatApp.Interface; } #endregion } }
什么都不带的Command
带参数的Command
代返回值的Command
总体框架是从PointGame(QF中的例子)中复制的
。。。
AirCombat_QFramework.All()汇总所有的"飞机大战"使用QF的方法,方便查找
。。。
主体是这个Command。Event是对Command后对应的操作。所以Event的命名很多对应这Command
void Command() { ChangeStarCommand increaseStarCommand; ChangeDiamondCommand increaseDiamondCommand; SetStarCommand setStarCommand; SetDiamondCommand setDiamondCommand; // IncreasePlanePropertyCommand increasePlanePropertyCommand; IncreasePlaneAttackCommand increasePlaneAttackCommand; IncreasePlaneFireRateCommand increasePlaneFireRateCommand; IncreasePlaneLifeCommand increasePlaneLifeCommand; UpgradesPlaneLevelCommand upgradesPlaneLevelCommand; // SetPlaneCommand initPlaneCommand; SwitchPlaneCommand changePlaneCommand; SwitchHeroCommand changeHeroCommand; // OpenStartGamePanelCommand openStartGamePanelCommand; OpenSelectHeroPanelCommand openSelectHeroCommand; OpenStrengthenPanelCommand openStrengthenPanel; ExitGameCommand exitGameCommand; }
/**************************************************** 文件:QFramework_AirCombat.cs 作者:lenovo 邮箱: 日期:2023/8/8 20:53:33 功能: *****************************************************/ using JetBrains.Annotations; using QFramework.Example; using System; using System.Collections; using System.Collections.Generic; using System.Numerics; using UnityEngine; using static PropertyItem; using Random = UnityEngine.Random; namespace QFramework.AirCombat { public class AirCombat_QFramework : MonoBehaviour ,IController { private void Start() { } void All() { Architecture(); // Model(); System(); Utility(); Controller(); // Command(); Event(); // Test(); } #region 辅助 void Test() { if (Input.GetKeyDown(KeyCode.Q)) this.SendCommand(new ChangeStarCommand(100)); if (Input.GetKeyDown(KeyCode.W)) this.SendCommand(new ChangeStarCommand(-100)); if (Input.GetKeyDown(KeyCode.E)) this.SendCommand(new ChangeDiamondCommand(-100)); if (Input.GetKeyDown(KeyCode.R)) this.SendCommand(new ChangeDiamondCommand(-100)); } void Event() { ChangeStarEvent changeStarEvent; ChangeDiamondEvent changeDiamondEvent; // SelectHeroIDEvent switchHeroEvent; SelectPlaneIDEvent switchPlaneEvent; // IncreasePlanePropertyEvent increasePlanePropertyEvent; UpgradesPlaneLevelEvent upgradesPlaneLevelEvent; } void Command() { ChangeStarCommand increaseStarCommand; ChangeDiamondCommand increaseDiamondCommand; SetStarCommand setStarCommand; SetDiamondCommand setDiamondCommand; // IncreasePlanePropertyCommand increasePlanePropertyCommand; IncreasePlaneAttackCommand increasePlaneAttackCommand; IncreasePlaneFireRateCommand increasePlaneFireRateCommand; IncreasePlaneLifeCommand increasePlaneLifeCommand; UpgradesPlaneLevelCommand upgradesPlaneLevelCommand; // SetPlaneCommand initPlaneCommand; SwitchPlaneCommand changePlaneCommand; SwitchHeroCommand changeHeroCommand; // OpenStartGamePanelCommand openStartGamePanelCommand; OpenSelectHeroPanelCommand openSelectHeroCommand; OpenStrengthenPanelCommand openStrengthenPanel; ExitGameCommand exitGameCommand; } void Model() { IModel iModel; AbstractModel abstractModel; IAirCombatAppModel iAirCombatAppModel; AirCombatAppModel airCombatAppModel; IPlaneModel iPlaneModel; PlaneModel planeModel; } void System() { ISystem iSystem; //IAchievementSystem iAchievementSystem; //AchievementSystem achievementSystem; } void Utility() { IUtility iIUtility; IStorage iStorage; PlayerPrefsStorage playerPrefsStorage; JsonStorage storage; } void Controller() { AirCombatAppController airCombatAppController; } void Architecture() { AirCombatApp counterApp; } public IArchitecture GetArchitecture() { return AirCombatApp.Interface; } #endregion } #region Model internal class PlaneModel { } internal interface IPlaneModel { } // 1. 定义一个 Model 对象 public interface IAirCombatAppModel : IModel { BindableProperty<int> Star { get; } BindableProperty<int> Diamond { get; } BindableProperty<int> SelectPlaneID { get; } BindableProperty<int> SelectHeroID { get; } } public class AirCombatAppModel : AbstractModel, IAirCombatAppModel { public BindableProperty<int> Star { get; } = new BindableProperty<int>(); public BindableProperty<int> Diamond { get; } = new BindableProperty<int>(); public BindableProperty<int> SelectHeroID { get; } = new BindableProperty<int>(); public BindableProperty<int> SelectPlaneID { get; } = new BindableProperty<int>(); protected override void OnInit() { IStorage storage = this.GetUtility<IStorage>(); // 设置初始值(不触发事件) Star.SetValueWithoutEvent(storage.LoadInt(nameof(Star))); Diamond.SetValueWithoutEvent(storage.LoadInt(nameof(Diamond))); SelectHeroID.SetValueWithoutEvent(storage.LoadInt(nameof(SelectHeroID))); SelectPlaneID.SetValueWithoutEvent(storage.LoadInt(nameof(SelectPlaneID))); // 当数据变更时 存储数据 Star.Register(newCount => { storage.SaveInt(nameof(Star), newCount); }); Diamond.Register(newCount => { storage.SaveInt(nameof(Diamond), newCount); }); SelectHeroID.Register(newCount => { storage.SaveInt(nameof(SelectHeroID), newCount); }); SelectPlaneID.Register(newCount => { storage.SaveInt(nameof(SelectPlaneID), newCount); }); } } #endregion #region Command // 引入 Command public class ChangeStarCommand : AbstractCommand<bool> { int _change = 0; public ChangeStarCommand(int change) { _change = change; } protected override bool OnExecute() { var model = this.GetModel<IAirCombatAppModel>(); int cur = this.GetModel<IAirCombatAppModel>().Star; int after = cur + _change; if (after >= 0 )//有钱&&上升空间 { this.GetModel<IAirCombatAppModel>().Star.Value = after; this.SendEvent<ChangeStarEvent>(); "ChangeStarCommand".LogInfo(); return true; } else { string str = "你没星星了!"; str += "需要" + _change; str.LogInfo(); // UIManager.Single.ShowDialog("你没星星了!"); return false; } } } public class SetStarCommand : AbstractCommand { int _after = 0; public SetStarCommand(int after) { _after = after; } protected override void OnExecute() { this.GetModel<IAirCombatAppModel>().Star.Value = _after; this.SendEvent<ChangeStarEvent>(); } } public class SetDiamondCommand : AbstractCommand { int _after = 0; public SetDiamondCommand(int change) { _after = change; } protected override void OnExecute() { this.GetModel<IAirCombatAppModel>().Diamond.Value = _after; this.SendEvent<ChangeDiamondEvent>(); } } public class ChangeDiamondCommand : AbstractCommand<bool> { int _change = 0; /// <summary>增加正,减少负</summary> public ChangeDiamondCommand(int change) { _change = change; } protected override bool OnExecute() { var model = this.GetModel<IAirCombatAppModel>(); int cur = model.Diamond; int after = cur + _change; if (after >= 0)//有钱&&上升空间 { model.Diamond.Value = after; this.SendEvent<ChangeDiamondEvent>(); return true; } else { string str = "你没钻石了!"; str += "需要" + _change; str.LogInfo(); // UIManager.Single.ShowDialog("你没星星了!"); return false; } } } public class IncreasePlanePropertyCommand : AbstractCommand { PlaneProperty.Property _planeProperty; public IncreasePlanePropertyCommand(PlaneProperty.Property planeProperty) { _planeProperty = planeProperty; } public IncreasePlanePropertyCommand(string planePropertyString) { _planeProperty = planePropertyString.String2Enum<PlaneProperty.Property>(); } protected override void OnExecute() { string planeID = this.GetModel<IAirCombatAppModel>().SelectPlaneID.ToString(); string property = ""; switch (_planeProperty) { case PlaneProperty.Property.attack: { property = DataKeys.ATTACK; } break; case PlaneProperty.Property.fireRate: { property = DataKeys.FIRE_RATE; } break; case PlaneProperty.Property.life: { property = DataKeys.LIFE; } break; default: break; } // string maxKey = KeysUtil.GetPropertyKeys(planeID + property + PropertyItem.ItemKey.maxVaue); string curKey = KeysUtil.GetPropertyKeys(planeID + property + PropertyItem.ItemKey.value); string grouthKey = KeysUtil.GetPropertyKeys(planeID + property + PropertyItem.ItemKey.grouth); int max = DataMgr.Single.Get<int>(maxKey); int cur = DataMgr.Single.Get<int>(curKey); int grouth = DataMgr.Single.Get<int>(grouthKey); int after = cur + grouth; if ( cur < max)//有上升空间 { if (after >= max)//到顶了 { after = max; } string valueKey = KeysUtil.GetPropertyKeys( planeID + property + ItemKey.value); DataMgr.Single.Set<int>(valueKey, after); Debug.LogFormat("IncreasePlanePropertyCommand {0}:{1} ",valueKey, after); this.SendEvent<IncreasePlanePropertyEvent>(); } else { ("数值到顶了!").LogInfo(); // UIManager.Single.ShowDialog("你没星星了!"); } } } public class IncreasePlaneAttackCommand : AbstractCommand { int _change; public IncreasePlaneAttackCommand(int change) { _change = change; } protected override void OnExecute() { int id = this.GetModel<IAirCombatAppModel>().SelectPlaneID; string pre = id + DataKeys.ATTACK; // // int max = DataMgr.Single.Get<int>(pre + ItemKey.maxVaue); int cur = DataMgr.Single.Get<int>(pre + ItemKey.value); int after = cur+_change; if ( after >= 0 && cur < max)//有上升空间 { if (after >= max)//到顶了 { after = max; } DataMgr.Single.SetObject(pre + ItemKey.value, after); } else { ("数值到顶了!").LogInfo(); // UIManager.Single.ShowDialog("你没星星了!"); } } } public class IncreasePlaneFireRateCommand : AbstractCommand { int _value; public IncreasePlaneFireRateCommand(int value) { _value = value; } protected override void OnExecute() { } } public class IncreasePlaneLifeCommand : AbstractCommand { int _value; public IncreasePlaneLifeCommand(int value) { _value = value; } protected override void OnExecute() { } } /// <summary>直接升级(费用判断另作处理)</summary> public class UpgradesPlaneLevelCommand : AbstractCommand { protected override void OnExecute() { ChangeLevel(); this.SendEvent<UpgradesPlaneLevelEvent>(); ChangeData(); this.SendEvent<IncreasePlanePropertyEvent>(); // } private void ChangeData() { //获取升级系数,修改数据 var ratioKey = KeysUtil.GetPropertyKeysWithoutPlaneId(DataKeys.UPGRADES_RATIO); var ratio = DataMgr.Single.Get<int>(ratioKey); ChangeData(ratio, PropertyItem.ItemKey.value, PlaneProperty.Property.attack); ChangeData(ratio, PropertyItem.ItemKey.maxVaue, PlaneProperty.Property.attack); ChangeData(ratio, PropertyItem.ItemKey.grouth, PlaneProperty.Property.attack); // ChangeData(ratio, PropertyItem.ItemKey.value, PlaneProperty.Property.life); ChangeData(ratio, PropertyItem.ItemKey.maxVaue, PlaneProperty.Property.life); ChangeData(ratio, PropertyItem.ItemKey.grouth, PlaneProperty.Property.life); } void ChangeLevel() { int planeID = this.GetModel<IAirCombatAppModel>().SelectPlaneID; string curKey = KeysUtil.GetPropertyKeys(planeID + DataKeys.LEVEL); string maxKey = KeysUtil.GetPropertyKeys(planeID + DataKeys.LEVEL_MAX); int cur = DataMgr.Single.Get<int>(curKey); int max = DataMgr.Single.Get<int>(maxKey); int after = cur + 1; after = after.Clamp(0, max - 1); DataMgr.Single.SetObject(curKey, after); } /// <summary>暂时设定为 grouth和max乘以系数</summary> private void ChangeData(int ratio, PropertyItem.ItemKey itemKey, PlaneProperty.Property property) { int planeID = this.GetModel<IAirCombatAppModel>().SelectPlaneID; var key = KeysUtil.GetPropertyKeys(planeID + property.ToString() + itemKey); var value = DataMgr.Single.Get<int>(key); value *= ratio; DataMgr.Single.Set(key, value); } } public class SwitchHeroCommand : AbstractCommand { int _heroID = 0; public SwitchHeroCommand(int heroID) { _heroID = heroID; } protected override void OnExecute() { this.GetModel<AirCombatAppModel>().SelectHeroID.Value = _heroID; this.SendEvent<SelectHeroIDEvent>(); } } public class SwitchPlaneCommand : AbstractCommand { int _change = 0; public SwitchPlaneCommand(int change) { _change = change; } protected override void OnExecute() { if (_change != 1 && _change != -1) //飞机的切换是顺序的 { return; } int max = PlaneSpritesModel.Single.Count; int id = this.GetModel<IAirCombatAppModel>().SelectPlaneID; id += _change; id = id.Clamp(0, max - 1); // id = (id < 0 ) ? 0 : id >= max ? id = max - 1 : id; // string str = (_change == -1) ? "左" : "右"; (str + "键:" + id).LogInfo(); // this.GetModel<IAirCombatAppModel>().SelectPlaneID.Value = id; this.SendEvent<SelectPlaneIDEvent>(); } } public class SetPlaneCommand : AbstractCommand { int _planeID = 0; public SetPlaneCommand(int planeID) { _planeID = planeID; } protected override void OnExecute() { int max = PlaneSpritesModel.Single.Count; if (_planeID < 0 || _planeID > max-1) { return; } // this.GetModel<IAirCombatAppModel>().SelectPlaneID.Value = _planeID; GameStateModel.Single.SelectedPlaneId = _planeID; this.SendEvent<SelectPlaneIDEvent>(); } } public class OpenSelectHeroPanelCommand : AbstractCommand { protected override void OnExecute() { UIKit.OpenPanel<SelectHeroPanel>(); } } public class OpenStartGamePanelCommand : AbstractCommand { protected override void OnExecute() { UIKit.OpenPanel<StartGamePanel>(); } } public class OpenStrengthenPanelCommand : AbstractCommand { Action _onComplete; /// <summary>比如设置了金币,但是对金币的监听是在打开面板是才注册的,所以onComplete才好触发</summary> public OpenStrengthenPanelCommand(Action onComplete) { _onComplete = onComplete; } public OpenStrengthenPanelCommand() { } protected override void OnExecute() { //这块是上个界面,选择飞机的界面来做的(如果再直接打开升级界面邮箱使用返回按钮的情况下可以用) UIKit.OpenPanel<SelectHeroPanel>(); UIKit.Stack.Push<SelectHeroPanel>(); UIKit.HidePanel<SelectHeroPanel>(); //UIManager.Single.Show(Paths.PREFAB_STRENGTHEN_VIEW); UIKit.OpenPanel<StrengthenPanel>(); "打开升级面板".LogInfo(); // _onComplete.DoIfNotNull(); } } public class ExitGameCommand : AbstractCommand { protected override void OnExecute() { Application.Quit(); "退出游戏".LogInfo(); } } #endregion #region Utility public interface IStorage : IUtility { void SaveInt(string key, int value); int LoadInt(string key, int defaultValue = 0); void SaveString(string key, string value); string LoadString(string key, string defaultValue = ""); void SaveFloat(string key, float value); float LoadFloat(string key, float defaultValue = 0.0f); } public class PlayerPrefsStorage : IStorage { public void SaveInt(string key, int value) { PlayerPrefs.SetInt(key, value); } public int LoadInt(string key, int defaultValue = 0) { return PlayerPrefs.GetInt(key, defaultValue); } public void SaveString(string key, string value) { PlayerPrefs.SetString(key, value); } public string LoadString(string key, string defaultValue = "") { return PlayerPrefs.GetString(key, defaultValue); } public void SaveFloat(string key, float value) { PlayerPrefs.SetFloat(key, value); } public float LoadFloat(string key, float defaultValue = 0.0f) { return PlayerPrefs.GetFloat(key, defaultValue); } } public class JsonStorage : IStorage { public void SaveInt(string key, int value) { PlayerPrefs.SetInt(key, value); } public int LoadInt(string key, int defaultValue = 0) { return PlayerPrefs.GetInt(key, defaultValue); } public void SaveString(string key, string value) { PlayerPrefs.SetString(key, value); } public string LoadString(string key, string defaultValue = "") { return PlayerPrefs.GetString(key, defaultValue); } public void SaveFloat(string key, float value) { PlayerPrefs.SetFloat(key, value); } public float LoadFloat(string key, float defaultValue = 0.0f) { return PlayerPrefs.GetFloat(key, defaultValue); } } #endregion #region Event public class UpgradesPlaneLevelEvent { } public class IncreasePlanePropertyEvent { } public class ChangeStarEvent { } public class ChangeDiamondEvent { } public class SelectHeroIDEvent { } public class SelectPlaneIDEvent { } #endregion #region Architecture public class AirCombatApp : Architecture<AirCombatApp> { protected override void Init() { // 注册 System //this.RegisterSystem<IAchievementSystem>(new AchievementSystem()); // 注册 Model this.RegisterModel<IAirCombatAppModel>(new AirCombatAppModel()); // 注册存储工具的对象 this.RegisterUtility<IStorage>(new PlayerPrefsStorage()); this.RegisterUtility<IStorage>(new JsonStorage()); } protected override void ExecuteCommand(ICommand command) { Debug.Log("Before " + command.GetType().Name + "Execute"); base.ExecuteCommand(command); Debug.Log("After " + command.GetType().Name + "Execute"); } protected override TResult ExecuteCommand<TResult>(ICommand<TResult> command) { Debug.Log("Before " + command.GetType().Name + "Execute"); var result = base.ExecuteCommand(command); Debug.Log("After " + command.GetType().Name + "Execute"); return result; } } #endregion }
4列乘以6行
这里乱了,是因为原始Panel拖到了QF的UIRoot,还没调整
同上,创建预制体(复制旧的)
添加Bind
标记QF ABMark和New AB名字(_prefab的格式)
CreateUICode
打开面板就发送实例Command(将操作从面板中分离开)
using UnityEngine; using UnityEngine.UI; using QFramework; namespace QFramework.AirCombat { public class SelectLevelPanelData : UIPanelData { } public partial class SelectLevelPanel : UIPanel,IController { protected override void OnInit(IUIData uiData = null) { mData = uiData as SelectLevelPanelData ?? new SelectLevelPanelData(); // please add init code here //LevelsTrans.transform ; //LevelRoot levelRoot; //LevelRootController levelRootController; //LevelsView levelsView; //LevelsController levelsController; //LevelItem levelItem; //LevelItemController levelItemController; this.SendCommand( new InstantiateLevelSelectableCommand(LevelsTrans)); this.RegisterEvent<OpenLoadingPanelEvent>(_ => { CloseSelf(); }); #region Bottom BackBtn.onClick.AddListenerAfterRemoveAll(() => { UIKit.Back<SelectHeroPanel>(); CloseSelf(); }); #endregion } #region 重写 其它 protected override void OnOpen(IUIData uiData = null) { } protected override void OnShow() { } protected override void OnHide() { } protected override void OnClose() { } public IArchitecture GetArchitecture() { return AirCombatApp.Interface; } #endregion } }
这里看到Andy用了很多脚本。
所以先直接有用QF的ResLoader来达成效果
void ReaderConfig()
{
ReaderConfig readerConfig;
ReaderMgr readerMgr;
string str=Paths.CONFIG_LEVEL_CONFIG;
//
ILoader iLoader;
ResourceLoader resourceLoader;
LoadMgr loadMgr;
}
。。。
_levelsTrans.LoadAndInstantiateGameObject(“LevelSelectable”,24);是自定义的拓展,看下一 #
public class InstantiateLevelSelectableCommand : AbstractCommand { RectTransform _levelsTrans; public InstantiateLevelSelectableCommand(RectTransform levelsTrans) { _levelsTrans = levelsTrans; } protected override void OnExecute() { #region Level /* { "levelCount": 24, "eachRow": 4 } */ #endregion //原本用到的脚本,写方便切换看 { LevelRoot levelRoot; LevelRootController levelRootController; LevelsView levelsView; LevelsController levelsController; LevelItem levelItem; LevelItemController levelItemController; } //数量和行列 { IReader reader = ReaderMgr.Single.GetReader(Paths.CONFIG_LEVEL_CONFIG); // int levelCount= reader[LevelRoot.Name.levelCount.Enum2String()].Get<>; } //实例 { //GameObject go = LoadMgr.Single.LoadPrefabAndInstantiate(Paths.PREFAB_LEVEL_ITEM, _levelsTrans); _levelsTrans.LoadAndInstantiateGameObject("LevelSelectable",24); } // TODO 组件 { foreach (Transform trans in _levelsTrans) { trans.AddComponent<LevelItem>(); trans.AddComponent<LevelItemController>(); } } } }
public class InstantiateLevelSelectableCommand : AbstractCommand { RectTransform _levelsTrans; public InstantiateLevelSelectableCommand(RectTransform levelsTrans) { _levelsTrans = levelsTrans; } protected override void OnExecute() { #region Level /* { "levelCount": 24, "eachRow": 4 } */ #endregion //原本用到的脚本 { LevelsView levelsView; LevelsController levelsController; LevelRoot levelRoot; LevelRootController levelRootController; LevelItem levelItem; LevelItemController levelItemController; } //数量和行列 { IReader reader = ReaderMgr.Single.GetReader(Paths.CONFIG_LEVEL_CONFIG); // int levelCount= reader[LevelRoot.Name.levelCount.Enum2String()].Get<>; } int levelCount = 24; int eachRow = 4; //一行多少个 //实例 { //GameObject go = LoadMgr.Single.LoadPrefabAndInstantiate(Paths.PREFAB_LEVEL_ITEM, _levelsTrans); _levelsTrans.LoadAndInstantiateGameObject("LevelSelectable", levelCount); } //排列 { for (int idx = 0; idx < levelCount; idx++) { Transform levelSelectable = _levelsTrans.GetChild(idx); levelSelectable.name = "LevelSelectable_"+idx; SetPos(levelSelectable, GetGrid(idx, eachRow)) ; } } // TODO 组件 { foreach (Transform trans in _levelsTrans) { trans.AddComponent<LevelItem>(); trans.AddComponent<LevelItemController>(); } } } #region 辅助 设置位置 /// <summary>行,6行4列</summary> private Vector2 GetGrid(int id,int eachRow) { var y = id / eachRow; //id/4第几行 var x = id % eachRow; //id%4第几个 return new Vector2(x, y); } private void SetPos( Transform t,Vector2 gridId) { int _leftOffet = 50; //上下行左右错开的值 int _lineSpacing = 20; int _offset = 10; // var width = t.Rect().rect.width * t.localScale.x; var height = t.Rect().rect.height * t.localScale.y; var indention = gridId.y % 2 == 0 ? _leftOffet : 0; var x = indention + width * 0.5f + (_offset + width) * gridId.x; var y = height * 0.5f + (_lineSpacing + height) * gridId.y; t.Rect().anchoredPosition = new Vector2(x, -y); } #endregion }
关卡子项选择QF的UI生成代码,为了注册生成关卡子项时的,名字、位置和解锁状态
using UnityEngine; using UnityEngine.UI; using QFramework; using QFramework.AirCombat; using UnityEngine.Purchasing; namespace QFramework.AirCombat { public class LevelSelectableData : UIPanelData { } public partial class LevelSelectable : UIPanel, IController { public void Init() { int cur = transform.GetSiblingIndex(); { gameObject.name = "LevelSelectable_" + (cur); LevelText.SetText(cur+1);//现实的话不从0开始 EnterBtn.onClick.AddListenerAfterRemoveAll(() => { Debug.Log("LevelSelectable 进入关卡" + cur); this.SendCommand(new OpenLoadingPanelCommand(transform)); }); MaskBtn.onClick.AddListenerAfterRemoveAll(() => { Debug.Log("LevelSelectable 当前关卡未开放"); // UIManager.Single.ShowDialog("当前关卡未开放"); }); } // this.RegisterEvent<UpdateLevelSelectableLockStateEvent>(eventId => { Debug.Log("LevelSelectable RegisterEvent<InstantiateLevelSelectableEvent>"); //能挑战已经通关的下一关 int tar = this.GetModel<IAirCombatAppModel>().PassedLevel + 1; Debug.Log("LevelSelectable tar "+ tar ); bool can = (cur <= tar); if (can) { MaskBtn.Hide(); } else { MaskBtn.Show(); } }); } #region 重写实现 protected override void OnInit(IUIData uiData = null) { mData = uiData as LevelSelectableData ?? new LevelSelectableData(); } protected override void OnOpen(IUIData uiData = null) { } protected override void OnShow() { } protected override void OnHide() { } protected override void OnClose() { } public IArchitecture GetArchitecture() { return AirCombatApp.Interface; } #endregion } }
public class InstantiateLevelSelectableCommand : AbstractCommand { RectTransform _levelsTrans; public InstantiateLevelSelectableCommand(RectTransform levelsTrans) { _levelsTrans = levelsTrans; } protected override void OnExecute() { #region Level /* { "levelCount": 24, "eachRow": 4 } */ #endregion //原本用到的脚本 { LevelsView levelsView; LevelsController levelsController; LevelRoot levelRoot; LevelRootController levelRootController; LevelItem levelItem; LevelItemController levelItemController; } //数量和行列 { IReader reader = ReaderMgr.Single.GetReader(Paths.CONFIG_LEVEL_CONFIG); // int levelCount= reader[LevelRoot.Name.levelCount.Enum2String()].Get<>; } int levelCount = 24; int eachRow = 4; //一行多少个 //实例 { //GameObject go = LoadMgr.Single.LoadPrefabAndInstantiate(Paths.PREFAB_LEVEL_ITEM, _levelsTrans); _levelsTrans.LoadAndInstantiateGameObject("LevelSelectable", levelCount); } //排列 { for (int idx = 0; idx < levelCount; idx++) { Transform levelSelectable = _levelsTrans.GetChild(idx); SetPos(levelSelectable, GetGrid(idx, eachRow)) ; } } // TODO 组件 { for (int idx = 0; idx < levelCount; idx++) { Transform levelSelectable = _levelsTrans.GetChild(idx); levelSelectable.GetComponent<LevelSelectable>().Init(); } } this.SendEvent<UpdateLevelSelectableLockStateEvent>(); } #region 辅助 设置位置 /// <summary>行,6行4列</summary> private Vector2 GetGrid(int id,int eachRow) { var y = id / eachRow; //id/4第几行 var x = id % eachRow; //id%4第几个 return new Vector2(x, y); } private void SetPos( Transform t,Vector2 gridId) { int _leftOffet = 50; //上下行左右错开的值 int _lineSpacing = 20; int _offset = 10; // var width = t.Rect().rect.width * t.localScale.x; var height = t.Rect().rect.height * t.localScale.y; var indention = gridId.y % 2 == 0 ? _leftOffet : 0; var x = indention + width * 0.5f + (_offset + width) * gridId.x; var y = height * 0.5f + (_lineSpacing + height) * gridId.y; t.Rect().anchoredPosition = new Vector2(x, -y); } #endregion }
这种拓展用到了很多QF的脚本,建议直接放在QF的文件夹下
namespace QFramework { public static class ExtndQFramework { public static void Example(Transform parent) { LoadAndInstantiateGameObject("WhiteChess", parent); } public static GameObject LoadAndInstantiateGameObject(string likeWhiteChess ,Transform parent) { //在扫雷案例中测试的,用到WhiteChess ResKit.Init(); ResLoader loader = ResLoader.Allocate(); GameObject prefab = loader.LoadSync<GameObject>(likeWhiteChess); GameObject go= GameObject.Instantiate(prefab, parent); return go; } public static Transform LoadAndInstantiateGameObject(this Transform parent , string likeWhiteChess , int count) { //在扫雷案例中测试的,用到WhiteChess ResKit.Init(); ResLoader loader = ResLoader.Allocate(); GameObject prefab = loader.LoadSync<GameObject>(likeWhiteChess); for (int i = 0; i < count; i++) { GameObject go = GameObject.Instantiate(prefab, parent); } return parent; } public static GameObject LoadGameObject(this string likeWhiteChess ) { //在扫雷案例中测试的,用到WhiteChess ResKit.Init(); ResLoader loader = ResLoader.Allocate(); GameObject go = loader.LoadSync<GameObject>(likeWhiteChess); return go; } } }
写死的时间是有点长,但不长看不出效果
#region Smooth、Slider /// <summary> /// 以前看教程收集的一个例子 /// </summary> /// <param name="mono">协程Mono</param> /// <param name="slider">滑动条</param> /// <param name="step">步进值</param> /// <param name="stepTime">步进时间</param> /// <param name="stepSmooth">步进平滑值</param> /// <exception cref="System.Exception"></exception> public static void PlayPrgSmooth(this MonoBehaviour mono , Slider slider , Text text , float step = 0.1f , float stepTime = 0.5f , float stepSmooth = 0.01f , Action onCompleted=null) { if (step <= stepSmooth) { throw new System.Exception("Prg step <= smooth异常"); } mono.StartCoroutine(OnValueChangeSmooth(slider,text, step, stepTime, stepSmooth, onCompleted)); } /// <summary>平滑点</summary> static IEnumerator OnValueChangeSmooth(Slider slider , Text text , float step , float stepTime , float stepSmooth , Action onCompleted) { slider.value = 0f; text.SetText(0.00f); // float process = 0f; while (process < 1f) { process += step; //类似帧循环,快点 yield return new WaitUntil(() => { float prg= Mathf.SmoothStep(from: slider.value , to: process , stepSmooth); text.SetText((prg).ToString("0.00%") ); //感觉要乘以100.0f,但不乘就有想要的效果 slider.value = prg; return process - slider.value < stepSmooth; }); yield return new WaitForSeconds(stepTime);//每0.5s会执行一遍循环体 } slider.value = 1.0f; text.SetText("100.00%"); onCompleted.DoIfNotNull(); } #endregion
public class OpenLoadingPanelCommand : AbstractCommand { protected override void OnExecute() { this.SendEvent<OpenLoadingPanelEvent>();//关闭关卡选择界面会注册事件 //TODO 设置场景状态 LoadingPanel panel= UIKit.OpenPanel<LoadingPanel>(); panel.PlayPrgSmooth(panel.Slider , panel.PrgText , 0.2f , 0.5f , 0.05f , () => { this.SendCommand<OpenGamePanelCommand>(); this.SendEvent<CloseLoadingPanelEvent>();//关闭加载界面会注册事件 }); } }
public class OpenGamePanelCommand : AbstractCommand
{
protected override void OnExecute()
{
Debug.Log("OpenGamePanelCommand");
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。