【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)

总体介绍

做的是 00,10,13,考虑做10。
11,12没下载,当时把这两个误认为 00,10
用到了UniRx

Framework有2个
00 Unity 游戏框架搭建 2019 第一季 C# 核心知识与简易 Manager Of Managers 框架搭建 120课数
01 Unity 游戏框架搭建 2019 第二季 模块/系统设计、命名、测试(资源管理/热更新) 133课数

QFramework加上简介有4个
总共是6个
10 QFramework 使用指南 91课数(2个示例,备忘录和魔塔)【免费】【里面的示例是文章主题内容】
(这是sik学院视频下的资料,QF有点老了,也有一些报错。不建议用,建议到https://github.com/liangxiegame/QFramework下载最新的,里面例子,教程文档什么都有。)
11 框架搭建 决定版:架构演化(第一季) 31课数
12 框架搭建 决定版:应用篇(第二季) 51课数
13 框架搭建 决定版:理论强化篇(第三季) 53课数

命名

主要看实际中 凉鞋 怎么用

私有

mXxx
m_Xxx
直接小写 xxx

public
大写Xxx

---------------------------------------------------

00 第一季 C# 核心知识与简易 Manager Of Managers 框架搭建

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第1张图片

消息 MonoBehaviour与MsgDispatcher

/****************************************************
    文件:Demo_202305032353.cs
	作者:lenovo
    邮箱: 
    日期:2023/5/3 23:53:10
	功能:
*****************************************************/

using System;
using UnityEngine;

public class Demo01_202305032353 : MonoBehaviour
{

    void Start()
    {
        MsgDispatcher.Register("KillEnemy",OnEnemyKilled);
        MsgDispatcher.Send("KillEnemy","赵云");
        //
        MsgDispatcher.UnRegister("KillEnemy", OnEnemyKilled);
        MsgDispatcher.Send("KillEnemy", "赵云");
        //
        this.Delay(5f, () => {Debug.Log("5秒真男人"); });
    }

    private void OnEnemyKilled(object obj)
    {
        Debug.LogFormat("{0}KillEnemy", obj );
    }
}

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第2张图片

消息 MonoBehaviourMsg(将MsgDispatcher内置到MonoBehaviour)

/****************************************************
    文件:Demo_202305032353.cs
	作者:lenovo
    邮箱: 
    日期:2023/5/3 23:53:10
	功能:
*****************************************************/

using System;
using UnityEngine;

public class Demo02_202305032353 : MonoBehaviourMsg
{

    void Start()
    {

        this.Delay(5f, () => {Debug.Log("5秒真男人"); });
        //
        RegisterMsg("AmbushEnemy", OnEnemyAmbushed);
        SendMsg("AmbushEnemy", "孙膑");
        //
        RegisterMsg("DefendEnemy", data => Debug.LogFormat("{0}DefendEnemy", data));
        SendMsg("DefendEnemy", "郝昭");
    }

    private void OnEnemyKilled(object obj)
    {
        Debug.LogFormat("{0}KillEnemy", obj );
    }


    private void OnEnemyAmbushed(object obj)
    {
        Debug.LogFormat("{0}AmbushEnemy", obj);
    }

    protected override void OnBeforeDestroy()
    {

    }
}

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第3张图片

---------------------------------------------------

01 第二季 模块/系统设计、命名、测试(资源管理/热更新)

bug TestFramework报错

增加了这两个
文件夹Tests,加了包TestFramework但还报错,索性先删了,
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第4张图片
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第5张图片

ResMgr.LoadSync

using UnityEngine;

namespace QFramework
{
	public class UIXXXPanel : MonoBehaviour
	{

#if UNITY_EDITOR
		[UnityEditor.MenuItem("QFramework/Example/9.UIXXXPanel", false, 9)]
		static void MenuItem()
		{
			UnityEditor.EditorApplication.isPlaying = true;

			new GameObject("UIXXXPanel").AddComponent<UIXXXPanel>();
		}
#endif


        [SerializeField] AudioClip coinClip;
        [SerializeField] AudioClip homeClip;
        [SerializeField] AudioClip bgClip;
        ResLoader mResLoader = new ResLoader();

		private void Start()
		{
			 coinClip = LoadAudioClip("coin");
			 homeClip  = LoadAudioClip("home");
			 bgClip = LoadAudioClip("coin");
			//
			OtherFunction();
		}


		private void OtherFunction()
		{
			 bgClip = LoadAudioClip("coin");
		}

		private void OnDestroy()
		{
			mResLoader.ReleaseAll();
		}

		AudioClip LoadAudioClip(string path)
		{
            return mResLoader.LoadSync<AudioClip>("resources://"+path);
        }
	}
 }

ResMgr.LoadAsync+回调

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace QFramework
{
	public class ResMgrExample : MonoBehaviour
	{

#if UNITY_EDITOR
		[UnityEditor.MenuItem("QFramework/Example/10.ResMgrExample", false, 10)]
		static void MenuItem()
		{
			UnityEditor.EditorApplication.isPlaying = true;

			new GameObject("ResMgrExample").AddComponent<ResMgrExample>();
		}
#endif

		ResLoader mResLoader = new ResLoader();

		[SerializeField] AudioClip audioClip1;
        [SerializeField] AudioClip audioClip2;
        [SerializeField] GameObject go;


		private IEnumerator Start()
		{
			yield return new WaitForSeconds(2.0f);

			mResLoader.LoadAsync<AudioClip>(
				assetName: "resources://coin", 
				onLoaded: coinClip =>
				{
					Debug.Log(coinClip.name);
					Debug.Log(Time.time);
				}
			);//这块是回调,所以不一定比后面快
			Debug.Log(Time.time);
			yield return new WaitForSeconds(2.0f);

			audioClip1=	mResLoader.LoadSync<AudioClip>("resources://home");
			yield return new WaitForSeconds(2.0f);

			go=mResLoader.LoadSync<GameObject>("resources://HomePanel");
			audioClip2=	mResLoader.LoadSync<AudioClip>("resources://Audio/coin");
			yield return new WaitForSeconds(5.0f);

			mResLoader.ReleaseAll();
		}
	}
}

stars Directory.CreateDirectory

    /// 文件夹有就好,没有就创建
    public static void Folder_New(string path)
    {
        if (Directory.Exists(path) == false) //输出path
        {
            Directory.CreateDirectory(path);
        }

    }

stars BuildPipeline.BuildAssetBundles

/****************************************************
    文件:AB.cs
	作者:lenovo
    邮箱: 
    日期:2023/5/6 9:41:45
	功能:
*****************************************************/

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Random = UnityEngine.Random;
 

public static class AB 
{
    public static void Build(
        string outputPath,
        BuildAssetBundleOptions option = BuildAssetBundleOptions.ChunkBasedCompression
    )
    {
        BuildPipeline.BuildAssetBundles
        (
            outputPath,
            option ,
            EditorUserBuildSettings.activeBuildTarget
        );
        AssetDatabase.Refresh();
    }

}





bug 打包时 ‘MenuItemAttribute’ could not be found

The type or namespace name ‘MenuItemAttribute’ could not be found
报错是AB包,报错是跳到打package的脚本

bug Test的dll引用

这个Alt+回车可以解决VS报错,但是Unity报错仍然在
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第6张图片

using NUnit.Framework;
using UnityEngine;

namespace QFramework
{
	public class NewBehaviourScript : MonoBehaviour
	{
#if UNITY_EDITOR
		[UnityEditor.MenuItem("QFramework/Playground")]
		private static void Test()
		{
		}


		[Test]
		public void Playmode()
		{
			Debug.Log(HotUpdateMgr.Instance.GetLocalResVersion());
		}
#endif
	}
}

unity缺少引用

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第7张图片

原版有这两个

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第8张图片

bug ‘EditorUserBuildSettings’ does not exist

The type or namespace name ‘EditorUserBuildSettings’ does not exist in the namespace ‘UnityEditor’
程序集对 Editor的勾选问题。
我这里是新建了一个程序集Common,想把一些脚本复制过来,当时Common程序集没勾选Editor。

watch TestFramework

安装TestFramework,import所有案例(此时只有1.3.4才有案例)
案例2开始可以进行Test
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第9张图片

案例02 Exercise 1_ Solution

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第10张图片
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第11张图片

主脚本


namespace MyExercise_1s
{
    public static class MyMath
    {
        public static int Add(int a, int b)
        {
            return a + b;
        }
    
        public static int Subtract(int a, int b)
        {
            return a - b; // Fixed
        }
    }
}

对主脚本的测试

using MyExercise_1s;
using NUnit.Framework;

namespace Tests_1s
{
    public class MyMathTests
    {
        [Test]
        public void AddsTwoPositiveIntegers()
        {
            Assert.AreEqual(3, MyMath.Add(1, 2));
        }
        
        [Test]
        public void AddAPositiveAndNegativeInteger()
        {
            Assert.AreEqual(1, MyMath.Add(3, -2));
        }
        
        [Test]
        public void SubtractAPositiveInteger()
        {
            Assert.AreEqual(3, MyMath.Subtract(5, 2));
        }
        
        [Test]
        public void SubtractANegativeInteger()
        {
            Assert.AreEqual(7, MyMath.Subtract(5, -2));
        }
    }
}

bug 凉鞋的Test(其中的文件夹)

程序集设置

我这里对着 案例02 的 程序集 复制过来 改名字的
然后Editor文件架下的只勾选Editor

程序集设置 不同处

其它文件架下的,勾选any。
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第12张图片

程序集设置 相同处

上面的设置一样还没报错(盲猜V0_0_4引用了UnityEditor.TestRunner可能有问题)
直接导入凉鞋的包会报错,就是这个引用的问题
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第13张图片

V0_0_4

using UnityEngine;
using UnityEditor;
using UnityEngine.TestTools;
using NUnit.Framework;
using System.Collections;

namespace QFramework
{
    public class V0_0_4
    {
        class SingletonTestClass : Singleton<SingletonTestClass>
        {
            private SingletonTestClass() { }
        }

        [Test]
        public void SingletonTest()
        {
            var instanceA = SingletonTestClass.Instance;
            var instanceB = SingletonTestClass.Instance;

            Assert.AreEqual(instanceA.GetHashCode(), instanceB.GetHashCode());
        }
    }
}

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第14张图片

V0_0_4Editor

#if UNITY_EDITOR
using NUnit.Framework;

namespace QFramework
{
    public class V0_0_4
    {
        class MonoSingletonTestClass : MonoSingleton<MonoSingletonTestClass>
        {

        }

        [Test]
        public void MonoSingeltonTest()
        {
            var instanceA = MonoSingletonTestClass.Instance;
            var instanceB = MonoSingletonTestClass.Instance;

            Assert.AreEqual(instanceA.GetHashCode(), instanceB.GetHashCode());
            Assert.AreEqual(instanceA.name, "MonoSingletonTestClass");
        }
    }
}
#endif

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第15张图片

总结 Test文件夹跑通了

bug 不支持 “EmbeddedLinux”,

    "EmbeddedLinux",报错不支持,

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第16张图片

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第17张图片

watch 凉鞋的Playground(其中的文件夹)

也是赋值修改一个程序集,根据它的引用,去放一个json.
放哪里,内容是什么,自己查引用

{
    "Version":999
}
using NUnit.Framework;
using UnityEngine;

namespace QFramework
{
	public class NewBehaviourScript : MonoBehaviour
	{
#if UNITY_EDITOR
		[UnityEditor.MenuItem("QFramework/Playground")]
		private static void Test()
		{

        }


		[Test]
		public void Playmode()
		{
			Debug.Log(HotUpdateMgr.Instance.GetLocalResVersion());
		}
#endif
	}
}

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第18张图片

bug ‘MenuItem’ could not be found

00 程序及设置没包括Editor
00 放到根目录

bug 过时 UnityEditor.BuildTarget

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第19张图片

watch 凉鞋的AssetBundleExample

注意的是
01 打的两个AB包是6
02 打包的两个方式是 1,4 ,结果都一样,重复打包被自动覆盖
03 用包的前提是不能勾选2
04 用包的两个例子是 3,5
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第20张图片
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第21张图片

bug 导包时的时间

一直认刚开始导包的时间,后面导出的还是开始的时间
DateTime.Now.ToString() 用法

    private static string GeneratePackageName()
    {
      // return "QFramework_" + DateTime.Now.ToString("yyyyMMddHHMM");///注意年小写的yyyy
        return "Common_" + DateTime.Now.ToString("yyyyMMddHHmm");///注意年小写的yyyy
    }

bug 一些Editor的类没识别到

我复制一些相同的脚本到自己的另一个程序集。报错了,如下图将这3个脚本拖到最外面的Editor就正常。
后来发现是 #UNITY_EDITOR的问题(包裹住MenuItem)
。。。
原因盲猜Unity识别不了程序集中的 Editor 中的脚本,需要手动加#UNITY_EDITOR
。。。
原版直接就正常的不需要拖,因为凉鞋直接手写 namespace,不采用程序集的方式。
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第22张图片

---------------------------------------------------

13 框架搭建 决定版:理论强化篇(第三季)

---------------------------------------------------

10 简介 QFramework 使用指南

01 链式编程风格突出(针对回调,计时的)
02 Action => Res => UI (后者基于前者)。对应的里面有Example(示例),Action => Res => UI外加一个libs

modify 我做了什么

01 写注释(Unity的代码就是不能自己写注释,不友好。哪怕通过xml之类的实现注释与代码的分离,只要我悬停鼠标有说明就好了),如图一
02 摘Extensions(框架暂时用你的,Extensions容易抄,整合进我的,也是对自己的Extensions的整理(拖进这个工程没报错))
在这里插入图片描述

watch 2017.3.xxx

直接一样用2017.3左右的版本不会报错导致运行不了,还自动弹出DoTween的面板。
但是还会抛这个错误
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第23张图片

bug 2020.3.23f1c1

modify 引入库Common

像这种,真的是忍不住想用自己的库。

namespace QFramework.Example
{
	using UnityEngine;
    using UnityEngine.UI;
    using DG.Tweening;

    public class DOTweenExample : MonoBehaviour 
	{
        Button mBtnMove;
        GameObject mCube;

        void Start () 
        {
            mCube = GameObject.Find("Cube");
            //mBtnMove = transform.Find("BtnMove").GetComponent

bug 程序集设置

直接导进入,直接使用自动生成的CSharp和Editor两个项目是没有问题的。如图一。
但是导入自带的库,带有的程序集要设置下(看着QFramework的其它程序集设置的,RootName好像感谢也没关系 )。如图二。
主要是 存在同名的 类 ,需要加限定。具体看下一条
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第24张图片

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第25张图片

bug ResMgr、UIMgr等命名在两个程序集之间冲突

因为要用的ResMgr在QFramework是单例类,不是类型(不确定是不是这原因),用不了using xxx=xxx的形式(这个是客观存在的,加了也没用),只能都加限定 QFramework.ResMgr

bug 项目模块识别有误

圈圈中的 (未找到)
Assets/QFramework/Framework/3.EditorToolKit/Editor/UnityEditorRushTools/CustomHierarchy.cs
重新导入,正常没问题的。
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第26张图片

半用 注释掉报错的那5个地方

这5个属于在unity2018被弃用的。但我没找到类似的替代
Assets/QFramework/Framework/3.EditorToolKit/Editor/UnityEditorRushTools/CustomHierarchy.cs
我标了TODO。如图一
。。。
untiy2017还能找到,如图二
unity2020找到不到(好歹给个Obsolute)
手册显示过期
NetworkIdentity
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第27张图片

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第28张图片

没用 删VS缓存

删VS缓存

没用 改为ILCpp

所以又改回默认的Mono

bug unity没报错,VS报错。但能运行

随便截一个,引用关系有啊,如图二
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第29张图片
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第30张图片

watch 总结

01 程序集设置,看里面的其它程序集来设置
02 命名冲突,加限定,我冲突了 ResMgr,UIMgr
03 5个过时语句,暂时注释掉

bug 一个总存在的报错

重新导入+注释那5句过时的
可以考到没其他报错。只有一个不管什么版本都报的错
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第31张图片

bug MonoComplier.Tick

修改增删 程序集 时,多次卡死这 处理条。
就是编译错误。很可能只能任务管理器强制退出,并且下次进入有 EnterSafeMode 的选择面板
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第32张图片
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第33张图片

watch 项目结构

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第34张图片

01 延时

3种计时写法,2种开协程,一种主线程
底层都是 StartCoroutine

namespace QFramework.Example
{
	using UnityEngine;

	public class DelayNodeExample : MonoBehaviour
	{

		private DelayAction mDelay3s = DelayAction.Allocate
		(
			3.0f, () => { Log.I("延时 3s");}
		);

		void Start()
		{
			this.Delay
			(
				1.0f, () => {Log.I("延时 1s");}
			);

			var delay2s = DelayAction.Allocate
			(
				2.0f, () => { Log.I("延时 2s");}
			);
			this.ExecuteNode(delay2s);
		}


		private void Update()
		{
			if (mDelay3s != null 
				&& !mDelay3s.Finished 
				&& mDelay3s.Execute(Time.deltaTime)
			)
			{
				Log.I("Delay3s 执行完成");
			}
		}
	}
}


【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第35张图片

02

using UnityEngine;

namespace QFramework.Example
{
	public class EventNodeExample : MonoBehaviour
	{
		private EventAction mEventNode2 = EventAction.Allocate(
			() => { Log.I("event 3 called"); },
			() => { Log.I("event 4 called"); }
		);


		private void Start()
		{
			var eventNode = EventAction.Allocate(
				() =>{Log.I("event 1 called"); }, 
				() =>{Log.I("event 2 called"); }
			);
			this.ExecuteNode(eventNode);
		}



		private void Update()
		{
			if (mEventNode2 != null 
				&& !mEventNode2.Finished 
				&& mEventNode2.Execute(Time.deltaTime))
			{
				Log.I("eventNode2 执行完成");
			}
		}
	}
}

ResKitExample.Audio

报AB包还是资源的错

using UnityEngine;
using QFramework;
using ResMgr = QFramework.ResMgr;

public class AudioTest : MonoBehaviour 
{
    private void Start()
    {
        ResMgr.Init();

        // 
        AudioManager.Instance.SendMsg(new AudioSoundMsg("TestSound"));

        AudioManager.Instance.SendMsg(new AudioMusicMsg("BackGroundMusic"));

        AudioManager.Instance.SendMsg(new AudioStopMusicMsg());

        AudioManager.PlaySound("TestSound");
        
        AudioManager.PlayMusic("BackgroundMusic");
    }
}

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第36张图片

bug 标点符号写哪边

因为 + - * /和链式编程的 “.”
还是觉得放左边比较泛用。
。。。。。。
但是用过VS,发现,你在比如“,”前面回车,不会自动缩进,“,”后面回车就会自动缩进。
我以为的跟VS默认的,不一样,只能先求同存异
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第37张图片

	public static Button GetButtonDeep
    (
        this Transform root, string childName
        ,UnityEngine.Events.UnityAction action
    )
	{
		Button result   = root.GetButtonDeep(childName);
		result.onClick.AddListener( action );

		return result;
	}
			gameObject
				.Show()
				.Hide()
				.Name("Yeah")
				.Layer(0)
				.Layer("Default")
				.DestroySelf();

watch 注释

其实我不理解为什么宁愿这样写注释(下),也不愿写summary的注释(上)(哪怕只是做教程)
太熟悉了?
简洁?
编译快?
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第38张图片

bug 程序集和命名空间的关系

使用一个方法Identity()同名,完全一样,使用位置是 (程序集CSharp,命名空间QFramework.Example),图中2。
同名一个在( 程序集Common && 没有命名空间),图中1。
同名一个在(程序集QFramework.Core.Runtime && 命名空间QFramework),图中3。
。。。
程序集程序集Common,QFramework.Core.Runtime 都是Auto Refrenced
系统自动认的是 第二个
。。。
不清楚因素,认最近文件夹路径?
命名空间和程序集
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第39张图片

LibsExample.ExtensionExample.GameObjectExample

举了3种示例
GameObject:Object
MonoBehaviour:Behaviour:Component:Object
Transform:Component:Object

using UnityEngine;

namespace QFramework.Example
{
	/// 
	/// CEGO EXAMPLE:GameObject 链式调用支持 
	/// 
	public class GameObjectExample : MonoBehaviour
	{
		private void Start()
		{
			gameObject
				.Show()
				.Hide()
				.Name("Yeah")
				.Layer(0)
				.Layer("Default")
				.DestroySelf();

			// 这里到会断掉,因为GameObject销毁之后就不希望再有操作了
			gameObject.DestroySelfGracefully();


			GameObject instantiatedObj = null;

			gameObject
				.DestroySelfAfterDelay(1.5f)
				.DestroySelfAfterDelayGracefully(1.5f)
				.ApplySelfTo(selfObj => instantiatedObj = selfObj.Instantiate());

            Debug.Log(instantiatedObj);

			#region 通过MonoBehaviour去调用GameObject相关的API

			this
				.Show()
				.Hide()
				.Name("Yeah")
				.Layer(0)
				.Layer("Default")
				.DestroyGameObj();

			this
				.DestroyGameObjGracefully();

			this
				.DestroyGameObjAfterDelay(1.5f)
				.DestroyGameObjAfterDelayGracefully(1.5f)
				.ApplySelfTo(selfScript => instantiatedObj = selfScript.gameObject.Instantiate());

			#endregion


			#region 也可以使用Transform,因为Transform继承了Component,而Core里的所有的链式扩展都默认支持了Component

			transform
				.Show()
				.Hide()
				.Name("Yeah")
				.Layer(0)
				.Layer("Default")
				.DestroyGameObj();

			// 这里到会断掉,因为GameObject销毁之后就不希望再有操作了
			transform
				.DestroyGameObjGracefully();

			transform
				.DestroyGameObjAfterDelay(1.5f)
				.DestroyGameObjAfterDelayGracefully(1.5f)
				.ApplySelfTo(selfTrans => instantiatedObj = selfTrans.gameObject.Instantiate());

			#endregion
		}
	}
}

LibsExample.DOTweenExample

namespace QFramework.Example
{
	using UnityEngine;
    using UnityEngine.UI;
    using DG.Tweening;

    public class DOTweenExample : MonoBehaviour 
	{
        Button mBtnMove;
        GameObject mCube;

        void Start () 
        {
            mCube = GameObject.Find("Cube");
            //mBtnMove = transform.Find("BtnMove").GetComponent

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第40张图片

LibsExample.ExtensionExample

都是看脚本,所以有了下一条的收录
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第41张图片

modify 如果你需要收录一些可以转移(转移影响不大)的脚本

01 UnityAPIExtensions.cs
02 DotNetExtensions.cs
A Framework.Core.Runtime
B Framework.Core.Editor
C Common(你自己的)
。。。
01全部搬空到Common程序集,删掉旧脚本,让A引用C
01调用了02,所以一起搬,一起删不然引用循环错误(A引用B,B又引用了A)。也让B引用C
。。。
总结,转移并且删掉了原来的 UnityAPIExtensions.cs,DotNetExtensions.cs
。。。
可以看到没报【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第42张图片

LibsExample.IOCExample

底层应该是找程序集,找类型,

using UnityEngine;

namespace QFramework.Example
{
	public class InjectExample : MonoBehaviour
	{
		[Inject] public A AObj;	//注入

		// Use this for initialization
		void Start()
		{
			var container = new QFrameworkContainer();
			container.RegisterInstance(new A());//放入字典
			container.Inject(this);//注入
			
			container.Resolve<A>().HelloWorld(); //解决
		}

		public class A
		{
			public void HelloWorld()
			{
				"This is A obj".LogInfo();
			}
		}
	}
}

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第43张图片

【未完成】LibsExample.NetworkExample

01 我们刚上手的,直接拆类(一个类一个脚本)
02 按命名空间分 QFramework.、 QFramework.Example和暴露的(CSharp)
03 看脚本时,看到PCClient,MobileServer(不清楚Clent要用PC做定语言,Server要用Mobile作定语)
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第44张图片

拉父类

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第45张图片

打包Client,uity运行Server

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第46张图片

打包Server,unity运行Client

bug 打包的运行后找不到资源

预制体的路径保持不变,我加了文件夹Prefabs,放在里面。这个没影响
01 打AB包,图2

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第47张图片
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第48张图片

bug 找到不到AB包

有打在StreamingAssets,但是还报这错误。
但是在Unity运行就不会。

Failed to Create Res. Not Find AssetData:AssetName:UIMsg BundleName: TypeName: Key:uimsg

。。。。。。

	[QMonoSingletonPath("[Framework]/MobileServer")]
	public class MobileServer : MonoSingleton<MobileServer>
	{
	......

        private IEnumerator Start()
		{
            UIMgr.OpenPanel<UIMsg>();

跑到了如下图,那就是文件夹Resources的事所以新建文件夹Resources,拖进预制体,打包,Build

namespace QFramework
{
    public static class ResFactory
    {
        public static IRes Create(ResSearchRule resSearchRule)
        {
            var lowerAssetName = resSearchRule.AssetName.ToLower();
            
            short assetType = 0;
            if (lowerAssetName.StartsWith("resources/") || lowerAssetName.StartsWith("resources://"))
            {
                assetType = ResType.Internal;
            }

bug 套接字不能重复

reimport解决的

bug 突然间不能附加进程调试

先了解引用关系
以前有一种解决方式reImport

UniRx.Async:
UniRx.Async.Editor:UniRx.Async
UniRx:UniRx.Async
UniRx.Example:UniRx、UniRx.Async

LibsExample.BindingsRxExample

using UnityEngine;
using UnityEngine.UI;
using BindingsRx;
using BindingsRx.Bindings;
using BindingsRx.Converters;
using BindingsRx.Exceptions;
using BindingsRx.Extensions;
using BindingsRx.Filters;

namespace QFramework.Example
{
    public class BindingsRxExample : MonoBehaviour
    {

        [SerializeField]  InputField mInputField;
        [SerializeField]  Text mText;

        void Start()
        {
            Transform canvas = transform.FindTop("Canvas");
            mInputField = canvas.Find("InputField").GetComponent<InputField>();
            mText = canvas.Find("Text").GetComponent<Text>();
            
            // from,to。左边的改变会影响右边
            mInputField.BindTextTo
            (
                () => mText.text
                , text => mText.text = text
            );
        }
    }
}

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第49张图片

LibsExample.JsonPathProtobuf

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第50张图片


using System;
using UnityEngine;
using UnityEngine.UI;

namespace QFramework
{
    public class JsonPathProtobuf : MonoBehaviour
    {

        ProtoBufTest tempProto = new ProtoBufTest
        {
            ID = 1,
            Msg = "Hello"
        };

        JsonTest tempJson = new JsonTest { Age = 18 };
        string assetsRoot = "Assets/QFramework/Example/LibsExample/JsonPathProtobuf/";
        string appRoot;// Application.dataPath不能写这里

        private void Start()
        {
            appRoot = Application.dataPath + "/QFramework/Example/LibsExample/JsonPathProtobuf/";
            ShowText();
                


            SaveProtoBuff();
            LoadProtoBuff();
            SaveJson();
            LoadJson();
        }


        #region 辅助


        private void ShowText()
        {
            Text text = transform.FindTop("Canvas").GetComponentInChildren<Text>();
            text.text = "P 保存protoBuf";
            text.text += "\nO 读取protoBuf";
            text.text += "\nA 保存json";
            text.text += "\nS 读取json";
        }

        private void LoadJson()
        {
            this.Sequence()
                .Until(() => {
                    return Input.GetKeyDown(KeyCode.S);
                })
                .Event(() => {
                    string path = appRoot + "/TestJosn/TestJson.json";
                    JsonTest tempLoadJson = SerializeHelper.LoadJson<JsonTest>(path);
                    Debug.Log(tempLoadJson.Age);
                })
                .Begin();
        }

        private void SaveJson()
        {
            this.Sequence()
                .Until(() => {
                    return Input.GetKeyDown(KeyCode.A);
                })
                .Event(() => {
                    string path = appRoot + "TestJosn".CreateDirIfNotExists();
                    path += "/TestJson.json"; tempJson.SaveJson(path);
#if UNITY_EDITOR
                    UnityEditor.AssetDatabase.Refresh();
#endif
                })
                .Begin();
        }

        private void LoadProtoBuff()
        {
            this.Sequence()
                .Until(() => {
                    return Input.GetKeyDown(KeyCode.O);
                })
                .Event(() => {

                    string path = appRoot + "TestJosn/testPro.proto";
                    ProtoBufTest tempLoadBuf = SerializeHelper.LoadProtoBuff<ProtoBufTest>(path);
                    Debug.Log(tempLoadBuf.ID);
                })
                .Begin();
        }

        private void SaveProtoBuff()
        {
            this.Sequence()
                .Until(() => {
                    return Input.GetKeyDown(KeyCode.P);
                })
                .Event(() => {
                    string path = (assetsRoot + "TestJosn").CreateDirIfNotExists();
                    path += "/testPro.proto";
                    tempProto.SaveProtoBuff(path);
#if UNITY_EDITOR
                    UnityEditor.AssetDatabase.Refresh();
#endif

                })
                .Begin();
        }
        #endregion  

    }


    #region 内部类



    [ProtoBuf.ProtoContract]
    public class ProtoBufTest
    {
        [ProtoBuf.ProtoMember(1)]
        public int ID=0;

        [ProtoBuf.ProtoMember(2)]
        public string Msg="Hello";
    }

    [System.Serializable]
    public class JsonTest
    {
        private string mName;
        public string Name
        {
            get { return mName; }
            set { mName = value; }
        }
        private int mAge;
        public int Age
        {
            get { return mAge; }
            set { mAge = value; }
        }
    }
    #endregion


}


bug IL2CPP

改回Mono
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第51张图片

LibsExample/SingletonExample/0.Singleton

Singleton
MonoSingleton
ISingleton,MonoBehaviour
ISingleton

LibsExample/SingletonExample/0.Singleton

单例执行删除,但静态变量仍然存在着

namespace QFramework.Example
{
	using UnityEngine;

	
	public class Singleton : MonoBehaviour
	{
		private void Start()
		{
			Class2Singleton.Instance.Log("Hello World!");
			
			Class2Singleton.Instance.Dispose();//删除
			
			// a differente instance
			Class2Singleton.Instance.Log("Hello World!");
		}
	}
}

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第52张图片

namespace QFramework.Example
{
    using UnityEngine;

    internal class Class2Singleton : Singleton<Class2Singleton>
    {
        private static int mIndex = 0;

        private Class2Singleton() { }

        public override void OnSingletonInit()
        {
            mIndex++;
        }

        public void Log(string content)
        {
            Debug.Log("Class2Singleton" + mIndex + ":" + content);
        }
    }
}

LibsExample/SingletonExample/2.SingletonProperty

看MonoSingleton的生命周期
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第53张图片

namespace QFramework.Example
{
	using System.Collections;
	using UnityEngine;


	public class MonoSingletonExample : MonoBehaviour
	{
		private IEnumerator Start()
		{
			var instance = Class2MonoSingleton.Instance;

			yield return new WaitForSeconds(3.0f);
			
			instance.Dispose();
		}
	}
}
namespace QFramework.Example
{
    using System.Collections;
    using UnityEngine;

    internal class Class2MonoSingleton : MonoSingleton<Class2MonoSingleton>
    {
        public override void OnSingletonInit()
        {
            Debug.Log(name + ":" + "OnSingletonInit");
        }

        private void Awake()
        {
            Debug.Log(name + ":" + "Awake");
        }

        private void Start()
        {
            Debug.Log(name + ":" + "Start");
        }

        protected override void OnDestroy()
        {
            base.OnDestroy();

            Debug.Log(name + ":" + "OnDestroy");
        }
    }
}

LibsExample/UniRxExample

UITestUniRx

一个预制体,叫Xxx
两个脚本,都是partial,脚本1命名为 XxxComponents(我改成Xxx.Components),脚本2叫Xxx

watch 01 UITestUniRx.Components

using UnityEngine;
using UnityEngine.UI;
using QFramework;

namespace QFramework.Example
{
	public partial class UITestUniRx
	{
		[SerializeField] public Toggle Toggle;
		[SerializeField] public Button Button;
		[SerializeField] public InputField InputField;
        [SerializeField] public Text Text;
	}
}

watch 01 UITestUniRxData


using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using QFramework;
using UniRx;

namespace QFramework.Example
{
	public class UITestUniRxData : UIPanelData
	{
		// TODO: Query Mgr's Data
	}

	public partial class UITestUniRx : UIPanel
	{
		protected override void InitUI(IUIData uiData = null)
		{
		}

		protected override void ProcessMsg (int eventId,QMsg msg)
		{
			throw new System.NotImplementedException ();
		}

		protected override void RegisterUIEvent()
		{
            Button
				.onClick
                .AsObservable()//可被观察
                .Subscribe(x=> this.LogInfo("按下按钮"));//点击了就打印
        
            InputField
				.OnValueChangedAsObservable() //值发生变化时
                .Where(x => x != null)		 //当x!=null时
                .SubscribeToText(Text);	   //变换Text的值

            Toggle
				.OnValueChangedAsObservable() //值发生变化时
                .SubscribeToInteractable(Button); //设置是否可交互
        }

		protected override void OnShow()
		{
			base.OnShow();
		}

		protected override void OnHide()
		{
			base.OnHide();
		}

		protected override void OnClose()
		{
		}

		void ShowLog(string content)
		{
			Debug.Log("[ UITestUniRx:]" + content);
		}
	}
}

watch 01、02 测试的(01、 02的效果测试)



using System.Collections.Generic;
using UnityEngine;
using QFramework;
using QFramework.Example;
using UniRx;
using UnityEngine.UI;
using System;
using System.Text;
using UnityEngine.Networking;
using System.Collections;

namespace LFramework
{
    /// 
    /// 2018/3/30
    /// 
    public class TestUniRx : MonoBehaviour
    {
        #region 字属


        public static readonly UniRx.Diagnostics.Logger log =   new UniRx.Diagnostics.Logger("L Log");
        //IReactiveProperty isChange      = new ReactiveProperty(false);


        [Header("ReactiveSubscribe的")]
        private CompositeDisposable disposables = new CompositeDisposable();
        /// ReactiveSubscribe的初始符
        bool ReactiveSubscribeFirst = false;
        private IDisposable CurrentSub;
        #endregion

        #region 测试
        void Start()
        {
            QFramework.ResMgr.Init();
            ReactiveSubscribeFirst = false;
            TestStart01();
            TestStart02();


        }

        void TestStart01()
        { 
            QFramework.UIMgr.OpenPanel<UITestUniRx>();
        }
        void TestStart02()
        {
            //说明怎么操作
            Debug.Log( String.Format(
                  "( a , DoubleClick);           //双击                    \n "
                + "( s , WWW);                   //WWW                     \n "
                + "( d , Property);              //属性监听(T键改变值)   \n "
                + "( f , Coroutine);             //和unity协程             \n "
                + "( g , ReactiveSubscribe);     //收集器                  \n "
                + "( h , TsfSubscribe);          //transform               \n  "
                + "空格就退出\n "                
                ) );
            Dictionary<string, Action> m_FuncDic = new Dictionary<string, Action>();
            m_FuncDic.Add("a", DoubleClick);           //双击
            m_FuncDic.Add("s", WWW);                   //WWW
            m_FuncDic.Add("d", Property);              //属性监听
            m_FuncDic.Add("f", Coroutine);             //和unity协程
            m_FuncDic.Add("g", ReactiveSubscribe);     //收集器
            m_FuncDic.Add("h", TsfSubscribe);          //transform

            //UniRx.Diagnostics.ObservableLogger//这里应该只是演示一种格式
            //    .Listener
            //    .Subscribe(_ => Debug.Log(_));

            // m_FuncDic中,按了什么键,执行什么方法
            Observable.EveryUpdate()
                .Do((x) => {
                    if (Input.inputString != string.Empty && Input.inputString != " ")
                    {
                        Debug.Log(Input.inputString);
                        if (m_FuncDic.ContainsKey(Input.inputString))
                        {
                            if (CurrentSub != null)
                            { 
                                CurrentSub.Dispose();
                            }
                            m_FuncDic[Input.inputString].InvokeGracefully();
                        }
                    }
                })
                .Subscribe()
                .AddTo(this);

            
            Observable.EveryUpdate()
                .Where(_ => Input.GetKeyDown(KeyCode.Space))
                .Subscribe(_ => {
                    disposables.Dispose();
                    disposables.Clear();
                })
                .AddTo(this);
        }


        #endregion



        #region 辅助
        /// 双击
        void DoubleClick()
        {
            var stream = Observable
                .EveryUpdate()
                .Where(x => Input.GetMouseButtonDown(0));

            CurrentSub = stream
                .Buffer(stream.Throttle(TimeSpan.FromSeconds(0.25f)))
                .Do(x => Debug.Log("在检测"))
                .Where(x => x.Count >= 2)
                .Subscribe(x => Debug.Log("按下次数" + x.Count));
        }

        void WWW()
        {
            ObservableWWW
                //.GetWWW("http://img.taopic.com/uploads/allimg/120428/128240-12042Q4020849.jpg")//这地址没东西了
                .GetWWW("https://patchwiki.biligame.com/images/blhx/thumb/a/a3/0ldcv3eg1w6c27witzhw69rskhlurum.jpg/350px-%E5%A4%A7%E5%87%A4%E6%8D%A2%E8%A3%855.jpg")
                .Subscribe(down =>{
                    Texture2D temp2d = down.texture;
                    Debug.Log(temp2d.name);
                    Sprite tempSp = Sprite.Create(temp2d
                        , new Rect(0, 0, temp2d.width, temp2d.height)
                        , Vector2.zero);
                    QFramework.UIMgr.GetPanel<UITestUniRx>().GetComponent<Image>().sprite = tempSp;
                }, x => Debug.Log("请求错误"))
                .AddTo(disposables);
        }


        /// 属性
        void Property()
        {
            IReactiveProperty<bool> m_Bool = new ReactiveProperty<bool>(false);
            m_Bool.Subscribe(xs => Debug.Log("值改变"));

            CurrentSub = Observable.EveryUpdate()
                .Where(_ => Input.GetKeyDown(KeyCode.T))
                .Subscribe(_ => m_Bool.Value = !m_Bool.Value);
        }


        /// 协程
        void Coroutine()
        {
            Sample10_MainThreadDispatcher temp = new Sample10_MainThreadDispatcher();
            CurrentSub = temp.Run();
            Debug.Log(temp);
        }

        /// GameObj
        void ReactiveSubscribe()
        {

            if (ReactiveSubscribeFirst == false)
            { 
                ReactiveSubscribeFirst= true;

            }
            disposables = new CompositeDisposable();
            ReactiveCollection<int> m_ReaList = new ReactiveCollection<int>();
            //
            m_ReaList.ObserveCountChanged()
                .Subscribe(x => { Debug.Log("变"+x); })
                .AddTo(disposables);

            m_ReaList.ObserveAdd()
                .Subscribe(x => { Debug.Log("加"+x); })
                .AddTo(disposables);

            m_ReaList.ObserveRemove()
                .Subscribe(x => Debug.Log("减"+x))
                .AddTo(disposables);
            //
            m_ReaList.Add(1);
            m_ReaList.Remove(1);
            CurrentSub = disposables;
            Debug.Log("-------------------------------");
        }

        /// transform
        void TsfSubscribe()
        {
            CurrentSub = transform
                .ObserveEveryValueChanged(x => x.position)
                .Subscribe(x => Debug.Log(x));
        }
        #endregion



        #region 内部类

        /// 从Assets/QFramework/Example/LibsExample/UniRxExample/OfficialExamples/Sample10_MainThreadDispatcher.cs
        /// 复制修改的类
        ///  都运行打印很乱,可以注释其它一个一个运行
        /// 
        public class Sample10_MainThreadDispatcher
        {
            public CompositeDisposable Run()
            {


                Debug.Log("--------------------------");
                CompositeDisposable disposable = new CompositeDisposable();
                // MainThreadDispatcher is heart of Rx and Unity integration
                // StartCoroutine can start coroutine besides MonoBehaviour.
                MainThreadDispatcher.StartCoroutine(TestAsync());//调用一次,执行一次


                // We have two way of run coroutine, FromCoroutine or StartCoroutine.
                // StartCoroutine is Unity primitive way and it's awaitable by yield return.
                // FromCoroutine is Rx, it's composable and cancellable by subscription's IDisposable.
                // FromCoroutine's overload can have return value, see:Sample05_ConvertFromCoroutine
                Observable.FromCoroutine(TestAsync)//调用一次,执行一次
                    .Subscribe()
                    .AddTo(disposable);


                // Add Action to MainThreadDispatcher. Action is saved queue, run on next update.
                MainThreadDispatcher.Post(_ => Debug.Log("test"), null); //调用一次,执行一次


                // Timebased operations is run on MainThread(as default)
                // All timebased operation(Interval, Timer, Delay, Buffer, etc...)is single thread, thread safe!
                Observable.Interval(TimeSpan.FromSeconds(1))//每隔一秒x++
                    .Subscribe(x => Debug.Log(x))
                    .AddTo(disposable);


                // Observable.Start use ThreadPool Scheduler as default.
                // ObserveOnMainThread return to mainthread
                Observable.Start(() => Unit.Default) // asynchronous work ;打印了Unit的ToString()方法
                    .ObserveOnMainThread()
                    .Subscribe(x => Debug.Log(x))
                    .AddTo(disposable);
                //
                return disposable;
            }

            IEnumerator TestAsync()
            {
                Debug.Log("a");
                yield return new WaitForSeconds(1);
                Debug.Log("b");
                yield return new WaitForSeconds(1);
                Debug.Log("c");
                yield return new WaitForSeconds(1);
                Debug.Log("d");
            }
        }

        #endregion      

    }
}


watch 01 效果

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第54张图片

watch 02 效果

检测双击的

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第55张图片

网图WWW

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第56张图片

监听一个布尔值

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第57张图片

监听一个列表

单独贴一下。
运行时,Add一下,后面自动Change
Remove一下,后面也自动Change
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第58张图片

        /// GameObj
        void ReactiveSubscribe()
        {

            if (ReactiveSubscribeFirst == false)
            { 
                ReactiveSubscribeFirst= true;

            }
            disposables = new CompositeDisposable();
            ReactiveCollection<int> m_ReaList = new ReactiveCollection<int>();
            //
            m_ReaList.ObserveCountChanged()
                .Subscribe(x => { Debug.Log("变"+x); })
                .AddTo(disposables);

            m_ReaList.ObserveAdd()
                .Subscribe(x => { Debug.Log("加"+x); })
                .AddTo(disposables);

            m_ReaList.ObserveRemove()
                .Subscribe(x => Debug.Log("减"+x))
                .AddTo(disposables);
            //
            m_ReaList.Add(1);
            m_ReaList.Remove(1);
            CurrentSub = disposables;
            Debug.Log("-------------------------------");
        }

监听Transform

LibsExample/UniRxExample/OfficialExamples

Sample01_ObservableWWW

只写方法,自己用MonoBehaviour来调用

ObservableWWW.Get

        /// 
        private void StartTest01()
        {
            // Basic: Download from google.
                //ObservableWWW.Get("http://google.co.jp/") //我这边超时错误
                ObservableWWW
                    .Get("https://baidu.com/")//返回
                    .Subscribe(
                        onNext:  res  => Debug.Log(res.Substring(0, 100)), // onSuccess
                        onError: error => Debug.LogException(error)); // onError
        }

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第59张图片

from、select

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第60张图片

        private void StartTest02()
        {
            int textId = 2;//外网测不了时
            if(textId == 1)
            {
                // Linear Pattern with LINQ Query Expressions
                // download after google, start bing download
                var query = from google in ObservableWWW.Get("http://google.com/")
                            from bing in ObservableWWW.Get("http://bing.com/")
                            select new { google, bing };



                var cancel = query.Subscribe(x => {
                    Debug.LogFormat("{0}:{1}"
                        , x.google.Substring(0, 100)
                        , x.bing.Substring(0, 100));
                });            
                // Call Dispose is cancel downloading.
                cancel.Dispose();
            }
            if(textId ==2)//有时会报错Empty reply from server,多运行几下
            { 
                var query = from baidu in ObservableWWW.Get("http://baidu.com/")
                              from sougou in ObservableWWW.Get("http://sougou.com/")
                              select new { baidu, sougou };


                var cancel = query
                    .Subscribe(res => {

                        Debug.Log(res.baidu);
                        Debug.Log(res.sougou);
                        Debug.LogFormat("{0}:{1}"
                            , res.baidu.Substring(0, 5)
                            , res.sougou.Substring(0, 5));
                });
                // Call Dispose is cancel downloading.
                //cancel.Dispose();
            }
        }

WhenAll

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第61张图片

       private void StartTest03_WhenAll()
        {
            int curID = 2;
            if (curID == 1)
            {
                // Observable.WhenAll is for parallel asynchronous operation
                // (It's like Observable.Zip but specialized for single async operations like Task.WhenAll of .NET 4)
                var parallel = Observable.WhenAll(
                    ObservableWWW.Get("http://google.com/"),
                    ObservableWWW.Get("http://bing.com/"),
                    ObservableWWW.Get("http://unity3d.com/"));

                parallel.Subscribe(xs =>
                {
                    Debug.Log(xs[0].Substring(0, 100)); // google
                    Debug.Log(xs[1].Substring(0, 100)); // bing
                    Debug.Log(xs[2].Substring(0, 100)); // unity
                });
            }

            if (curID == 2)
            {
                //意思是res的复数
                var reses = Observable.WhenAll(
                    ObservableWWW.Get("https://baidu.com/")
                    , ObservableWWW.Get("https://sougou.com/")
                    , ObservableWWW.Get("https://www.bilibili.com/")
                );

                reses.Subscribe(res =>
                {
                    Debug.Log(res[0].Substring(0, 100));
                    Debug.Log(res[1].Substring(0, 100));
                    Debug.Log(res[2].Substring(0, 100));
                });
            }

        }

ScheduledNotifier进度

直接跑100%
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第62张图片

        private void StartTest04_ScheduledNotifier()
        {
            int curID = 2;
            if (curID == 1)
            {
                // with Progress
                // notifier for progress
                var progressNotifier = new ScheduledNotifier<float>();
                progressNotifier.Subscribe(x => Debug.Log(x)); // write www.progress

                // pass notifier to WWW.Get/Post
                ObservableWWW
                    .Get(url: "http://google.com/", progress: progressNotifier)
                    .Subscribe();
            }
            if (curID == 2)
            {
                var scheduledNotifier = new ScheduledNotifier<float>();
                scheduledNotifier.Subscribe(x => Debug.Log(x));


                ObservableWWW
                    .Get(url: "http://baidu.com/", progress: scheduledNotifier)
                    .Subscribe();
            }
        }

WWWErrorException

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第63张图片

       private void StartTest05_WWWErrorException()
        {
            int curID = 2;
            if (curID == 1)
            {
                // with Error
                // If WWW has .error, ObservableWWW throws WWWErrorException to onError pipeline.
                // WWWErrorException has RawErrorMessage, HasResponse, StatusCode, ResponseHeaders
                ObservableWWW
                    .Get("http://www.google.com/404")
                    .CatchIgnore((WWWErrorException ex) =>
                    {
                        Debug.Log(ex.RawErrorMessage);
                        if (ex.HasResponse)
                        {
                            Debug.Log(ex.StatusCode);
                        }
                        foreach (var item in ex.ResponseHeaders)
                        {
                            Debug.Log(item.Key + ":" + item.Value);
                        }
                    })
                    .Subscribe();
            }
            if (curID == 2)
            {
                ObservableWWW.Get("https://www.bilibili.com/404")
                    .CatchIgnore((WWWErrorException error) =>
                    {
                        Debug.Log(error.RawErrorMessage);
                        if (error.HasResponse)
                        {
                            Debug.Log(error.StatusCode);
                        }
                        string str = "";
                        foreach (var item in error.ResponseHeaders)
                        {
                            str+=item.Key + ":" + item.Value+"\n";
                        }

                        Debug.Log(str);
                    })
                    .Subscribe();
            }
        }

Sample02_ObservableTriggers

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第64张图片

      void Do_ObservableUpdateTrigger()
        {
            int curID = 2;
            if (curID == 1)
            {
                // Get the plain object
                var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

                // Add ObservableXxxTrigger for handle MonoBehaviour's event as Observable
                cube.AddComponent<ObservableUpdateTrigger>()
                    .UpdateAsObservable()
                    .SampleFrame(30)
                    .Subscribe(
                        res => Debug.Log("cube")
                        , () => Debug.Log("destroy"));

                // destroy after 3 second:)
                GameObject.Destroy(cube, 6f);
            }

            if (curID == 2)
            {
                var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

                cube.AddComponent<ObservableUpdateTrigger>()
                    .UpdateAsObservable()
                    .SampleFrame(30)
                    .Skip(1)
                    .Subscribe(_ => {
                        Debug.Log("cube");
                        Debug.Log("destroy");
                    });

                GameObject.Destroy(cube, 4f);
            }
        }

Sample03_GameObjectAsObservable(UpdateAsObservable、OnMouseUpAsObservable)

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第65张图片

        void Start()
        {
            int curId = 2;
            if (curId == 1)
            {
                // All events can subscribe by ***AsObservable if enables UniRx.Triggers
                this.OnMouseDownAsObservable()
                    .SelectMany(_ => this.gameObject.UpdateAsObservable())
                    .TakeUntil(this.gameObject.OnMouseUpAsObservable())//结束标志
                    .Select(_ => Input.mousePosition)
                    .RepeatUntilDestroy(this)
                    .Subscribe(pos => Debug.Log(pos), () => Debug.Log("!!!" + "complete"));
            }
            if (curId == 2)
            {
                // All events can subscribe by ***AsObservable if enables UniRx.Triggers
                this.OnMouseDownAsObservable()//鼠标点击
                    .SelectMany(_ => this.gameObject.UpdateAsObservable())//点击的是一个物体
                    .TakeUntil(this.gameObject.OnMouseUpAsObservable())//结束标志
                    .Select(_ => Input.mousePosition) //在结果中选择 pos
                    .RepeatUntilDestroy(this) //不断重复这个过程直到销毁
                    .Subscribe(
                         onNext: pos => Debug.Log(pos), 
                         onCompleted: () => Debug.Log("!!!" + "complete")
                     );
            }
        }

Sample04_ConvertFromUnityCallback

就输出了+LogCallback
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第66张图片

using System;
using UnityEngine;

namespace UniRx.Examples
{
    public class Sample04_ConvertFromUnityCallback : MonoBehaviour
    {
        void Awake()
        {
            // method is separatable(分离) and composable(组合)
            LogHelper
                .LogCallbackAsObservable()
                .Where( x => (x.LogType == LogType.Warning)  )
                .Subscribe(x => Debug.Log(x));

            LogHelper
                .LogCallbackAsObservable()
                .Where(x => (x.LogType == LogType.Error) )
                .Subscribe(x => Debug.Log(x));
        }

        private void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                Debug.LogWarning("LogWarning");
                Debug.LogError("LogError");
            }
        }


        #region 内部类


        // This is about log but more reliable log sample => Sample11_Logger

        private class LogCallback
        {
            public string Condition;
            public string StackTrace;
            public UnityEngine.LogType LogType;
        }

        static class LogHelper
        {
            // If static register callback, use Subject for event branching.

#if (UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7)                    
            static Subject<LogCallback> subject;

            public static IObservable<LogCallback> LogCallbackAsObservable()
            {
                if (subject == null)
                {
                    subject = new Subject<LogCallback>();

                    // Publish to Subject in callback


                    UnityEngine.Application.RegisterLogCallback((condition, stackTrace, type) =>
                    {
                        subject.OnNext(new LogCallback { Condition = condition, StackTrace = stackTrace, LogType = type });
                    });
                }

                return subject.AsObservable();
            }

#else
            // If standard evetns, you can use Observable.FromEvent.

            public static IObservable<LogCallback> LogCallbackAsObservable()
            {
                return Observable.FromEvent<Application.LogCallback, LogCallback>(
                    conversion: h 
                    => ( 
                        condition, 
                        stackTrace, 
                        type) 
                    => h( new LogCallback { 
                        Condition = condition, 
                        StackTrace = stackTrace, 
                        LogType = type
                    }),
                    addHandler:    h => Application.logMessageReceived += h, 
                    removeHandler: h => Application.logMessageReceived -= h);
            }
#endif
        }
        #endregion



    }
}

Sample05_ConvertFromCoroutine

拿到了,但是格式错误,查了官网没看出哪错了
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第67张图片

启动脚本 Sample05_ConvertFromCoroutine_Start

/****************************************************
    文件:Sample05_ConvertFromCoroutine_Start.cs
	作者:lenovo
    邮箱: 
    日期:2023/6/10 9:21:46
	功能:对应的测试脚本
*****************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;

namespace UniRx.Examples
{
    public class Sample05_ConvertFromCoroutine_Start : MonoBehaviour
    {
        #region 属性

        #endregion

        #region 生命



        /// 首次载入且Go激活
        void Start()
        {
            Sample05_ConvertFromCoroutine.GetWWW("https://www.baidu.com",gameObject);
            //https://docs.unity.cn/2021.3/Documentation/ScriptReference/Networking.UnityWebRequest.Get.html
            //"https://www.example.com"
            //https://error.html"
        }


        #endregion

    }
}




Sample05_ConvertFromCoroutine

using System;
using System.Collections;
using System.Threading;
using UnityEngine;
#if UNITY_2018_3_OR_NEWER
#pragma warning disable CS0618
#endif

namespace UniRx.Examples
{
    public class Sample05_ConvertFromCoroutine
    {
        // public method
        public static IObservable<string>  GetWWW(string url,GameObject gameObject=null)
        {
            int curID = 2;   
            if (curID == 1)
            { 
          
                // convert coroutine to IObservable
                // cancellation ,取消的名词
                // Token,目的为了减轻服务器压力,方式是对请求数据(用户名与密码)的加工
                return Observable
                    .FromCoroutine<string>((observer, cancellationToken) 
                         => GetWWWCore(url, observer, cancellationToken)
                    );            
            }
            if (curID == 2)
            {
                return (IObservable<string>)Observable
                    .FromCoroutine<string>((observer, cancellationToken)
                        => GetWWWCore(url, observer, cancellationToken))
                    .Subscribe(
                        _ => Debug.Log("OnNext"),
                        () => Debug.Log("OnCompleted"))
                    .AddTo(gameObject);
            }

            return null;



        }

        // IEnumerator with callback
        static IEnumerator GetWWWCore(string url
            , IObserver<string> observer
            , CancellationToken cancellationToken)
        {
            var www = new UnityEngine.WWW(url);
            while (!www.isDone && !cancellationToken.IsCancellationRequested)//连接中
            {           
               
                yield return null;
            }

            if (cancellationToken.IsCancellationRequested)//取消连接
            {
                yield break;
            } 

            if (www.error != null) //连接错误
            {
                observer.OnError(new Exception(www.error));
            }
            else  //连接成功
            {
                observer.OnNext(www.text);
                Debug.Log(www.text);
                observer.OnCompleted();
            }
        }
    }
}
#if UNITY_2018_3_OR_NEWER
#pragma warning restore CS0618
#endif

Sample06_ConvertToCoroutine

一个打印数字
一个请求网址,有时会报错(unity3d.com)报错概率很高
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第68张图片

using System;
using System.Collections;
using UnityEngine;

namespace UniRx.Examples
{
    public class Sample06_ConvertToCoroutine : MonoBehaviour
    {
        // convert IObservable to Coroutine
        void Start()
        {
            StartCoroutine(  NormalCoroutine()  );
            StartCoroutine( TestNewCustomYieldInstruction()  );
        }



        #region 辅助


        /// =Range(1, 10),然后Return(100)
        IEnumerator NormalCoroutine()     
            

        {
            yield return new WaitForSeconds(1);


            var val = default(int);
            yield return Observable
                .Range(1, 10)
                .StartAsCoroutine(x => { val = x; });


            Debug.Log(val); // 10(callback is last value)
            yield return new WaitForSeconds(3);


            yield return Observable
                .Return(100)
                .StartAsCoroutine(x => { val = x; });


            Debug.Log(val); // 100
        }


        #region TestNewCustomYieldInstruction


        // Note:ToAwaitableEnumerator/StartAsCoroutine/LazyTask are obsolete way on Unity 5.3
        // You can use ToYieldInstruction.

#if !(UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
#if UNITY_2018_3_OR_NEWER
#pragma warning disable CS0618
#endif

        IEnumerator TestNewCustomYieldInstruction()
        {
            // wait Rx Observable.
            yield return Observable
                .Timer(TimeSpan.FromSeconds(1))
                .ToYieldInstruction();


            // you can change the scheduler(this is ignore Time.scale)
            yield return Observable
                .Timer( TimeSpan.FromSeconds(1), Scheduler.MainThreadIgnoreTimeScale )
                .ToYieldInstruction();


            // get return value from ObservableYieldInstruction
            var oWWW = ObservableWWW
                //.Get("http://unity3d.com/")
                .Get("https://www.baidu.com/")
                .ToYieldInstruction(throwOnError: false);
            yield return oWWW;                                                                                                                    


            if (oWWW.HasError) 
            { 
                Debug.Log("oWWW.Error\n" + oWWW.Error.ToString()); 
            }
            if (oWWW.HasResult)
            { 
                Debug.Log("oWWW.Result\n"+ oWWW.Result); 
            }

            // other sample(wait until transform.position.y >= 100)
            // 这块我打印不出什么来验证
            yield return this
                .ObserveEveryValueChanged(go => go.transform)
                .FirstOrDefault(trans => trans.position.y >= 100 )
                .ToYieldInstruction();

        }
#if UNITY_2018_3_OR_NEWER
#pragma warning restore CS0618
#endif
#endif
        #endregion
        #endregion


    }
}

Sample07_OrchestratIEnumerator

运行了两次,第二次单击鼠标结束协程
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第69张图片

#pragma warning disable 0168
#pragma warning disable 0219

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace UniRx.Examples
{
    public class Sample07_OrchestratIEnumerator : MonoBehaviour
    {


        void Start()
        {
            // after completed AsyncA, run AsyncB as continuous routine.
            // UniRx expands SelectMany(IEnumerator) as SelectMany(IEnumerator.ToObservable())
            var cancel = Observable
               .FromCoroutine(AsyncA)
                .SelectMany(AsyncB)//==.SelectMany(AsyncB.ToObservable())
                .Subscribe();



            // If you want to stop Coroutine(as cancel), call subscription.Dispose()
            // cancel.Dispose();
            Observable.EveryUpdate()
                .Where(_ => Input.GetMouseButtonDown(0))
                .Subscribe(_ => cancel.Dispose(), () =>Debug.Log("已取消!!!")); //取消协程任务


            int i = 0; //做个计时不然看不出效果
            Observable
                .EveryUpdate()
                .Sample(TimeSpan.FromSeconds(1f))
                .Subscribe(_ => Debug.Log(i++ + "DoTimer-----"))
                .AddTo(this);
        }

        // two coroutines
        IEnumerator AsyncA()
        {
            Debug.Log("a start");
            yield return new WaitForSeconds(3);
            Debug.Log("a end");
        }                                         

        IEnumerator AsyncB()
        {
            Debug.Log("b start");
            yield return new WaitForEndOfFrame();
            Debug.Log("b end");
        }
    }
}

#pragma warning restore 0219
#pragma warning restore 0168

Sample08_DetectDoubleClick 双击

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace UniRx.Examples
{
    public class Sample08_DetectDoubleClick : MonoBehaviour
    {
        void Start()
        {
            // Global event handling is very useful.
            // UniRx can handle there events.
            // Observable.EveryUpdate/EveryFixedUpdate/EveryEndOfFrame
            // Observable.EveryApplicationFocus/EveryApplicationPause
            // Observable.OnceApplicationQuit

            // This DoubleCLick Sample is from
            // The introduction to Reactive Programming you've been missing
            // https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

            var clickStream = Observable.EveryUpdate()
                .Where(_ => Input.GetMouseButtonDown(0));  //if(Input.GetMouseButtonDown(0))


            //打印"双击DoubleClick Detected! Count:" num++
            clickStream
                .Buffer(clickStream.Throttle(TimeSpan.FromMilliseconds(250)))//掐死(面包条一段一段掐团),if(timer>=250){ xs.Count++;timer=0;}
                .Where(xs => xs.Count >= 2)//predicate谓语. if (xs.Count >= 2)
                .Subscribe(xs => Debug.Log("双击DoubleClick Detected! Count:" + xs.Count));
        }
    }
}

Sample09_EventHandling

StartTest01

按下Q
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第70张图片

StartTest02

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第71张图片

StartTest03

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第72张图片

StartTest04

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第73张图片

StartTest05

StartTest01到05的脚本

#pragma warning disable 0067

using System;
using System.Reflection;
using UnityEngine;

namespace UniRx.Examples
{
    public class Sample09_EventHandling : MonoBehaviour
    {




        #region 字属


        /// Foo,function object Oriented,即面向对象函数,原命名为FooBar
        public event EventHandler<MyEventArgs> mMyEventHandler;
        public event Action<int> mIntAction;

        CompositeDisposable mCompositeDisposable = new CompositeDisposable();

        // Subject is Rx's native event expression and recommend way for use Rx as event.
        // Subject.OnNext as fire event,
        // expose IObserver is subscibable for external source, it's no need convert.
        Subject<int> mSubject = new Subject<int>(); //主题
        public IObservable<int> mObservable { get { return mSubject; } } //可被观察的
        #endregion



        #region 生命
        void Start()
        {
            //不用Start,采用Update按键的方式
            //StartTest01();
            //StartTest02();
            //StartTest03();
            //StartTest04();
            //StartTest05();
        }

        private void Update()
        {
            Common.DownKeyCode( KeyCode.Q, StartTest01 );
            Common.DownKeyCode( KeyCode.W, StartTest02 );
            Common.DownKeyCode( KeyCode.E, StartTest03 );
            Common.DownKeyCode( KeyCode.R, StartTest04 );
            Common.DownKeyCode( KeyCode.T, StartTest05 );
        }

        void OnDestroy()
        {
            // manage subscription lifecycle
            mCompositeDisposable.Dispose();
        }
        #endregion



        #region 辅助


        private void StartTest01()
        {
            //01 定义
            // convert to IO as (sender, eventArgs)
            Observable.FromEventPattern<EventHandler<MyEventArgs>, MyEventArgs>(
                    conversion:    handler => handler.Invoke,
                    addHandler:    handler => mMyEventHandler += handler,
                    removeHandler: handler => mMyEventHandler -= handler)//后面都用 h 简代 handler
                .Subscribe(onNext: handler => Debug.Log("StartTest01的OnNext CallBack:"+ handler.EventArgs.ToString()) )
                .AddTo(mCompositeDisposable); // IDisposable can add to collection easily by AddTo

            //02 接下来测试

            mMyEventHandler(this, new MyEventArgs { MyProperty = 666 });
        }

        private void StartTest02()
        {                                                                                       
            // convert to IO, many situation this is useful than FromEventPattern
            Observable.FromEvent<EventHandler<MyEventArgs>, MyEventArgs>(
                    conversion:    h => (sender, e) => h(e),
                    addHandler:    h => mMyEventHandler += h,
                    removeHandler: h => mMyEventHandler -= h)
                .Subscribe(onNext: handler => Debug.Log("StartTest02的OnNext CallBack:" + handler.MyProperty) )
                .AddTo(mCompositeDisposable);

            mMyEventHandler(this, new MyEventArgs { MyProperty = 666 });

        }

        private void StartTest03()
        {
            // You can convert Action like event.
            Observable.FromEvent<int>(
                    addHandler:    h => mIntAction += h,
                    removeHandler: h => mIntAction -= h)
                .Subscribe(onNext: handler => Debug.Log("StartTest03的OnNext CallBack:" + handler.ToString()))
                .AddTo(mCompositeDisposable);

            mIntAction(3); //一个委托(命令、请求都可以说,实质是方法的地址,这个例子没往里面塞具体的方法)
        }

        private void StartTest04()
        {
            // AOT Safe EventHandling, use dummy capture, see:https://github.com/neuecc/UniRx/wiki/AOT-Exception-Patterns-and-Hacks
            var capture = 0;
            Observable.FromEventPattern<EventHandler<MyEventArgs>, MyEventArgs>(
                    conversion:     h => 
                    {
                        capture.GetHashCode(); // dummy for AOT
                        return new EventHandler<MyEventArgs>(h);
                    },
                    addHandler:     h => mMyEventHandler += h,
                    removeHandler:  h => mMyEventHandler -= h)
                .Subscribe(onNext: handler => Debug.Log("StartTest04的OnNext CallBack:" + handler.EventArgs.ToString()))
                .AddTo(mCompositeDisposable);

            mMyEventHandler(this, new MyEventArgs { MyProperty = 666 });
        }

        private void StartTest05()
        {
            // Subject as like event.
            mObservable
                .Subscribe(onNext: handler => Debug.Log("StartTest05的OnNext CallBack:") )
                .AddTo(mCompositeDisposable);

            mSubject.OnNext(1); // fire event
        }
        #endregion

        #region 内部类
        public class MyEventArgs : EventArgs
        {
            public int MyProperty { get; set; }

            public override string ToString()
            {
                string str = "";
                str += "MyProperty\t" + MyProperty + "\n";

                return str;
            }
        }
        #endregion

    }
}

#pragma warning restore 0067

Sample10_MainThreadDispatcher

结果写在注释里面

             RunTest01(); //abcd
             RunTest02();//abcd
             RunTest03();//test
             RunTest04(); //0 1 2 3 4.....
             RunTest05();//()
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;

namespace UniRx.Examples
{
    public class Sample10_MainThreadDispatcherStart : MonoBehaviour
    {
        #region 属性

        #endregion

        #region 生命

        /// 首次载入
        void Awake()
        {
            Sample10_MainThreadDispatcher mainThreadDispatcher = new Sample10_MainThreadDispatcher();
            mainThreadDispatcher.Run();
        }
     
        #endregion 



    }
}
using System;
using System.Collections;
using UnityEngine;

namespace UniRx.Examples
{
    public class Sample10_MainThreadDispatcher
    {
        public void Run()
        {

             RunTest01(); //abcd
             RunTest02();//abcd
             RunTest03();//test
             RunTest04(); //0 1 2 3 4.....
             RunTest05();//()
        }

        private void RunTest05()
        {
            // Observable.Start use ThreadPool Scheduler as default.
            // ObserveOnMainThread return to mainthread
            Observable
                .Start(() => Unit.Default) // asynchronous work
                .ObserveOnMainThread()
                .Subscribe(x => Debug.Log(x));
        }

        private void RunTest04()
        {
            // Timebased operations is run on MainThread(as default)
            // All timebased operation(Interval, Timer, Delay, Buffer, etc...)is single thread, thread safe!
            Observable
                .Interval(TimeSpan.FromSeconds(1))
                .Subscribe(x => Debug.Log(x));
        }


        private void RunTest03()
        {
            // Add Action to MainThreadDispatcher. Action is saved queue, run on next update.
            MainThreadDispatcher
                .Post(_ => Debug.Log("test"), null);
        }


        /// 运行一次
        private void RunTest02()
        {
            // We have two way of run coroutine, FromCoroutine or StartCoroutine.
            // StartCoroutine is Unity primitive way and it's awaitable by yield return.
            // FromCoroutine is Rx, it's composable and cancellable by subscription's IDisposable.
            // FromCoroutine's overload can have return value, see:Sample05_ConvertFromCoroutine
            Observable
                .FromCoroutine(TestAsync)
                .Subscribe();
        }

        /// 运行一次
        private void RunTest01()
        {
            // MainThreadDispatcher is heart of Rx and Unity integration (结合)

            // StartCoroutine can start coroutine besides MonoBehaviour.
            MainThreadDispatcher
                .StartCoroutine(TestAsync());
        }

        IEnumerator TestAsync()
        {
            Debug.Log("a");
            yield return new WaitForSeconds(1);


            Debug.Log("b");
            yield return new WaitForSeconds(1);


            Debug.Log("c");
            yield return new WaitForSeconds(1);


            Debug.Log("d");
        }
    }
}

Sample11_Logger

需要启动脚本
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第74张图片

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;

namespace UniRx.Examples
{
    public class Sample11_LoggerStart : MonoBehaviour
    {

        #region 生命



        /// 首次载入且Go激活
        void Start()
        {
            Sample11_Logger logger = new Sample11_Logger();
            logger.ApplicationInitialize();
            logger.Run();   
        }

        #endregion 


    }
}




using System;
using System.Collections;
using UniRx.Diagnostics;
using UnityEngine;

namespace UniRx.Examples
{
    public class Sample11_Logger
    {
        // UniRx.Diagnostics.Logger
        // logger is threadsafe, define per class with name.
		static readonly UniRx.Diagnostics.Logger mLogger = new UniRx.Diagnostics.Logger("Sample11");

        // call once at applicationinit
        public void ApplicationInitialize()
        {
            // Log as Stream, UniRx.Diagnostics.ObservableLogger.Listener is IObservable
            // You can subscribe and output to any place.
            // 初始化
            ObservableLogger.Listener.LogToUnityDebug();
            


            // for example, filter only Exception and upload to web.
            // (make custom sink(IObserver) is better to use)
            // 没啥演示,没服务器来收集日志
            ObservableLogger.Listener
                .Where(x => x.LogType == LogType.Exception)
                .Subscribe(x =>
                {
                     //ObservableWWW.Post("", null).Subscribe();
                });
        }

        public void Run()
        {
            // Debug is write only DebugBuild.
            mLogger.Debug("Debug Message");

            // or other logging methods
            mLogger.Log("Message");
            mLogger.Exception(new Exception("test exception"));
        }
    }
}

Sample12_ReactiveProperty

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第75张图片

// for uGUI(from 4.6)
#if !(UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5)

using System;
using UnityEngine;
using UnityEngine.UI;

namespace UniRx.Examples
{
    public class Sample12_ReactiveProperty : MonoBehaviour
    {


        #region 字属
        [Header("场景节点")]
        public Button       MyButton;
        public Toggle       MyToggle;
        public InputField   MyInputField;
        public Text         MyText;
        public Slider       MySlider;

        // You can monitor/modifie in inspector by SpecializedReactiveProperty
        [Header("脚本变量")]
        public IntReactiveProperty IntRxProp = new IntReactiveProperty();
        Enemy enemy = new Enemy(1000);
        #endregion




        private void Awake()
        {
            Transform canvasTrans = transform.FindTop("Canvas");
            MyButton        = canvasTrans.GetComponentDeep<Button>("MyButton") ;
            MyToggle        = canvasTrans.GetComponentDeep<Toggle>("MyToggle");
            MyInputField    = canvasTrans.GetComponentDeep<InputField>("MyInputField");
            MyText          = canvasTrans.GetComponentDeep<Text>("MyText");
            MySlider        = canvasTrans.GetComponentDeep<Slider>("MySlider");
        }


        void Start()
        {

            InitButton();
            InitToggle();
            InitInputField();
            InitSlider();
            InitEnemy();
            InitInspector();
        }


        #region 辅助
        private void InitInspector()
        {
            // initial text:)  
            //滑动细节面板上的属性就会同步Text显示
            IntRxProp.SubscribeToText(MyText);
        }

        private void InitEnemy()
        {
          
            // from RxProp, CurrentHp changing(Button Click) is observable
            enemy.CurrentHp.SubscribeToText(MyText);
            enemy.IsDead.Where(isDead => isDead == true)
                .Subscribe(_ =>
                {
                    MyToggle.interactable = MyButton.interactable = false;
                });


        }

        private void InitInputField()
        {
            // input shows delay after 1 second
            //延时一秒,将输入框文字赋值文本组件
#if !(UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
            MyInputField.OnValueChangedAsObservable()
#else
                MyInputField.OnValueChangeAsObservable()
#endif
                .Where(x => x != null)
                .Delay(TimeSpan.FromSeconds(1))
                .SubscribeToText(MyText); // SubscribeToText is UniRx.UI Extension Method   
        }

        private void InitSlider()
        {
            // converting for human visibility
            //
            MySlider.OnValueChangedAsObservable()
                .SubscribeToText(MyText, x => Math.Round(x, 2).ToString());
        }

        private void InitToggle()
        {
            // Toggle, Input etc as Observable(OnValueChangedAsObservable is helper for provide isOn value on subscribe)
            // SubscribeToInteractable is UniRx.UI Extension Method, same as .interactable = x)
            //Toggle控制Button的Interactable
            MyToggle.OnValueChangedAsObservable().SubscribeToInteractable(MyButton);
        }

        private void InitButton()
        {
            // UnityEvent as Observable
            // (shortcut, MyButton.OnClickAsObservable())
            // 点按钮扣99
            MyButton.onClick.AsObservable().Subscribe(_ => enemy.CurrentHp.Value -= 99);
        }
        #endregion

    }


    #region 内部类
    // Reactive Notification Model
    public class Enemy
    {
        public IReactiveProperty<long> CurrentHp { get; private set; }

        public IReadOnlyReactiveProperty<bool> IsDead { get; private set; }

        public Enemy(int initialHp)
        {
            // Declarative Property
            CurrentHp = new ReactiveProperty<long>(initialHp);
            IsDead = CurrentHp.Select(x => x <= 0).ToReactiveProperty();
        }
    }
    #endregion

}

#endif

Sample13_ToDoApp

bug

节点丢失
ToDoList这个节点大小盖住了下面的按钮(此时没有Mask),意味着加了一个Item后,下面的按钮就失效了

主体

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第76张图片

// for uGUI(from 4.6)
#if !(UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5)

using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.EventSystems;

namespace UniRx.Examples
{
    public class Sample13_ToDoApp : MonoBehaviour
    {

        [Header("场景节点")]
        public Text Title;
        public Button AddBtn;
        public Button ClearBtn;
        public InputField ToDoInput;
        public GameObject SampleItemPrefab;
        public GameObject TodoLst;

        [Header("脚本变量")]
        ReactiveCollection<GameObject> toDos = new ReactiveCollection<GameObject>();


        private void Awake()
        {
            Transform canvasTrans = transform.FindTop("Canvas");
            Title = canvasTrans.GetComponentDeep<Text>("Title");
            AddBtn = canvasTrans.GetComponentDeep<Button>("AddBtn");
            ClearBtn = canvasTrans.GetComponentDeep<Button>("ClearBtn");
            ToDoInput = canvasTrans.GetComponentDeep<InputField>("ToDoInput");
            TodoLst = canvasTrans.FindChildDeep("TodoLst").gameObject;
            toDos = new ReactiveCollection<GameObject>();
        }
        void Start()
        {
            //两个按钮
            { 
                // merge Button click and push enter key on input field.
                //增加按钮或输入框回车,同功能
                var submit = Observable.Merge(
                    AddBtn.OnClickAsObservable().Select( _ => ToDoInput.text),
                    ToDoInput.OnEndEditAsObservable().Where( _ => Input.GetKeyDown(KeyCode.Return)));

                // 增加
                submit
                    .Where(x => x != "")
                    .Subscribe(x =>{
                        ToDoInput.text = ""; // clear input field
                        var item = Instantiate(SampleItemPrefab) as GameObject;
                        (item.GetComponentInChildren(typeof(Text)) as Text).text = x;
                        toDos.Add(item);});

                // 清空已经办好的(勾选了的)
                ClearBtn
                    .OnClickAsObservable()
                    .Subscribe(_ => {
                        var removeTargets = toDos.Where(x => x.GetComponent<Toggle>().isOn).ToArray();
                        foreach (var item in removeTargets)
                        {
                            toDos.Remove(item);
                        }});            
            }


            //对Item的增删改
            { 
                //变化是改变抬头上的文本(数量变化)
                toDos
                    .ObserveCountChanged()
                    .Subscribe(x => Title.text = "TODO App, ItemCount:" + x);

                //增加的将该变量设置父节点
                toDos
                    .ObserveAdd()
                    .Subscribe(x =>{x.Value.transform.SetParent(TodoLst.transform, false);});

                //清空时销毁
                toDos
                    .ObserveRemove()
                    .Subscribe(x =>{GameObject.Destroy(x.Value);});            
            }
        }
    }
}

#endif

UIKitExample/EventExample

一个注册事件(发东西的,被观察的)
一个观察者(收东西的,被调用的,可以被调用方法,这里的例子是被调用了一个 参数"Hello World!")
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第77张图片

协程

里面的类没了,报错

收,相当于订阅Up主的粉丝

using UnityEngine;

namespace QFramework
{


	public class EventGet : MonoBehaviour 
	{
		void Start () 
		{
			QEventSystem.RegisterEvent(TestEvent.TestOne,GetEvent);
		}

		void GetEvent(int key, params object[] obj)
		{
			switch (key)
			{
				case (int)TestEvent.TestOne:
					this.LogInfo(obj[0].ToString());
					break;
			}
		}
	}
}

发,相当于Up主

using UnityEngine;
using UniRx;

namespace QFramework
{
    public class EventTest : MonoBehaviour
    {       
        void Start()
        {
            Observable
                .EveryUpdate()
                .Subscribe( _ => 
                    QEventSystem.SendEvent(TestEvent.TestOne,"Hello World!"));
        }
    }
}

枚举

using UnityEngine;

namespace QFramework
{
    public enum TestEvent
    {
        TestOne
    }
}

UIKitExample/ManagerOfManagersExample

给的ID跑的逻辑是没有的,需要取消注释 ForwardMsg(tmpMsg); 我放到了任务列表
在这里插入图片描述

可以得到结果
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第78张图片

namespace QFramework
{
	using UnityEngine;

	[QMonoSingletonPath("[Event]/QMsgCenter")]
	public partial class QMsgCenter : MonoBehaviour, ISingleton
	{
		......
		public void SendMsg(QMsg tmpMsg)
		{
			......
   			 //	TODO case (int)PlayerEvent.Run: 
			 ForwardMsg(tmpMsg);
		}

Player ,相当于粉丝

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace QFramework.Example
{
	public class Player : QMonoBehaviour
	{
		
		private IManager mManager;

		// Use this for initialization
		void Start()
		{
			RegisterEvent(PlayerEvent.Run);
		}

		// Update is called once per frame

		protected override void ProcessMsg(int eventId, QMsg msg)
		{
			switch (eventId)
			{
				case (int)PlayerEvent.Run: //查TODO ,去取消注释才有结果		
					Log.I("收到跑的消息了");
					break;
			}
		}

		public override IManager Manager
		{
			get { return GameManager.Instance ; }
		}



		#region 内部类
		public class GameManager : QMgrBehaviour, ISingleton
        {
            public override int ManagerId
            {
                get { return QMgrID.Game; }
            }


            public static GameManager Instance
            {
                get { return MonoSingletonProperty<GameManager>.Instance; }
            }

            public void OnSingletonInit()
            {

            }
        }

		#endregion

    }


}

ManagerOfManagersExample

using System.Collections;
using System.Collections.Generic;
using QFramework;
using UnityEngine;

namespace QFramework.Example
{
	
	public class ManagerOfManagersExample : QMonoBehaviour
	{
		public override IManager Manager
		{
			get { return UIManager.Instance; }
		}


		private void Update()
		{
			if (Input.GetMouseButtonDown(0))
			{

				Debug.Log("单击");	
				SendEvent(PlayerEvent.Run);
			}
		}
	}
}

ForwardMsg的出处

using System.Collections;
using System.Collections.Generic;
using QFramework.Example;
using UnityEngine;


namespace QFramework
{
	/// 管所有Mgr
	public partial class QMsgCenter 
	{

		public static void ForwardMsg(QMsg msg)
		{
			switch (msg.ManagerID)
			{
				case QMgrID.Game:
					Player.GameManager.Instance.SendMsg(msg);//根据msg.ManagerID,给mgr发消息
                    break;
			}
		}

	}
}

枚举

namespace QFramework.Example
{

    public enum PlayerEvent
    {
        Start = QMgrID.Game,
        Run,
        End
    }
}

UIKitExample/UIExample

watch 看总体运行

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第79张图片

bug VS删除断点后,错误列表还保存着

modify 从打AB包创建文件夹的拓展方法,转移所在脚本的所有内容到自己的库

其中用到Log的dll,复制即可

ResKitExample/Audio

AB名直接复制原文件名,系统自动变小写的
看到名字格式,以为有强制命名格式,实际只是为了人好,具体看Assets/QFrameworkData/QAssets.cs
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第80张图片
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第81张图片

using UnityEngine;
using QFramework;


public class AudioTest : MonoBehaviour 
{
    string mMusicName = "resources://JYJ - BACK SEAT";
    //string mMusicName = "BackGroundMusic";
    string mSoundName = "TestSound";


    private void Start()
    {
        QFramework.ResMgr.Init();

        // 
       // AudioManager.Instance.SendMsg(new AudioSoundMsg(mSoundName));

        AudioManager.Instance.SendMsg(new AudioMusicMsg(mMusicName));

        AudioManager.Instance.SendMsg(new AudioStopMusicMsg());

       // AudioManager.PlaySound(mSoundName);
        
        AudioManager.PlayMusic(mMusicName);
    }
}

做这个的原因是,RealFrame做过类似的,想比较整合起来

ResKitExample/Pool

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第82张图片
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第83张图片

using UnityEngine;

namespace QFramework
{
    public class CallPool : MonoBehaviour
    {

        
        private void Start()
        {
            #region SimpleObjectPool


            "====SimpleObjectPool".LogInfo();
            var pool = new SimpleObjectPool<Fish>(() => new Fish(),initCount:50);
            pool.CurCount.LogInfo();
           //
            var fish = pool.Allocate();
            pool.CurCount.LogInfo();
            //
            pool.Recycle(fish);
            pool.CurCount.LogInfo();
            #endregion



            #region SafeObjectPool


            "====SafeObjectPool".LogInfo();
            SafeObjectPool<Bullet>.Instance.Init(50,25);
            var bullet = Bullet.Allocate();
            SafeObjectPool<Bullet>.Instance.CurCount.LogInfo();
            //
            bullet.Recycle2Cache();
            SafeObjectPool<Bullet>.Instance.CurCount.LogInfo();
            #endregion
        }



        #region 内部类


        class Fish
        {

        }


        class Bullet :IPoolable,IPoolType
        {

            public  bool IsRecycled { get; set; }


            public static Bullet Allocate()
            {
                return SafeObjectPool<Bullet>.Instance.Allocate();
            }
            public void OnRecycled()
            {
                "回收了".LogInfo();
            }



            
            public void Recycle2Cache()
            {
                SafeObjectPool<Bullet>.Instance.Recycle(this);
            }
        }
        #endregion  


    }
}

ResKitExample/RefCounter

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第84张图片

using UnityEngine;

namespace QFramework.Course
{
    public class RefCounterExample : MonoBehaviour
    {
        void Start()
        {
            var room = new Room();

            room.EnterPeople();
            room.EnterPeople();
            room.EnterPeople();
            //
            room.LeavePeople();
            room.LeavePeople();
            room.LeavePeople();
        }
    }



    #region 内部类
    public class Light
    {
        public void SwitchOn()
        {
            Log.E("开灯");
        }

        public void SwitchOff()
        {
            Log.E("关灯");
        }
    }

    public class Room : SimpleRC
    {
        private Light mLight = new Light();

        public void EnterPeople()
        {
            Log.E("进入人了");

            if (RefCount == 0)
            {
                mLight.SwitchOn();
            }

            Retain();
        }

        public void LeavePeople()
        {
            Release();

            Log.E("人出来了");
        }

    
        protected override void OnZeroRef()
        {
            mLight.SwitchOff();
        }
    }
    #endregion
}

ResKitExample/ResKit/LoadAssetBundleResExample

using UnityEngine;
using UnityEngine.UI;

namespace QFramework.Example
{
	public class AssetBundleResExample : MonoBehaviour
	{
		private ResLoader mResLoader = ResLoader.Allocate();

		public RawImage RawImage;

		private void Awake()
		{
			ResMgr.Init();
		}

		// Use this for initialization
		void Start()
		{
			Transform canvasTrans = transform.FindTop("Canvas");
			RawImage rawImage = canvasTrans.Find("RawImage").GetComponent<RawImage>();
			RawImage.texture = mResLoader.LoadSync<Texture2D>("TestImage");
			
			// 通过下边方式也一样
			RawImage.texture = mResLoader.LoadSync<Texture2D>("testimage_png","TestImage");
		}

		private void OnDestroy()
		{
			mResLoader.Recycle2Cache(); //回收到缓存
            mResLoader = null;
		}
	}
}

ResKitExample/ResKit/LoadAssetBundleResExample

bug 走这里的打包不行

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第85张图片
所以一开始做的是:图片放Resources,路径加 Resources/ 能拿到( 最后走的是Resorces.Load(string path))
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第86张图片

但是初始文件夹是没有Resources的,所以继续找

watch ResKit中打包

01 在ResMgr.Init()的方法中找到了一个文件名(图一,直接截打包好的图),然后顺藤摸瓜发现,通过这个方式打包(图二)
02 之前卡的是,mResLoader.LoadSync中找到 ResDatas.GetAssetData,里面的两个静态列表都是空的,也就是没有从asset_bindle_config中加载到东西,因为走上一中打包就不会生成asset_bindle_config
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第87张图片
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第88张图片

using UnityEngine;
using UnityEngine.UI;

namespace QFramework.Example
{
	public class AssetBundleResExample : MonoBehaviour
	{
		private ResLoader mResLoader = ResLoader.Allocate();
		public RawImage RawImage;

		private void Awake()
		{
			ResMgr.Init();
		}

		// Use this for initialization
		void Start()
		{
			Transform canvasTrans = transform.FindTop("Canvas");
            RawImage = canvasTrans.Find("RawImage").GetComponent<RawImage>();
            //底层能够走的方法 ResDatas.GetAssetData
            //RawImage.texture = mResLoader.LoadSync("TestImage");

            // 通过下边方式也一样
            RawImage.texture = mResLoader.LoadSync<Texture2D>("testimage_png","TestImage");
		}



        private void OnDestroy()
		{
			mResLoader.Recycle2Cache(); //回收到缓存
            mResLoader = null;
		}
	}
}

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第89张图片

ResKitExample/ResKit/LoadResourcesResExample

跟上面一样的逻辑,加了"resources://"或"Resources/"走别的逻辑分支

using UnityEngine;
using UnityEngine.UI;

namespace QFramework.Example
{
	public class LoadResourcesResExample : MonoBehaviour
	{
		public RawImage RawImage;
		
		private ResLoader mResLoader = ResLoader.Allocate();
		
		// Use this for initialization
		private void Start()
		{
			RawImage.texture = mResLoader.LoadSync<Texture2D>("resources://TestTexture");
		}

		private void OnDestroy()
		{
			Log.I("On Destroy ");
			mResLoader.Recycle2Cache();
			mResLoader = null;
		}
	}
}

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第90张图片

ResKitExample/ResKit

bug 空

实际内容是将上面两个例子汇总了一下。
但是第三条的Asset报null,(“assetobj_prefab”, “AssetObj”)。

            GameObject prefab = mResLoader.LoadSync<GameObject>("assetobj_prefab", "AssetObj");
            prefab.Instantiate()
				.Name("这是使用通过 AssetName  和 AssetBundle 加载的对象");

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第91张图片

watch 对比

回溯看不出哪里错了,所以试试加载其它预制体,可以的,一个UI物体
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第92张图片

            //回溯看不出哪里错了,所以试试加载其它预制体
            GameObject prefab = mResLoader.LoadSync<GameObject>("uitestunirx_prefab", "UITestUniRx");
            prefab.Instantiate()
				.Name("这是使用通过 AssetName  和 AssetBundle 加载的对象");

watch 然后对比发现少了标签

但测试完不是这原因
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第93张图片

watch 注释掉前面的代码就可以

就是有两种 LoadSync方式,直接资源名、包名+文件名。同一种资源,只能采用一种 LoadSync。先用谁,另一个就报空。
下面的写法就会报空第二块代码 mResLoader.LoadSync(“AssetObj”)


			GameObject prefab = mResLoader.LoadSync<GameObject>("assetobj_prefab", "AssetObj");
            //回溯看不出哪里错了,所以试试加载其它预制体	,最终发现是QFramework标签
           // GameObject prefab = mResLoader.LoadSync("uitestunirx_prefab", "UITestUniRx");
            prefab.Instantiate()
				.Name("这是使用通过 AssetName  和 AssetBundle 加载的对象");

            mResLoader.LoadSync<GameObject>("AssetObj")
				.Instantiate()
				.Name("这是使用通过 AssetName 加载的对象");

modify 总的

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第94张图片


using System.IO;
using UnityEngine;

namespace QFramework.Example
{
	public class ResKitExample : MonoBehaviour
	{
		private ResLoader mResLoader = ResLoader.Allocate();


        private void Awake()
        {
			ResMgr.Init();		
        }
        private void Start()
		{
			

			mResLoader.LoadSync<GameObject>("resources://GameObject")
				.Instantiate()
				.Name("这是使用 ResKit 加载的对象");

            if (true)//二选一,选A,B就报空的那种
            {
                mResLoader.LoadSync<GameObject>("assetobj_prefab", "AssetObj")
                    //回溯看不出哪里错了,所以试试加载其它预制体	,最终发现是QFramework标签
                    // mResLoader.LoadSync("uitestunirx_prefab", "UITestUniRx");
                    .Instantiate()
                    .Name("这是使用通过 AssetName  和 AssetBundle 加载的对象");
            }
            else
            {
                mResLoader.LoadSync<GameObject>("AssetObj")
                    .Instantiate()
                    .Name("这是使用通过 AssetName 加载的对象");
            }



        }

		

		private void OnDestroy()
		{
			mResLoader.Recycle2Cache();
			mResLoader = null;
		}
	}
}

ResKitExample/SpriteAtlas

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第95张图片

using System.Collections;
using UnityEngine;
using UnityEngine.U2D;
using UnityEngine.UI;

namespace QFramework
{
	/// 
	/// 
	/// 参考:http://www.cnblogs.com/TheChenLin/p/9763710.html
	/// 
	public class TestSpriteAtlas : MonoBehaviour
	{
		[SerializeField] private Image mImage;

		// Use this for initialization
		private IEnumerator Start()
		{
			Transform canvasTrans = transform.FindTop("Canvas");
            mImage=canvasTrans.GetComponentInChildren<Image>();
            var loader = ResLoader.Allocate();
			ResMgr.Init();

#if UNITY_2017_1_OR_NEWER
			var spriteAtlas = loader.LoadSync<SpriteAtlas>("spriteatlas");
			var square = spriteAtlas.GetSprite("Square");
			Log.I(spriteAtlas.spriteCount);

			mImage.sprite = square;
#endif

			yield return new WaitForSeconds(5.0f);

			loader.Recycle2Cache();
			loader = null;
		}
	}
}

UIKitExample/UIExample

A=>B,表示A可以打开B。脚本多,看工程
1=>2
2=>3
2=>4
3=>5
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第96张图片

star 一种花括号的写法

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第97张图片

watch UniRx系列教程的脚本

王小梯 / UniRx精讲
UniRx系列教程
长,考虑要不要贴
适合复用的就静态类

UniRxExtensions

/****************************************************
    文件:UniRxExtensions.cs
	作者:lenovo
    邮箱: 
    日期:2023/6/6 17:55:35
	功能:
    来源:https://www.bilibili.com/video/BV1EB4y1z7nY/?spm_id_from=333.337.search-card.all.click&vd_source=54db9dcba32c4988ccd3eddc7070f140
*****************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using UniRx;
using UnityEngine;
using Random = UnityEngine.Random;
//需要这两个
using UniRx;
using UniRx.Async;
using UniRx.Triggers;


/*
 *  AddTo,同生共死
 *  Subject,一个参数,多个用元组
 *  Where==if,过滤
 *  First,第一个才有效
 *  括号里面的方法可以写 _=> ()=> 形参(比如unit,list)=>
 *  buffer,事件缓存,事件存一块可以一起输出
 *  01 go.UpdateAsObservable() ;02 Observable.EveryUpdate().AddTo(this) 。01的好处是自动AddTo(go)上
 *  x协程返回IEnumerator,无法适应TryCatch
 *  ReactiveProperty,常用于UI的MVC
 */

public static partial class UniRxExtensions
{

    #region 生命


    /// 首次载入且Go激活
    public static void ExampleMonoBehaviour(this MonoBehaviour mono)
    {
        if (false)
        { 
            DoAfterTime(mono);
            DoUpdate(mono);
            DoTimer(mono);        
        }

    }

    public static void ExampleGameObject(this GameObject go, MonoBehaviour mono)
    {
        if (false)
        { 
            go.DoWhenHide();
            go.DoWhenDestroy();
            go.DoWhenMouseDown();
            go.DoDelayMouseDown(2f);
            go.DoDelayFrameMouseDown(2);
            go.DoDelayMouseDownByUpdate(2f);
            go.DoWhenCollide();
            go.DoUpdate();
            go.DoTimer(1f);
            IDisposable disposable = go.DoUpdateDispose();//ifxxx,操作disposable
        }

       

    }

    public static void BindInt(this ReactiveProperty<int> num,MonoBehaviour mono) 
    {
        num   
            .Skip(1)//跳过第一次的赋值初始化阶段
            .Subscribe(_ =>Debug.Log("ValueChange"))
            .AddTo(mono);
    }


    #endregion


    #region 辅助
    public static void DoWhenHide(this GameObject go)
    {
        go
          .OnDisableAsObservable()
          .Subscribe(_ => Debug.Log("DoWhenHide"))
          .AddTo(go);
    }

    public static void DoWhenDestroy(this GameObject go)
    {
        go
          .OnDestroyAsObservable()
          .Subscribe(_ => Debug.Log("DoWhenHide"))
          .AddTo(go);
    }

    public static void DoWhenMouseDown(this GameObject go)
    {
        go
          .OnMouseDownAsObservable()
          .Subscribe(_ => Debug.Log("DoWhenMouseDown"))
          .AddTo(go);
    }

    public static void DoDelayMouseDown(this GameObject go, float delay)
    {
        go
          .OnMouseDownAsObservable()
          .Delay(TimeSpan.FromSeconds(delay))
          .Subscribe(_ => Debug.Log("DoDelayMouseDown"))
          .AddTo(go);
    }
    public static void DoDelayFrameMouseDown(this GameObject go, int cnt)
    {
        go
          .OnMouseDownAsObservable()
          .DelayFrame( cnt )
          .Subscribe(_ => Debug.Log("DoDelayMouseDown"))
          .AddTo(go);
    }

    /// 一般用于if(xxx){disposable.Dispose();}
    public static IDisposable DoUpdateDispose(this GameObject go)
    {
        IDisposable disposable = go
           .UpdateAsObservable()
           .Subscribe(_ =>Debug.Log("DoUpdateDispose"))
           .AddTo(go);

        return disposable;
    }

    /// 一般用于if(xxx){disposable.Dispose();}
    public static IDisposable DoUpdateDispose(this GameObject go,CompositeDisposable compositeDisposable)
    {
        IDisposable disposable = go
           .UpdateAsObservable()
           .Subscribe(_ => Debug.Log("DoUpdateDispose"))
           .AddTo(compositeDisposable);

        return disposable;
    }

    public static void DoDelayMouseDownByUpdate(this GameObject go, float delay)
    {
        go
          .UpdateAsObservable()
          .Where( _=>
          {
              if (Input.GetMouseButtonDown(0))
              {
                  Debug.Log("DoDelayMouseDownByUpdate点击鼠标左键");
                  return true;
              }
              return false;
          })
          .Delay(TimeSpan.FromSeconds(delay))
          .Subscribe(_ => Debug.Log("DoDelayMouseDownByUpdate"))
          .AddTo(go);
    }

    public static void DoWhenCollide(this GameObject go)
    {
        go
          .OnCollisionEnterAsObservable()
          .Subscribe(_ => Debug.Log("DoWhenCollide"))
          .AddTo(go);
    }


    /// 每隔2秒
    public static void DoTimer(this MonoBehaviour mono)
    {
        Observable
            .EveryUpdate()
            .Sample(TimeSpan.FromSeconds(2f))
            .Subscribe(_ => Debug.Log("DoTimer"))
            .AddTo(mono);
    }



    public static void DoUpdate(this MonoBehaviour mono)
    {
        Observable
            .EveryUpdate()
            .Subscribe(_ => Debug.Log("DoUpdate"))
            .AddTo(mono);
    }

    public static void DoUpdate(this GameObject go)
    {
        go
            .UpdateAsObservable()
            .Subscribe(_ => Debug.Log("DoUpdate"))
            .AddTo(go);
    }

    public static void DoTimer(this GameObject go,float time)
    {
        go
            .UpdateAsObservable()
            .Sample(TimeSpan.FromSeconds(time))
            .Subscribe(_ => Debug.Log("DoTimer"))
            .AddTo(go);
    }

    public static void DoAfterTime(this MonoBehaviour mono)
    {
        Observable
            .Timer(TimeSpan.FromSeconds(2f))
            .Subscribe(_ => Debug.Log("DoAfterTime"))
            .AddTo(mono);
    }
    #endregion

    #region 系统

    #endregion

    #region 辅助

    #endregion

}




UniRxExtensions.FirstLastTake

/****************************************************
    文件:UniRxExtensions.FirstLastTake.cs
	作者:lenovo
    邮箱: 
    日期:2023/6/7 17:48:10
	功能:
*****************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using UniRx;
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.Events;
using Random = UnityEngine.Random;


public static partial class UniRxExtensions
{
    public static void ExampleStart_Keyword(GameObject go)
    {
        //go.DoFirst();
        //go.DoLast();
        //go.DoTake(3);
        //go.DoBuffer(60 * 25);
        //go.DoMerge();
        //go.DoReturn();
        go.Do();
    }

    public static void DoFirst(this GameObject go)
    {
        go
            .UpdateAsObservable()
            .Where(_ => Input.GetMouseButtonDown(0))
            .First(unit => true)
            .Subscribe(_ => Debug.Log("DoFirst"))
            .AddTo(go);
    }

    public static void DoLast(this GameObject go)
    {
        go
            .UpdateAsObservable()
            .Where(unit => Input.GetMouseButtonDown(0))
            .Last(unit => true)
            .Subscribe(_ => Debug.Log("DoLast"))
            .AddTo(go);
    }

    public static void DoTake(this GameObject go, int cnt)
    {
        go
            .UpdateAsObservable()
            .Where(unit => Input.GetMouseButtonDown(0))
            .Take(cnt)
            .Subscribe(_ => Debug.Log("DoTake"))
            .AddTo(go);
    }


    /// 每cnt帧的时间输出一次
    public static void DoBuffer(this GameObject go, int cnt)
    {
        go
            .UpdateAsObservable()
            .Buffer(cnt)
            .Subscribe(_ => Debug.Log("DoBuffer"))
            .AddTo(go);

    }

    public static void DoMerge(this GameObject go)
    {
        IObservable<Unit> disposable0 = go.UpdateAsObservable()
            .Where(_ => Input.GetMouseButtonDown(0));

        IObservable<Unit> disposable1 = go.UpdateAsObservable()
            .Where(_ => Input.GetMouseButtonDown(1));

        disposable0.Merge(disposable1)
            .Subscribe(_ => Debug.Log("Mereg单击"))
            .AddTo(go);

        //相当于
        //IObservable disposable3 = go.UpdateAsObservable()
        //  .Where(_ => Input.GetMouseButtonDown(0)  || Input.GetMouseButtonDown(1));

    }
    public static void DoReturn(this GameObject obj)
    {

        Debug.Log("DoReturn的前面");
        Observable
            .Return("DoReturn")
            .Subscribe(Debug.Log)
            .AddTo(obj);


    }

    /// 提前筛选 
    public static void Do(this GameObject go)
    {
        go.UpdateAsObservable()
            .Do(_ => Debug.Log("Do"))
            .Subscribe(_ => Debug.Log("Do的Subscribe"))//不订阅就不会带引Do
            .AddTo(go);

    }


    /// 与Where、Delay等结合使用
    public static void DoWithDo(this GameObject go)
    {
        go.UpdateAsObservable()
            .Where(_ => Input.GetMouseButtonDown(0))
            .Do(_ => Debug.Log("DoWhereDo按下了鼠标"))
            .Delay(TimeSpan.FromSeconds(2f))
            .Do(_ => Debug.Log("DoWhereDo延时2秒"))
            .Subscribe(_ => Debug.Log("DoWhereDo的Subscribe"))//不订阅就不会带引Do
            .AddTo(go);

    }


    public static void DoStartWith(this GameObject go)
    {
        Observable
            .Return("baidu.com")
            .StartWith("https://")
            .Subscribe(_ => Debug.Log("DoStartWith的Subscribe"))
            .AddTo(go);
    }

}




UniRxExtensionsMonoBehaviour.Start

/****************************************************
    文件:UniRxExtensionsMonoBehaviour.Start.cs
	作者:lenovo
    邮箱: 
    日期:2023/6/8 22:40:42
	功能:生命函数放这里
*****************************************************/

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
 

    public partial class UniRxExtensionsMonoBehaviour : MonoBehaviour
    {


        #region 生命


        /// 首次载入且Go激活
        void Start()
        {
            
            //UniRxExtensions.ExampleMonoBehaviour(this);
            //UniRxExtensions.ExampleGameObject(gameObject,this);
            //UniRxExtensions.ExampleStart_Keyword(gameObject);
            //Example_Scene();
            //Example_ToObservable();
            ExampleStart_Message();

        }


        #endregion 



    }




UniRxExtensionsMonoBehaviour.Message_ReactiveProperty

/****************************************************
    文件:UniRxExtensionsMonoBehaviour.Message_ReactiveProperty.cs
	作者:lenovo
    邮箱: 
    日期:2023/6/7 17:48:10
	功能:消息机制
*****************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using UniRx;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using Random = UnityEngine.Random;


public  partial class UniRxExtensionsMonoBehaviour : MonoBehaviour
{

    int msgId = 0;
    ReactiveProperty<int> mReactiveProperty_Int = new ReactiveProperty<int>();
    ReactiveProperty<string> mReactiveProperty_String = new ReactiveProperty<string>();
    static int CurTextID = 3;
    
    
    public void ExampleStart_Message()
    {
        if (CurTextID == 1)
        { 
            MainThreadingMsg_Receive();//注册
            MainThreadingMsg_Publish();//调用
            MainThreadingMsg_Publish();
            MainThreadingMsg_Publish();        
        }

        //
        if (CurTextID == 2)
        {
            ReactivePropertyChangeValue_Int();
            mReactiveProperty_Int.Value++;//调用
            mReactiveProperty_Int.Value++;
            mReactiveProperty_Int.Value++;
        }
        //
        if (CurTextID == 3)
        {
            //ReactivePropertyChangeValue_Int();//如果前面没注册
            ReactivePropertyChangeValue_String();
            mReactiveProperty_String.Value = Guid.NewGuid().ToString();
            mReactiveProperty_Int.Value++;
            mReactiveProperty_String.Value = Guid.NewGuid().ToString();
        }
    }




    #region 辅助

    void ReactivePropertyChangeValue_Int()
    {

        mReactiveProperty_Int
            .Skip(1)//跳过初始化
            .Subscribe(_=>Debug.Log("ReactivePropertyChangeValue_Int的Subscribe"))
            .AddTo(this);
    }


    void ReactivePropertyChangeValue_String()
    {

        mReactiveProperty_String
            .Skip(1)//跳过初始化
            .Subscribe(_ => Debug.Log("ReactivePropertyChangeValue_String的Subscribe"))
            .AddTo(this);
    }

    void ReactiveProperty_Merge()
    {
        mReactiveProperty_Int
           .Select(_ => Unit.Default)
           .Merge(mReactiveProperty_String.Select(_ => Unit.Default))
           .Subscribe(_=>Debug.Log("ReactiveProperty_Merge的Subscribe"))
           .AddTo(this);
    }

        /// 多线程的消息,主线程下一帧Update收
        void MultiThreadingMsg_Receive()
    {
        MessageBroker.Default.Receive<MsgTmp>()
            .SubscribeOnMainThread()
            .Subscribe(msgTmp =>
                Debug.Log("MainThreadingMsg_Receive的Subscribe" + msgTmp.ToString()))
            .AddTo(this);

    }


    /// 单线程的消息,即发即收
    void MainThreadingMsg_Publish()
    {
        MessageBroker.Default.Publish(new MsgTmp()
        {
            Idx = msgId,
            Val = "绝区零"+ msgId.ToString(),
           
        }) ;
        msgId++;
    }


     void MainThreadingMsg_Receive()
    {
        MessageBroker.Default.Receive<MsgTmp>()
           .Subscribe(msgTmp => 
            Debug.Log("MainThreadingMsg_Receive的Subscribe"+msgTmp.ToString()))
           .AddTo(this);
   
    }
    #endregion


    #region 内部类

    #endregion
    class MsgTmp
    { 
        public int Idx { get; set; }
        public string Val { get; set; }


        public override string ToString()
        {
            string str = "MsgTmp";
            str += "\tIdx=" + Idx;
            str += "\tVal=" + Val;

            return str;
        }
    }
}





UniRxExtensionsMonoBehaviour.Scene

/****************************************************
    文件:UniRxExtensionsMonoBehaviour.Scene.cs
	作者:lenovo
    邮箱: 
    日期:2023/6/6 18:6:33
	功能:
*****************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using UniRx;
using UnityEngine;
using Random = UnityEngine.Random;
 

public partial  class UniRxExtensionsMonoBehaviour : MonoBehaviour
{
    //意思是一部分放Start,一部分放Update,单用Dic好像搞错了,而且也不每关
    Dictionary<Action,Action> startUpdateDic=new Dictionary<Action,Action>(); 
    ReactiveProperty<int> numRp=new ReactiveProperty<int>(0);
    //
    IDisposable disposable;
    CompositeDisposable compositeDisposable;


    /// 有场景交互部分
    private void Example_Scene()
    {


        gameObject.FindTop("Go").ExampleGameObject(this );
        numRp.BindInt(this);
        //
        GameObject Cube1 = gameObject.FindTop("Cube1");
        Cube1.DoWhenCollide();
        Cube1.DoWhenMouseDown();
        //
        disposable = gameObject.DoUpdateDispose();
        //
        disposable = gameObject.DoUpdateDispose(compositeDisposable);
        //
        disposable = gameObject.DoUpdateDispose(compositeDisposable);
        compositeDisposable.AddTo(gameObject);



    }

    private void Example_SceneUpdate()
    {
        if (Input.GetMouseButtonDown(0))
        {
            numRp.Value++;
            //
            disposable.Dispose();
            compositeDisposable.Dispose();
        }
    }


}





UniRxExtensions.ToObservable

/****************************************************
    文件:UniRxExtensions.ToObservable.cs
	作者:lenovo
    邮箱: 
    日期:2023/6/7 17:48:10
	功能:各种协程转Observable
*****************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using UniRx;
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.Events;
using Random = UnityEngine.Random;


public partial  class UniRxExtensionsMonoBehaviour:MonoBehaviour
{
    void Example_ToObservable()
    {
        //IEnumeratorBody2Observable(enumerator());
        IEnumeratorBody2Observable_TryCatch(enumerator_TryCatch());

        //
        //IEnumerator2ObservableBody();
        //IEnumerator2ObservableBody_TryCatch();

    }



    #region 辅助

    /// 转,但方法块在IEnumeratorBody
    void IEnumeratorBody2Observable( IEnumerator from)
    {
        from.ToObservable()
            .DoOnCompleted(()=>  Debug.Log("ConvertToObservable")) //这里_(报错)与()(不报错)是不同的
            .Subscribe( _ =>  Debug.Log("ConvertToObservable的Subscribe"))
            .AddTo(this);
    }

    /// 转,但方法块在IEnumeratorBody
    void IEnumeratorBody2Observable_TryCatch(IEnumerator from)
    {
        from.ToObservable()
            .Catch<Unit, Exception>(expcetion =>
            {
                Debug.LogError("IEnumeratorBody2Observable_TryCatch的Catch");
                return Observable.ReturnUnit();
            })
            .DoOnCompleted(() => Debug.Log("IEnumeratorBody2Observable_TryCatch的DoOnCompleted(该异常不会阻碍DoOnCompleted的打印)")) //这里_(报错)与()(不报错)是不同的
            .Subscribe(_ => Debug.Log("IEnumeratorBody2Observable_TryCatch的Subscribe"))
            .AddTo(this);
    }

    IEnumerator enumerator(Action onComplted = null)
    {

        Debug.Log("enumerator的前");
        yield return null;
        Debug.Log("enumerator的后");
        onComplted?.Invoke();
    }

    IEnumerator enumerator_TryCatch(Action onComplted = null)
    {
        int index = 0;
        Debug.Log("enumerator的前");
        yield return null;
        Debug.Log("enumerator的后");
        int[] arr = new int[0];
         index = arr[0];
    }


    IObservable<Unit> Obs()
    {
        IObservable<Unit> res = Observable.ReturnUnit();
        res.Do(_ => Debug.Log("IObservable的前"))
            .DelayFrame(5)
            .Do(_ => Debug.Log("IObservable的后"));

        return res;
    }


    /// IObservable解决IEnumerator的异常捕捉
    IObservable<Unit> ObsTryCatch()
    {
        int index = 0;
        IObservable<Unit> res = Observable.ReturnUnit();
        res=res
            .Do(_ => Debug.Log("IObservable的前"))
            .DelayFrame(5)
            .Do(_ => Debug.Log("IObservable的后"))
            .Do( _=>
            {
                int[] arr = new int[0];
                index = arr[0];
            })
            .Catch<Unit,Exception>( expcetion=>               
            {

                Debug.LogError(" IObservable的异常");
                return Observable.ReturnUnit();
            });

        return res;
    }


    /// 转,但方法块在Observable
    void IEnumerator2ObservableBody()
    {
        Obs()
            .DoOnCompleted(() => Debug.Log("IObservable的DoOnCompleted"))
            .Subscribe()
            .AddTo(this);

        StartCoroutine(Obs()
            .DoOnCompleted(() => 
                Debug.Log("IObservable的StartCoroutine的DoOnCompleted"))
            .ToYieldInstruction());
    }

    /// 转,但方法块在Observable
    void IEnumerator2ObservableBody_TryCatch()
    {
        ObsTryCatch()
            .DoOnCompleted(() => Debug.Log("IObservable的TryCatch的DoOnCompleted"))
            .Subscribe()
            .AddTo(this);

        StartCoroutine(ObsTryCatch()
            .DoOnCompleted(() =>
                Debug.Log("IObservable的TryCatch的StartCoroutine的DoOnCompleted"))
            .ToYieldInstruction());
    }
    #endregion



}




watch 博主 inspironxdeUniRx系列(对UniRX的EventHandler拆解得很仔细,适合入门)

12.UniRx序列(FromEvent、FromEventPattern、Where、WhenAll、Never)

watch 波哥2010 (讲delegate,讲得易懂)

大白话系列之C#委托与事件讲解(一)

【未完成】TodoList备忘录Demo

位置

拖入里面的TodoList文件夹,改压缩包,是完整工程(包括QF)
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第98张图片

TodoItem

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
 
namespace QFramework.TodoList
{
    public class TodoItem 
    {
          public bool Completed;
          public string Content;


        public TodoItem(bool v1, string v2)
        {
            this.Completed = v1;
            this.Content = v2;
        }
    }
}

TodoList

using QFramework;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
 
namespace QFramework.TodoList
{
    public class TodoList
    {
        public List<TodoItem> mTodoItems;
    }
}

预制体

演示太琐碎,直接贴代码

        void CreatePrefab()
        {

            Transform UIRoot = transform.FindTop("UIRoot");//拖了一个QF的UIRoot预制体
            Transform Design = UIRoot.FindChildDeep("Design");
            Design.Show();
            //
            GameObject UITodoList = new GameObject("UITodoList");
            UITodoList.SetParent(Design);
            UITodoList.GetOrAddComponent<RectTransform>().Stretch();
            //
            GameObject text = new GameObject("Text");
            text.SetParent(UITodoList);
            text.GetOrAddComponent<RectTransform>().Stretch();
            text.AddComponent<Text>().alignment = TextAnchor.UpperCenter;
            text.AddComponent<UIMark>();

            // 根据上面拖出UITodoList这个预制体,右键两个@ResKit-AssetBundle Mark 、@UIKit-Create UICode,生成相关脚本
            //命名空间要改到,QFramework/Preferences
        }
    /// 平铺开
    public static  RectTransform Stretch(this RectTransform rect)
    {
        rect.anchorMin = Vector2.zero;
        rect.anchorMax = Vector2.one;
        rect.sizeDelta = Vector2.zero;

        return rect;
    }

bug QFramework/Preferences报错

bug UIOKPanelData不存在

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第99张图片

//
看了,也就是所在类名,改一下

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第100张图片

01 错误信息

我报错了,所以手动改namespace QFramework.Example 为 namespace QFramework.TodoList。图一
【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第101张图片

02 脚本位置

位置是Assets/QFramework/Framework/0.Core/Editor/1.PackageManager/Window/PackageKitWindow.cs

	public class PackageKitWindow : QEditorWindow
	{
		[MenuItem(FrameworkMenuItems.Preferences, false, FrameworkMenuItemsPriorities.Preferences)]
		private static void Open()
		{

03 快捷键重复

发现Ctrl+E(%e)快捷键,重复了,之前学QF摘了一些到个人库Common,先注释掉个人的

04 json文件丢失

【主跑例子】 Framework01、02;QFramework00(我跟着视频的旧版本,但推荐用最新的)、01(无)、02(无)、03(无)_第102张图片

05 到TodoList压缩包找该脚本复制

报空
至此,跳到最新版本

bug

这是sik学院视频下的资料,QF有点老了,也有一些报错。不建议用,建议到https://github.com/liangxiegame/QFramework下载最新的,里面例子,教程文档什么都有。

---------------------------------------------------

---------------------------------------------------

你可能感兴趣的:(Unity,C#,Siki,unity,c#)