Unity热更新方案C#Like(一)-序言

C#Like是Unity的热更方案,使用纯C#语言写出可以热更新的代码,就像可以在所有平台使用DLL(动态链接库)文件一样.遵从KISS设计原则,让用户轻松构建或升级成Unity的热更新项目.本文将会分二十多章详细介绍C#Like,详见底部的文章导读.

题外话:

 大家好,我叫容容,没想到加入CSDN的日期是2006-08-05,竟然从未发布过一篇技术博客,当然也从未在其他博客发布过,真惭愧.这篇文章作为第一篇,是一个C#Like热更新方案的总则,接着下来将会出一系列的详细的技术探讨,会把我官网 www.csharplike.com 的教程转移到这里来.我这个书呆子不会宣传,只顾埋头敲代码,希望借此发博客能够让更多的人看到我的作品,大家切磋武功,也欢迎大家转载.


创作灵感:

 C#Light的作者自2014年后就停更了没动静了,项目采用它也存在一系列的问题,例如解析效率低(视乎代码里需要几秒十几秒甚至以上,在手机上是致命的),支持C#语法太少,旧项目转为热更新项目的难度很大,难怪之前在网上看到过有人探讨Unity热更新方案对比时评价说C#Light只是"Like"(像)C#而已,说不上是C#.所以我要立项做出一个不只是像C#的热更新方案,一个真正接近纯C#的热更新方案,而且决定使用C#Like作为项目名字以致敬C#Light.

技术要点:

  1.  解析效率优化.我采用编译部分和执行部分分离,即运行时不再具备解析脚本功能,而只有运行功能,编译部分将完全放在编辑器内.这样运行时加载时间几乎可以忽略.
  2. 支持丰富的C#语法.我就把缺失部分的C#语法将逐一支持上.
  3. 升级成热更新项目精简化.我就做出一个几乎同MonoBehaviour一模一样功能的带热更新功能的LikeBehaviour,让用户的编程习惯无需改变,更不要说要额外采用其他语言(例如Lua)辅助热更,纯粹就只需把原来基类MonoBehaviour的改成LikeBehaviour及微调绑定的数据即可轻松地把旧项目升级成热更新项目.
  4. 全新的热更新模式.由于不再在运行时编译代码,即不能在运行时把一个字符串解析执行,不能针对性地对某个C#脚本进行热更,我们采用了所有的代码都是热更新代码的模式,除了初始包的登录界面是非热更新代码,其他所有的都是热更新代码.例如,我们的Unity初始的包内,不包含任何游戏代码和资源,游戏里所有的代码和资源都是全热更新的.可以做到玩家这个游戏包,今天进去玩的是游戏A,第二天进去玩的是游戏B...
  5. AssetBundle管理精简化,你只需设置场景的AssetBundle(你也可选地设置各资源的预制体以达到自定义AssetBundle的下载大小目的)及最终下载地址,即可完成整个热更新代码和资源的流程.
  6. 改进调试模式,可以做到断点调试代码.

Talk is cheap, show me the code:

 好吧,拿出一个完整的热更新项目的作为示范吧(导出WebGL平台的演示,方便大家一点就可以进去测试看效果,大家完全也可以自行导出,服务器放在香港,访问可能会有点慢):

项目代码已放在GitHub,或者本文顶部下载.里面包含C#Like内置的演示和已转为热更新项目的2个Unity官方免费资源的项目Platformer Microgame 和Tanks! Tutorial.
欢迎自行导出测试验证我们的项目是真的可以热更新的.在下一篇Unity热更新方案C#Like(二)-导出官方示范的例子,确认方案可行性 会详细步骤示范如何导出,及2个Unity官方免费资源的项目如何一步一步地转化成热更新项目. 

功能概要对比:

功能C#LightC#Like免费版C#Like
委托支持支持支持
Lambda支持支持支持
面向对象类仅能继承接口多了支持partial多了构造函数(支持this/base);析构函数;类继承;虚函数
运算表达式+ - * / % += -= *= /= %= > >= < <= != == && || ! ++ --(仅支持i++不支持++i) ?: is as多了完全支持++ --多了位运算 & | ~ ^ &= |= ^= << >> <<= >>=
关键字thisthis typeofthis base sizeof typeof unsafe $ @ #pragma #warning #error
命名空间 using不支持,有名无实,导致每种在热更代码里使用的所有类型必须先非热更注册,非常不便且容易遗漏完整的命名空间功能,无需事先注册类型就能直接使用,使用方便;using指令/别名/static;多了using语句
异常处理throw同C#Light多了try-catch-finally
类型var void bool float double char string byte sbyte int uint short ushort long ulong null同C#Light多了支持可空运算?及配套的合并运算?. ??
get/set访问器仅支持自动实现的get/set同C#Light多了可以自定义实现get/set
循环语句for foreach continue break if-else return while do-while同C#Light多了switch-case-default
调试能打印报错语句在调试模式下可以使用Visual Studio断点/步进调试,与正常C#一模一样;热更代码模式下当脚本出错可以打印出堆栈数据(文件名/函数名/第几行)同C#Like免费版,但支持更多C#特性,大幅减少调试模式和热更代码模式差异
编译脚本在运行时编译,视乎你的代码量多少可能会花费几秒甚至超过十几秒,即使已经预编译为Token了所有编译过程都在编辑器里完成,保存为二进制文件,运行时加载时间几乎可以忽略,虽然编译时间也基本一样(首次编译甚至花费更多时间建立缓存数据),但加载时候给玩家极好的体验同C#Like免费版
MonoBehaviour不支持LikeBehaviour仿照MonoBehaviour,让热更脚本直接按MonoBehaviour的方式写代码,热更脚本就像是继承MonoBehaviour一样多了完美支持协程
多线程不支持支持支持且多了lock语法
注释仅//仅////和/**/
宏定义和区域不支持不支持#if #elif #else #endif #region #endregion
枚举不支持不支持支持
参数修饰符不支持不支持支持ref out in params
函数重载不支持不支持支持
默认参数不支持不支持支持
对象初始值设定项不支持不支持支持
集合初始值设定项不支持不支持支持
内联变量声明不支持不支持支持
表达式主体不支持不支持支持
switch表达式及弃元不支持不支持支持
CSVKissCSV同C#Like免费版
JSONKissJSON同C#Like免费版
Socket/WebSocket超简洁的可热更的接口,提供KissServerFramework(最简洁易用的IOCP服务器框架,用户逻辑单线程,后台数据库多线程,面向对象,操作极简,包含WebSocket/Socket/HTTP/MySQL,你不会用到SQL的,只需定义数据库表结构,即可使用数据且自动和客户端和数据库三者间同步数据)同C#Like免费版
ResourceManager全自动更加方便管理AssetBundle,设置场景的AssetBundle后,你只需在C#Like设置面板里配置最终下载地址即可同C#Like免费版

快速了解:

  • 传统非热更新代码:我们定义一个最简单的类,继承于MonoBehaviour,调用最常用的几个生命周期函数
using UnityEngine;
using System;
using System.Collections;

namespace CSharpLike
{
	/// <summary>
	/// 最简单的非热更Hello World例子
	/// 示范最简单的Unity生命周期函数
	/// 和协程的简单用法
	/// </summary>
	public class SampleHelloWorld : MonoBehaviour
	{
		void Awake()
		{
			gameObject.name = "I'm MonoBehaviour";
			Debug.Log("Awake");
		}
		void OnEnable()
		{
			Debug.Log("OnEnable");
		}
		IEnumerator Start()
		{
			Debug.Log("Start:这里返回类型为IEnumerator表示为协程模式");
			Debug.Log("Start:before WaitForSeconds:" + DateTime.Now.ToString());
			yield return new WaitForSeconds(2f);
			Debug.Log("Start:after WaitForSeconds:" + DateTime.Now.ToString());
			/*'StartCoroutine(string methodName, object obj)'的方式最多1个参数
			3个参数的只能使用StartCoroutine(IEnumerator routine)的方式
			这里示范调起带3个参数的子协程*/
			yield return StartCoroutine(SubCoroutine("test string", 123, -1f));
			Debug.Log("Start:after SubCoroutine:" + DateTime.Now.ToString());
			停止协程示范:
			StopCoroutine("SubCoroutine");//只能停止按函数名方式启动的
			//StopAllCoroutines();
		}
		//由Start函数调起的子协程 
		IEnumerator SubCoroutine(string strValue, int iValue, float fValue)
		{
			Debug.Log("SubCoroutine(" + strValue + "," + iValue + "," + fValue + ")");
			yield return new WaitForSeconds(2f);
			if (fValue > 0f)
				yield break;
			else
			{
				//示范可空类型'?' 合并运算 '?.' 和 '??'
				System.Random r = null;//new System.Random();
				int? i = r?.Next(1000);
				Debug.Log("SubCoroutine:i=" + (i ?? iValue));
			}
			yield return new WaitForEndOfFrame();
			Debug.Log("SubCoroutine:end:" + DateTime.Now.ToString());
		}
		void FixedUpdate()
		{
			Debug.Log("FixedUpdate");
		}
		float angle = 0f;
		void Update()
		{
			//Debug.Log("Update");
			angle += Time.deltaTime * 50f;
			transform.localEulerAngles = new Vector3(0f, angle, 0f);
		}
		void LateUpdate()
		{
			Debug.Log("LateUpdate");
		}
		void OnGUI()
		{
			Debug.Log("OnGUI");
		}
		void OnDisable()
		{
			Debug.Log("OnDisable");
		}
		void OnDestroy()
		{
			Debug.Log("OnDestroy");
		}
	}
}
  •  这里我们写一个跟上面传统unity代码一模一样功能的热更代码(C#Like完整版的),大家可以对比一下两者的区别:
using UnityEngine;
using System;
using System.Collections;

namespace CSharpLike
{
	/// <summary>
	/// 最简单的热更Hello World例子.
	/// 示范最简单的Unity生命周期函数(支持所有Behaviour所有事件,这里示范最常用的).
	/// 和协程的简单用法.
	/// </summary>
	public class SampleHelloWorld : LikeBehaviour
	{
		void Awake()
		{
			//同MonoBehaviour的gameObject
			gameObject.name = "I'm LikeBehaviour";
			Debug.Log("Awake:和Unity MonoBehaviour的完全一样");
		}
		void OnEnable()
		{
			Debug.Log("OnEnable:和Unity MonoBehaviour的完全一样");
		}
		IEnumerator Start()
		{
			Debug.Log("Start:这里返回类型为IEnumerator表示为协程模式");
			Debug.Log("Start:before WaitForSeconds:" + DateTime.Now.ToString());
			yield return new WaitForSeconds(2f);
			Debug.Log("Start:after WaitForSeconds:" + DateTime.Now.ToString());
			/*只支持'StartCoroutine(string methodName, params object[] vars)'的方式
			注意:不支持StartCoroutine(SubCoroutine("test string", 123, -1f))写法
			这里示范调起带3个参数的子协程*/
			yield return StartCoroutine("SubCoroutine", "test string", 123, -1f);
			Debug.Log("Start:after SubCoroutine:" + DateTime.Now.ToString());
			停止协程示范:
			//StopCoroutine("SubCoroutine");
			//StopAllCoroutines();
		}
		//由Start函数调起的子协程 
		IEnumerator SubCoroutine(string strValue, int iValue, float fValue)
		{
			Debug.Log("SubCoroutine(" + strValue + "," + iValue + "," + fValue + ")");
			yield return new WaitForSeconds(2f);
			if (fValue > 0f)
				yield break;
			else
			{
				//示范可空类型'?' 合并运算 '?.' 和 '??'
				System.Random r = null;//new System.Random();
				int? i = r?.Next(1000);
				Debug.Log("SubCoroutine:i=" + (i ?? iValue));
			}
			yield return new WaitForEndOfFrame();
			Debug.Log("SubCoroutine:end:" + DateTime.Now.ToString());
		}
		void FixedUpdate()
		{
			Debug.Log("FixedUpdate:和Unity MonoBehaviour的完全一样");
		}
		float angle = 0f;
		void Update()
		{
			//Debug.Log("Update:和Unity MonoBehaviour的完全一样");
			angle += Time.deltaTime * 50f;
			//同MonoBehaviour的transform
			transform.localEulerAngles = new Vector3(0f, angle, 0f);
		}
		void LateUpdate()
		{
			Debug.Log("LateUpdate:和Unity MonoBehaviour的完全一样");
		}
		void OnGUI()
		{
			Debug.Log("OnGUI:和Unity MonoBehaviour的完全一样");
		}
		void OnDisable()
		{
			Debug.Log("OnDisable:和Unity MonoBehaviour的完全一样");
		}
		void OnDestroy()
		{
			Debug.Log("OnDestroy:和Unity MonoBehaviour的完全一样");
		}
	}
}
  •  这里我们写一个跟上上面面传统unity代码类似功能的热更代码(C#Like免费版的),大家可以对比一下两者的区别:
using UnityEngine;
using System;

namespace CSharpLike
{
	/// <summary>
	/// 最简单的热更Hello World例子.
	/// 示范最简单的Unity生命周期函数(支持所有Behaviour所有事件,这里示范最常用的).
	/// 和模仿协程的简单用法.
	/// </summary>
	public class SampleHelloWorld : LikeBehaviour
	{
		void Awake()
		{
			//同MonoBehaviour的gameObject
			gameObject.name = "I'm LikeBehaviour";
			Debug.Log("Awake:和Unity MonoBehaviour的完全一样");
		}
		void OnEnable()
		{
			Debug.Log("OnEnable:和Unity MonoBehaviour的完全一样");
		}
		int stepStart = 0;
		void Start()
		{
			if (stepStart == 0)
			{
				Debug.Log("Start:和Unity MonoBehaviour的一样但不能使用协程");
				Debug.LogError("示范协程: 你不能在C#Like免费版里使用协程"+
				" (在完整版已支持).强烈推荐升级到完整版: " + 
				"https://assetstore.unity.com/packages/slug/222256");
				// 我们提供以下方案给免费用户:
				// 协程: 使用 MemberCallDelay 模拟协程 (只能模拟
				// 'yield return new WaitForSeconds(float seconds);'
				// 和 'yield return null;').
				// 协程是Unity非常强大的功能,它能够让我们的代码逻辑变得更清晰整洁,
				// 你不去使用它实在太可惜了.
				Debug.LogError("Start:step0: " + DateTime.Now);
				stepStart++;
				MemberCallDelay("Start", 2f);
			}
			else if (stepStart == 1)
			{
				Debug.LogError("Start:step1: " + DateTime.Now);
				stepStart++;
				MemberCallDelay("Start");
			}
			else if (stepStart == 2)
			{
				Debug.LogError("Start:step2: " + DateTime.Now);
				stepStart++;
				SubCoroutine("test", 123, 321f);
			}
			else if (stepStart == 3)
			{
				Debug.LogError("Start:step3: " + DateTime.Now);
				stepStart = 0;
			}
		}
		int stepSubCoroutine = 0;
		void SubCoroutine(string str, int iValue, float fValue)
		{
			if (stepSubCoroutine == 0)
			{
				Debug.LogError("SubCoroutine:(" + str + "," + iValue + "," + fValue
				+ ") " + DateTime.Now);
				stepSubCoroutine++;
				MemberCallDelay("SubCoroutine", str, iValue, fValue, 2f);
			}
			else if (stepSubCoroutine == 1)
			{
				Debug.LogError("SubCoroutine:end " + DateTime.Now);
				MemberCallDelay("Start");
				stepSubCoroutine = 0;
			}
		}
		void FixedUpdate()
		{
			Debug.Log("FixedUpdate:和Unity MonoBehaviour的完全一样");
		}
		float angle = 0f;
		void Update()
		{
			//Debug.Log("LateUpdate:和Unity MonoBehaviour的完全一样");
			angle += Time.deltaTime * 50f;
			transform.localEulerAngles = new Vector3(0f, angle, 0f);
		}
		void LateUpdate()
		{
			Debug.Log("LateUpdate:和Unity MonoBehaviour的完全一样");
		}
		void OnGUI()
		{
			//Debug.Log("OnGUI:和Unity MonoBehaviour的完全一样");
			if (GUI.Button(new Rect(0, 0, 64, 64), "Back"))
			{
				//返回上一层及关掉自身
				SampleCSharpLike.instance.gameObject.SetActive(true);
				HotUpdateManager.Hide("Sample/SampleHelloWorld");
			}
		}
		void OnDisable()
		{
			Debug.Log("OnDisable:和Unity MonoBehaviour的完全一样");
		}
		void OnDestroy()
		{
			Debug.Log("OnDestroy:和Unity MonoBehaviour的完全一样");
		}
	}
}

开发里程碑:

版本1.0

万事开头难,项目分成2部分考虑,一部分是制作一个编译器,专门负责解析C#代码成为可执行的二进制文件,编译成类似DLL一样功能的文件;一部分是制作一个虚拟机,专门负责执行可执行的二进制文件的指令,类似于执行DLL文件.大家都知道,在Unity的IL2CPP环境下,是不可能存在DLL的.幸好能站在C#Light这个巨人肩膀上,完成这两大模块的框架搭建.

然后就是怎样仿制一个LikeBehaviour来作为衔接非热更新代码部分和热更新代码部分的桥梁.

最后就是针对性地支持更多的C#语法.

还有就是JSON库无法使用其他的,只能使用内置的KissJSON,因为其他JSON库无法和热更新代码里的类互相转换,独此一家.

顺便还做了一些内置的示范代码以验证各种C#特性.

总之首个版本是最最耗时的.

版本1.1

毕竟游戏很多都是会有个服务器的,HTTP就不用说了,长链接Socket/WebSocket总得支持吧?然后就弄了个内置的Socket/WebSocket,可直接在热更新项目里使用的那种.

有了长链接,对应测试的服务器代码框架总得有吧?然后就弄了个免费的KissFrameworkServer放在GitHub,里面就是对应内置演示例子的服务器代码.

作为游戏,肯定策划会使用表格填数值吧?然后就弄了个读取CSV的功能. 

版本1.2

 初版的KissFrameworkServer是通过配置RIDL文件来配置传递的网络对象的,感觉比较菜,怎么可能不可视化地编辑呢?为了想可以在多个平台使用,就采用了跨平台的UI库GtkSharp,因为没有使用过GtkSharp,花了不少时间去弄这个编辑器.

版本1.3

 除了修正KissEditor编辑器部分错误,发现我的官网实在太挫了,整个网站就只有1个html静态网页文件,说出来可能会被人笑话,怎么说KissFrameworkServer也是包含HTTP功能的,那就优化KissFrameworkServer吧,不只是客户端示范使用它,而且官网也使用它,采用Bootstraps作为H5前端,而且做了一个Demo系统以备作为GM后台使用.

版本1.4

 AssetBundle想采用官方的Addressable,但自己都搞得一头雾水,算了,自己写一个AssetBundle管理器,遵从KISS原则,用户只需设置极少的内容即可轻松管理.

有一个用户来信咨询如何把一个项目转为热更新项目,还提议把一个Unity出品的一个塔防转成热更新的项目,然后我一看,资源文件很大,弄出来了也不好作为示范,我只把其中一个界面的代码改成热更新的且把步骤发给该用户.然后挑选了一个Unity里一个代码量比较少的免费项目'Tanks! Tutorial'改成热更新项目.

同时也修正了部分转化项目时候发现的一些Bug.

版本1.5

那个Unity出品的项目代码量太少了吧,就只有9个脚本,这怎么能说服别人使用你的产品,然后就再选一个代码多一些的免费资源吧,依惯例还是找Unity出品的吧.然后就选'Platformer Microgame'.

同时也修正了部分转化项目时候发现的一些Bug.

版本1.6

 前面的ResourceManager还是不够精简,得再次优化,优化到用户只需设置场景的AssetBundle及最终下载地址即可,其他可以完全不用管.

还有其他原先需要手动做的合并配置的都做到了自动合并,让用户操作更加少.

而且官网的教程再次优化.

版本1.7

这个版本主要是完善更加多的C#特性,让C#Like更接近C#了. 

版本1.8

C#特性还是会不断往里面添加,以体现我的诚意. 

项目版本历史

版本C#LikeC#Like免费版
1.0功能
- 支持协程.
- 支持JSON库. KissJson是唯一可同时在热更和非热更代码都可以使用的JSON库.
- 支持委托.
- 支持lambda语法.
- 支持IL2CPP.
- 面向对象. 支持构造函数(支持this/base);析构函数;类继承;虚函数;接口继承;支持partial.
- 运算表达式. 支持+ - * / % += -= *= /= %= > >= < <= != == && || ! ++ -- ?: ?. ?? & | ~ ^ &= |= ^= << >> <<= >>=
- 支持命名空间, using 指令, using 别名, using 语句, using static.
- 循环语句: for foreach continue break if-else return while do-while throw switch-case-default lock try-catch-finally yield
- 支持自动实现的和自定义的get/set访问器.
- 支持所有类型(含Nullable).
- 支持枚举.
- 支持宏和区域.#if #elif #else #endif #region #endregion
- 支持多线程.
- 支持注释方式: //和/**/
- 支持函数修饰符: ref out in params.
- 支持函数函数重载.
- 支持函数默认值.
- 支持自定义目标二进制文件加密.
- 其他: 支持关键字this base sizeof typeof unsafe as is $ @ #pragma #warning #error volatile abstract.
功能
- 支持JSON库. KissJson是唯一可同时在热更和非热更代码都可以使用的JSON库.
- 支持委托.
- 支持lambda语法.
- 支持IL2CPP.
- 面向对象. 支持partial和继承接口.
- 运算表达式. 支持+ - * / % += -= *= /= %= > >= < <= != == && || ! ++ -- ?:
- 支持命名空间, using 指令, using 别名, using static.
- 循环语句: for foreach continue break if-else return while do-while throw
- 支持自动实现的get/set访问器
- 支持Nullable外的类型.
- 支持多线程(不支持'lock'语法).
- 支持注释方式: //
- 支持自定义目标二进制文件加密.
- 其他: 支持关键字this typeof as is
1.1功能
- 支持CSV文件.
- 全平台支持Socket/WebSocket.
- 支持KissFramework, 一个超级简单易用的服务器框架.
- 支持数字后缀'f/F/u/U/l/L'.
- 重构和优化代码.
修正
- 修复错误: KissJSON里类型为long/ulong的报错.
- 修复错误: if-else语句如果出现空白的语句会报错.
- 修复错误: 自定义getset可能出现上下文异常.
功能
- 支持CSV文件.
- 全平台支持Socket/WebSocket.
- 支持KissFramework, 一个超级简单易用的服务器框架.
- 支持数字后缀'f/F/u/U/l/L'.
- 重构和优化代码.
修正
- 修复错误: KissJSON里类型为long/ulong的报错.
- 修复错误: if-else语句如果出现空白的语句会报错.
1.2功能
- KissJSON格式化JSON增加更可读性的接口.
- HotUpdateBehaviour绑定新增类型'Vector3/Color'.
修正
- KissServerFramework使用KissEditor编辑器,可以更方便编辑网络对象.
功能
- KissJSON格式化JSON增加更可读性的接口.
- HotUpdateBehaviour绑定新增类型'Vector3/Color'.
修正
- KissServerFramework使用KissEditor编辑器,可以更方便编辑网络对象.
1.3功能
- KissServerFramework可以轻松架构网页了.
修正
- 修正无法从热更代码里访问非热更代码里的放在类里面的枚举.
- KissEditor编辑器修正部分错误.
功能
- KissServerFramework可以轻松架构网页了.
修正
- 修正无法从热更代码里访问非热更代码里的放在类里面的枚举.
- KissEditor编辑器修正部分错误.
1.4功能
- 新增ResourceManager,最精简方式自动导出AssetBundle和读取资源.
- 新增link.xml配置.
- 把Unity出品的Tanks! Tutorial改造成全热更项目,并列出详尽过程.
- 获取对应热更脚本类的对象实例,无需再借助HotUpdateBehaviour.
修正
- 协程内,while循环语句里的出现'yield return'语句会发生异常.
- 修正LikeBehaviour修正Color和Vector3类型的数据获取.
- 非内置类型的数学计算发生异常,例如Vector3的加减乘除运算.
- 热更脚本里的类对象的数组异常.
功能
- 新增ResourceManager,最精简方式自动导出AssetBundle和读取资源.
- 新增link.xml配置.
- 使用C#Like免费版把Unity出品的Tanks! Tutorial改造成全热更项目,并列出详尽过程.
- 获取对应热更脚本类的对象实例,无需再借助HotUpdateBehaviour.
修正
- 修正LikeBehaviour修正Color和Vector3类型的数据获取.
- 非内置类型的数学计算发生异常,例如Vector3的加减乘除运算.
- 热更脚本里的类对象的数组异常.
1.5功能
- 增加Sprite的绑定.
- 增加对象的null的判断.
- 把Unity出品的Platformer Microgame改造成全热更项目.
- 增加Simulation的事件.
修正
- 修正as语句异常情况.
- 修正多重继承LikeBehaviour的类的override函数异常.
- 允许Array出现0的情况.
- 修正$语法糖多于2个参数会异常的情况, 现在支持包含特殊符号'{{'和'}}'和转义符'\'.
功能
- 增加Sprite的绑定.
- 增加对象的null的判断.
- 把Unity出品的Platformer Microgame改造成全热更项目.
- 增加Simulation的事件.
修正
- 修正as语句异常情况.
- 允许Array出现0的情况.
1.6功能
- ResourceManager现在更加全自动更加方便管理AssetBundle了,你只需在C#Like设置面板里配置最终下载地址即可.
- 编辑器里直接运行可以直接调用StreamingAssets内自动打包好的AssetBundle资源了,测试更加方便了.
修正
- 修正LikeBehaviour的behaviour异常,现在内置Demo的'飞机大战'正常了.
- 修正函数传入null会报错异常的问题.
- 修正可空类型异常.
- 'AheadOfTime.cs'和'link.xml'现在能自动合并了.
功能
- ResourceManager现在更加全自动更加方便管理AssetBundle了,你只需在C#Like设置面板里配置最终下载地址即可.
- 编辑器里直接运行可以直接调用StreamingAssets内自动打包好的AssetBundle资源了,测试更加方便了.
修正
- 修正LikeBehaviour的behaviour异常,现在内置Demo的'飞机大战'正常了.
- 'AheadOfTime.cs'和'link.xml'现在能自动合并了.
1.7功能
- 增加由非热更新代码快速调用热更新代码的函数.
- 支持使用对象初始值设定项.
- 支持内联变量声明.
- 支持构造函数和方法和属性和访问器的表达式主体.
- 支持switch表达式及弃元'_'.
- 支持集合初始值设定项.
功能
- 增加由非热更新代码快速调用热更新代码的函数.
1.8功能
- 支持关键字nameof.
- 支持逐字文本 - @ 在变量、属性和字符串文本中.

目前不足之处:

- 尚未支持goto语句(曾有老师说过这个goto太破坏流程的,谨慎使用)
- 尚未支持热更新代码中使用async和await(但目前我们是可以使用协程的)
- 尚未支持代码混淆(这个代码像C#的DLL一样,有可能会被反编译出源码,这个是耗时的工程,后面考虑支持上)
- 尚未支持热更新代码中定义泛型类或接口或方法

 本系列文章导读:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C#Like

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值