C#Like是Unity的热更方案,使用纯C#语言写出可以热更新的代码,就像可以在所有平台使用DLL(动态链接库)文件一样.遵从KISS设计原则,让用户轻松构建或升级成Unity的热更新项目.本文将会分二十多章详细介绍C#Like,详见底部的文章导读.
题外话:
大家好,我叫容容,没想到加入优快云的日期是2006-08-05,竟然从未发布过一篇技术博客,当然也从未在其他博客发布过,真惭愧.这篇文章作为第一篇,是一个C#Like热更新方案的总则,接着下来将会出一系列的详细的技术探讨,会把我官网 www.csharplike.com 的教程转移到这里来.我这个书呆子不会宣传,只顾埋头敲代码,希望借此发博客能够让更多的人看到我的作品,大家切磋武功,也欢迎大家转载.
创作灵感:
C#Light的作者自2014年后就停更了没动静了,项目采用它也存在一系列的问题,例如解析效率低(视乎代码里需要几秒十几秒甚至以上,在手机上是致命的),支持C#语法太少,旧项目转为热更新项目的难度很大,难怪之前在网上看到过有人探讨Unity热更新方案对比时评价说C#Light只是"Like"(像)C#而已,说不上是C#.所以我要立项做出一个不只是像C#的热更新方案,一个真正接近纯C#的热更新方案,而且决定使用C#Like作为项目名字以致敬C#Light.
技术要点:
- 解析效率优化.我采用编译部分和执行部分分离,即运行时不再具备解析脚本功能,而只有运行功能,编译部分将完全放在编辑器内.这样运行时加载时间几乎可以忽略.
- 支持丰富的C#语法.我就把缺失部分的C#语法将逐一支持上.
- 升级成热更新项目精简化.我就做出一个几乎同MonoBehaviour一模一样功能的带热更新功能的LikeBehaviour,让用户的编程习惯无需改变,更不要说要额外采用其他语言(例如Lua)辅助热更,纯粹就只需把原来基类MonoBehaviour的改成LikeBehaviour及微调绑定的数据即可轻松地把旧项目升级成热更新项目.
- 全新的热更新模式.由于不再在运行时编译代码,即不能在运行时把一个字符串解析执行,不能针对性地对某个C#脚本进行热更,我们采用了所有的代码都是热更新代码的模式,除了初始包的登录界面是非热更新代码,其他所有的都是热更新代码.例如,我们的Unity初始的包内,不包含任何游戏代码和资源,游戏里所有的代码和资源都是全热更新的.可以做到玩家这个游戏包,今天进去玩的是游戏A,第二天进去玩的是游戏B...
- AssetBundle管理精简化,你只需设置场景的AssetBundle(你也可选地设置各资源的预制体以达到自定义AssetBundle的下载大小目的)及最终下载地址,即可完成整个热更新代码和资源的流程.
- 改进调试模式,可以做到断点调试代码.
Talk is cheap, show me the code:
好吧,拿出一个完整的热更新项目的作为示范吧(导出WebGL平台的演示,方便大家一点就可以进去测试看效果,大家完全也可以自行导出,服务器放在香港,访问可能会有点慢):
项目代码已放在GitHub,或者本文顶部下载.里面包含C#Like内置的演示和已转为热更新项目的2个Unity官方免费资源的项目Platformer Microgame 和Tanks! Tutorial.
欢迎自行导出测试验证我们的项目是真的可以热更新的.在下一篇Unity热更新方案C#Like(二)-导出官方示范的例子,确认方案可行性 会详细步骤示范如何导出,及2个Unity官方免费资源的项目如何一步一步地转化成热更新项目.
功能概要对比:
功能 | C#Light | C#Like免费版 | C#Like |
---|---|---|---|
委托 | 支持 | 支持 | 支持 |
Lambda | 支持 | 支持 | 支持 |
面向对象 | 类仅能继承接口 | 多了支持partial | 多了构造函数(支持this/base);析构函数;类继承;虚函数 |
运算表达式 | + - * / % += -= *= /= %= > >= < <= != == && || ! ++ --(仅支持i++不支持++i) ?: is as | 多了完全支持++ -- | 多了位运算 & | ~ ^ &= |= ^= << >> <<= >>= |
关键字 | this | this typeof | this 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表达式及弃元 | 不支持 | 不支持 | 支持 |
CSV | 无 | KissCSV | 同C#Like免费版 |
JSON | 无 | KissJSON | 同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#Like | C#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一样,有可能会被反编译出源码,这个是耗时的工程,后面考虑支持上)
- 尚未支持热更新代码中定义泛型类或接口或方法
本系列文章导读:
- Unity热更新方案C#Like(一)-序言
- Unity热更新方案C#Like(二)-导出官方示范的例子,确认方案可行性
- Unity热更新方案C#Like(三)-详解支持的C#特性:类
- Unity热更新方案C#Like(四)-详解支持的C#特性:委托和Lambda
- Unity热更新方案C#Like(五)-详解支持的C#特性:运算表达式
- Unity热更新方案C#Like(六)-详解支持的C#特性:循环语法
- Unity热更新方案C#Like(七)-详解支持的C#特性:get/set访问器
- Unity热更新方案C#Like(八)-详解支持的C#特性:多线程
- Unity热更新方案C#Like(九)-详解支持的C#特性:Using和命名空间
- Unity热更新方案C#Like(十)-详解支持的C#特性:宏和区域
- Unity热更新方案C#Like(十一)-详解支持的C#特性:枚举
- Unity热更新方案C#Like(十二-详解支持的C#特性:参数修饰符
- Unity热更新方案C#Like(十三)-详解支持的C#特性:函数重载和默认参数
- Unity热更新方案C#Like(十四)-详解支持的C#特性:异常处理
- Unity热更新方案C#Like(十五)-详解支持的C#特性:关键字:unsafe typeof nameof $ @ #pragma #warning #error
- Unity热更新方案C#Like(十六)-详解支持的C#特性:其他杂项:初始值设定项,表达式主体,内联变量声明
- Unity热更新方案C#Like(十七)-详解支持的长链接Socket和WebSocket
- Unity热更新方案C#Like(十八)-详解如何和Unity交互
- Unity热更新方案C#Like(十九)-详解KissJSON:唯一可以在本热更新框架使用的JSON库
- Unity热更新方案C#Like(二十)-详解KissCSV:一个简易实用的CSV表格读取方式
- Unity热更新方案C#Like(廿一)-详解KissFrameworkServer:对应的示范例子和官网所用的服务器框架
- Unity热更新方案C#Like(廿二)-详解内置的例子C#Like Demo:飞机大战,简易聊天室,简易账号/物品/邮件系统
- Unity热更新方案C#Like(廿三)-实战:示范如何把Unity官方免费例子Tanks! Tutorial转成可热更新项目
- Unity热更新方案C#Like(廿四)-实战:示范如何把Unity官方免费例子Platformer Microgame转成可热更新项目
- Unity热更新方案C#Like(廿五)-实战:示范如何建立初始包CSharpLikeFreeDemo项目
- Unity热更新方案C#Like(廿六)-(可选)详解免费版的演示如何升级到完整版的演示