这两天一直在研究CSLight,目前Unity热更新的方式有两种,一种是ulua这个网上的例子已经很多了。还有一种就是CSLight。其实我更希望CSLight可以趋向成熟,因为它的语法就是C#,但是有些C#的标准语法用不了。这两天我学习的做了一个例子,也把我遇到的坑记录一下。结合上章NGUI研究之李剑英的CSLight入门指南结合NGUI热更需要的朋友可以看下。
1.在github上下载CSLight,当我把DLL拖进项目的时候会报错。原因是CSLight的dll和NGUI的冲突了,所以我直接把他的core文件夹代码全部拷贝在我的工程里面。
2.脚本可以直接就创建成.cs文件,这样可以利用unity的语法提示。李总真是太聪明了哈哈。
3.脚本与类之间传递参数。。如下脚本所示,调用脚本UIMain中的Start()方法,并且将名子作为参数传递了进去。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
using using System.Collections; using using System; public class void { ScriptMgr.Instance.LoadProject(); ScriptMgr.Instance.Execute("UIMain.Start(\""+name+"\");"); } } |
ScriptMagr是李总封装的脚本管理类,是一个静态类。因为我们在脚本中可能会用到一些数据对象,需要提前注册一下,每次打开界面都去注册一下显然不太好。LoadProject()等于就是开游戏的时候注册一下,以后直接就去用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
using using System.Collections; using using System; /// <summary> /// 这个类实现脚本的Logger接口,脚本编译时的信息会从Log输出出来 /// </summary> class ScriptLogger { public { UnityEngine.Debug.Log(str); } public { Debug.LogError(str); } public { Debug.LogWarning(str); } } public { /// <summary> /// ScriptMgr用单例模式,主要是为了提供C#Light Env的初始化 /// </summary> public { get { if g_this return } } #region forInstance static public { get; private } private { env env.logger.Log("C#LightEvil RegTypes(); } #endregion /// <summary> /// 这里注册脚本有权访问的类型,大部分类型用RegHelper_Type提供即可 /// </summary> void { //大部分类型用RegHelper_Type提供即可 env.RegType(new env.RegType(new env.RegType(new env.RegType(new env.RegType(new env.RegType(new env.RegType(new env.RegType(new env.RegType(new env.RegType(new //对于AOT环境,比如IOS,get set不能用RegHelper直接提供,就用AOTExt里面提供的对应类替换 env.RegType(new env.RegType(new //每一种回调类型要独立注册 env.RegDeleType(new env.RegDeleType(new env.RegDeleType(new env.RegType(new env.RegType(new env.RegType(new env.RegType(new } public { get; private } public { if try { string[] Dictionary<string, foreach { var project.Add(v, } env.Project_Compiler(project, projectLoaded } catch { Debug.LogError("编译脚本项目失败,请检查" } } public { var try { var var expr.ComputeValue(content); } catch { var var var Debug.LogError(dumpv } } } |
大家注意看RegTypes()里面的注册方法。把你的脚本中用到的类,可以是unity提供的类,可以是NGUI提供的类,也可以是你自己封装的类都在这里注册一下,只有注册了你的脚本里才能使用这些方法。
假如界面Prefab在Assetbundle里面热更新了,那么脚本也对应需要更新,比如之前的界面只有一个按钮,那么新更新一个界面有两个按钮了,那么需要给新增加的按钮加监听事件。先看看下面可以热更新的这条脚本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
using using System.Collections; public class static //UICommon里面调用脚本的Start方法,并且传入了名子的字符串 static { Transform rootUI //在Resources下面读取资源或者 Assetbundle来读取,并且实例化在场景视图中。这一句操作我觉得也可以在Unity的脚本中完成 GameObject prefab = GameObject //放在UIPanel下面,让坐标在原点 gameObject.transform.parent gameObject.transform.localPosition gameObject.transform.localScale Transform transform //找到UIPrefab下面的一个Sprite并且修改一下Sprite的名子。 UISprite sprite.spriteName sprite.transform.localPosition sprite.MakePixelPerfect(); //获取按钮对象,并且增加按钮的监听 button UICommonEvent.onClick UICommonEvent.AddOnClick(button); } //当按钮点击的时候在脚本中得到回调 static { if(go.name Debug.Log("雨松MOMO提示,您点击了这个按钮喔"); } } } |
代码写完你会发现几乎和C#的脚本万全一样,但是有几个比较恶心的地方。
1.不支持范型。
热更新的这样的代码就不能直接使用了。
Resources.Load<GameObject>
gameObject.GetComponent<UISprite>
2.不支持typeof()关键字
3.不支持代理事件。
用NGUI做界面,可能里面用了大量的UIEventListener ,比如按钮、精灵的位移动画等等。这种东西如果硬要在脚本里面写太蛋疼了。我觉得最好还是把代理相关的东西拿出来。
还有就是做界面的时候可能会用到一些定时器,如果用代理来做的话也需要改改,总之向这种delegate回调的地方应该都要封装成方法,然后在回调进脚本里面。
在上面的代码中,我在处理按钮的点击事件的时候。如下代码所示,我写了一条Unity的脚本,在热更新的脚本里面,通过类名.就可以直接访问方法并且传递参数。UIEventListener监听到事件以后,在回调一下热更新脚本中的方法。
1 2 3 4 5 6 7 8 9 |
class public static { UIEventListener.Get(button).onClick onClick(go); }; } } |
注:我也不是CSLight的高手,也是最近开始学。感谢作者给我了很大帮助,他的游戏项目中大量的使用CSLight。据说效率还可以,这两天我在好好测试一下它的效率,希望有经验的朋友可以分享一些。谢谢啦
CSLight学习笔记结合NGUI