C#Like是Unity的热更方案,使用纯C#语言写出可以热更新的代码,就像可以在所有平台使用DLL(动态链接库)文件一样.遵从KISS设计原则,让用户轻松构建或升级成Unity的热更新项目.
简介
本篇主要介绍C#Like如何和Unity交互:
- 预制体或场景里的组件如何绑定热更新的代码
- 热更新代码如何访问预制体或场景里的组件
- 非热更新代码如何调用热更新代码.
- 热更新代码如何调用非热更新代码.
预制体或场景里的组件如何绑定热更新的代码:
假设我们热更新代码里有个类,继承于LikeBehaviour,里面有若干MonoBehaviour的生命周期函数,然后在预制体或场景里想要绑定这个类,就像该类就是继承于MonoBehaviour一样.
- 首先,我们写这个热更新代码的如下:
using System;
using UnityEngine;
using UnityEngine.UI;
namespace CSharpLike
{
/// <summary>
/// 热更脚本和Unity交互数据的例子
/// </summary>
public class ExampleInteractivePrefabData : LikeBehaviour
{
void Start()
{
//获取当前热更新脚本组件,该组件继承于MonoBehaviour,可看做MonoBehaviour
Debug.Log("HotUpdateBehaviour=" + behaviour);
//同MonoBehaviour的gameObject
Debug.Log("gameObject.name=" + gameObject.name);
//同MonoBehaviour的transform
Debug.Log("transform.localPosition=" + transform.localPosition);
//获取预制体里设置的数值类数据(int/bool/float/double/string),以字符串为键值
//这里获取int数值为例子,在预制体中,我们设置一个键值'iValueA'的值为123
//GetBoolean/GetDouble/GetFloat/GetString
Debug.Log("integer value set in prefab:iValue=" + GetInt("iValueA"));
//我们可以修改该数值,它会在编辑器里刷新.
//你也可以运行中在编辑器里直接修改它.
SetInt("iValueA", 321);//SetBoolean/SetDouble/SetFloat/SetString
//这里再次调用一下该数值,看修改是否有效
Debug.Log("integer value after modify:iValue=" + GetInt("iValueA"));
//我们可以获取预制体里Unity的组件(GameObject/TextAsset/Material/Texture/AudioClip),
//同样也是以字符串为键值.
//这里获取GameObject为例子,在预制体中,我们设置了一个键值为'ButtonStart'的GameObject
GameObject goStart = GetGameObject("ButtonStart");
goStart.SetActive(true);//我们设置它为活动,在预制体中,我们设置隐藏的
//我们这里示范获取预制体绑定的文本组件(UnityEngine.UI.Text)
//你可以获取在'运行时'绑定在HotUpdateBehaviour的gameObjects组件.
//你可以获取任何可以通过GameObject.GetComponent<T>()来获取的Unity组件.
//例如Image/Button/Slider/MeshRenderer/...等等
Text text = GetComponent<Text>("TextMsg");
//这里示范获取绑定在预制体的'资源'(TextAsset/Material/Texture/AudioClip),
//例如文本资源(TextAsset)这些在编辑器不能拖在GameObject列的.
TextAsset ta = GetTextAsset("LoadTextAsset");//GetMaterial/GetTexture/GetAudioClip
Debug.Log("Load TextAsset:" + ta.text);
text.text = ta.text;//读取文本资源后,在前面绑定的文本组件里显示
}
void OnClick(int i, string str)//'ButtonStart'绑定的按钮响应
{
//点击按钮,在文本组件里显示当前时间和显示传入的参数i和str
GetComponent<Text>("TextMsg").text = DateTime.Now.ToString() + ",i=" + i + ",str=" + str;
}
void OnClickBack()//'Back'绑定的按钮响应
{
HotUpdateManager.Show("Assets/C#Like/Sample/SampleCSharpLikeHotUpdate.prefab");//显示上一个界面
HotUpdateManager.Hide("Assets/C#Like/Sample/SampleInteractivePrefabData.prefab");//关闭自身
}
}
}
- 初始的HotUpdateBehaviour只包含"Awake/OnEnable/Start/OnDisable/OnDestroy"基本的生命周期函数,你必须写一批适合你待开发的游戏的非热更新代码HotUpdateBehaviourXXXX以备用,请模仿"Assets\C#Like\Runtime\Interaction\HotUpdateBehaviourCustom\HotUpdateBehaviour{XXXX}.cs". (如果最后你的游戏已经发布了,但找不到合适的HotUpdateBehaviourXXXX用的话,可以使用后备方案的包含所有生命周期的"HotUpdateBehaviourAll.cs",但不建议是因为会有一定的性能损失), 如下代码是模仿写法:
using UnityEngine;
namespace CSharpLike
{
/// <summary>
/// 这个HotUpdateBehaviour是额外带"OnApplicationFocus/OnApplicationPause/OnApplicationQuit"的.
/// "Awake/OnEnable/Start/OnDisable/OnDestroy"是由基类HotUpdateBehaviour带上了.
/// (更多的生命周期详见Unity官网: https://docs.unity3d.com/ScriptReference/MonoBehaviour.html).
/// </summary>
public class HotUpdateBehaviourApplication : HotUpdateBehaviour
{
void OnApplicationFocus(bool hasFocus)
{
helper.MemberCall("OnApplicationFocus", hasFocus);
}
void OnApplicationPause(bool pauseStatus)
{
helper.MemberCall("OnApplicationPause", pauseStatus);
}
void OnApplicationQuit()
{
helper.MemberCall("OnApplicationQuit");
}
}
}
- 然后在预制体或场景里选取合适的"CSharpLike.HotUpdateBehaviour"作为桥接.上面的例子只用到Start(),那只需选用最基础HotUpdateBehaviour即可.
- 创建一个预制体叫SampleInteractivePrefabData
- 如下图上部,里面包含1个Text组件(msg)和1个返回按钮(back,里面的OnClick组件绑定HotUpdateBehaviour.OnClick事件,参数写OnClickBack)和1个开始按钮(buttonStart,里面的OnClick组件绑定HotUpdateBehaviour.OnClick事件,参数填OnClick(456,"xyz"),即点击该按钮的时候相当于执行代码 OnClick(456,"xyz"); 一样)
- 如下图的下部,选中SampleInteractivePrefabData节点后,在Inspector面板添加组件HotUpdateBehaviour.然后设置该组件:
- 设置"Integers",新加一个Key为iValueA,Value为123的,即相当于MonoBehaviour脚本"public int iValueA;"绑定一个数值123一样
- 设置"Game Objects",新加Key为ButtonStart,Value为拖放buttonStart节点,即相当于MonoBehaviour脚本"public GameObject ButtonStart;"拖放buttonStart节点绑定一样.
- 设置"Game Objects",新加Key为TestMsg,Value为拖放msg节点,即相当于MonoBehaviour脚本"public Text TextMsg;"拖放msg节点绑定一样.
- 设置"Text Assets",新加Key为Key为LoadTextAsset,Value为拖放的文本资源文件,即相当于MonoBehaviour脚本"public TextAsset LoadTextAsset;"拖放文本资源文件绑定一样.
- 最后,设置绑定的完整类名:"Bind Hot Update Class Full Name"为"CSharpLike.SampleInteractivePrefabData",注意,如有命名空间,必须带上命名空间哦.
热更新代码如何访问预制体或场景里的组件:
- 如何访问预制体或场景里绑定的数值,目前支持类型:int/float/double/bool/string/Vector3/Color
传统Unity代码MonoBehaviour | 热更新代码LikeBehaviour方式1 | 热更新代码LikeBehaviour方式2 | |
---|---|---|---|
定义 | public int iValueA; | 无需定义 | 同传统Unity代码 |
预制体设置 | 设置iValueA数值为123 | "Integers"新加一个Key为iValueA,Value为123 | 同方式1 |
预绑定 | 无 | 无 | 在Start或Awake函数内绑定 iValueA = GetInt("iValueA"); |
读取 | 直接使用iValueA,例如 Debug.Log("iValueA="+iValueA); | Debug.Log("iValueA="+GetInt("iValueA")); | 同传统Unity代码 |
修改 | 直接修改iValueA,例如 iValueA = 321; | SetInt("iValueA", 321); | 同传统Unity代码 |
优点 | 性能好 | 代码精简,无需在代码里定义数据 | 从传统Unity代码升级方便, 原则上仅需在Start或Awake里绑定即可. 性能上比方式1好一些 |
缺点 | 非热更新 | 频繁获取或修改的性能较差 | 代码量会多一些 |
- 如何访问预制体或场景里绑定的组件,例如Text/GameObject/...
传统Unity代码MonoBehaviour | 热更新代码LikeBehaviour方式1 | 热更新代码LikeBehaviour方式2 | |
---|---|---|---|
定义 | public Text TextMsg; | 无需定义 | 同传统Unity代码 |
预制体设置 | 设置LoadTextAsset为拖放的文本资源文件 | "Text Assets",新加Key为Key为LoadTextAsset,Value为拖放的文本资源文件 | 同方式1 |
预绑定 | 无 | 无 | 在Start或Awake函数内绑定 TextMsg = GetComponent<Text>("TextMsg"); |
读取 | 直接使用TextMsg,例如 Debug.Log(TextMsg.text); | Debug.Log(GetComponent<Text>("TextMsg").text); | 同传统Unity代码 |
优点 | 性能好 | 代码精简,无需在代码里定义数据 | 从传统Unity代码升级方便, 原则上仅需在Start或Awake里绑定即可. 性能上比方式1好一些 |
缺点 | 非热更新 | 频繁获取或修改的性能较差 | 代码量会多一些 |
GameObject的直接使用GetGameObject("ButtonStart")来代替.
特别地:绑定其他基类为LikeBehaviour的对象的方式:
var obj = HotUpdateBehaviour.GetComponentByType(GetGameObject("XXXXX"), typeof(ExampleInteractivePrefabData)) as ExampleInteractivePrefabData;
在Awake里绑定其他基类为LikeBehaviour的对象时候,可能对象为空,因为该对象尚未初始化,需要要移到Start里绑定!
- 如何访问预制体或场景里绑定的资源,例如TextAsset/Material/Texutre/AudioClip/Sprite
传统Unity代码MonoBehaviour | 热更新代码LikeBehaviour方式1 | 热更新代码LikeBehaviour方式2 | |
---|---|---|---|
定义 | public TextAsset LoadTextAsset; | 无需定义 | 同传统Unity代码 |
预制体设置 | 设置LoadTextAsset为拖放的文本资源文件 | "Text Assets",新加Key为Key为LoadTextAsset,Value为拖放的文本资源文件 | 同方式1 |
预绑定 | 无 | 无 | 在Start或Awake函数内绑定 LoadTextAsset = GetTextAsset("LoadTextAsset"); |
读取 | 直接使用TextMsg,例如 Debug.Log(LoadTextAsset.text); | Debug.Log(GetTextAsset("LoadTextAsset").text); | 同传统Unity代码 |
优点 | 性能好 | 代码精简,无需在代码里定义数据 | 从传统Unity代码升级方便, 原则上仅需在Start或Awake里绑定即可. 性能上比方式1好一些 |
缺点 | 非热更新 | 频繁获取或修改的性能较差 | 代码量会多一些 |
非热更新代码如何调用热更新代码:
- 假设我们热更新代码有个类,该类是非热更新代码想要访问的
namespace CSharpLike
{
public class HotUpdateClassBridge : LikeBehaviour
{
public int Add(int a, int b)
{
return a + b;
}
}
}
- 我们必须先确保热更新脚本已经初始化完毕 (即已经调用过'yield return ResourceManager.LoadCode();')
- 我们非热更新的代码任意位置像如下调用:
HotUpdateBehaviour.GetHotUpdateBridge().MemberCall("Add", 1, 2);
//默认的类名叫'CSharpLike.HotUpdateClassBridge',如果你调用'CSharpLike.XXXXX'类的函数'void YYYY()'你可以这样子调用
//HotUpdateBehaviour.GetHotUpdateBridge("CSharpLike.XXXXX").MemberCall("YYYY");
- 注意:这个类里的函数你就当做是静态
热更新代码如何调用非热更新代码:
- 这个没有什么限制,热更新的代码可以任意调用非热更新的代码.
本系列文章导读:
- 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(廿六)-(可选)详解免费版的演示如何升级到完整版的演示