C#Like是Unity的热更方案,使用纯C#语言写出可以热更新的代码,就像可以在所有平台使用DLL(动态链接库)文件一样.遵从KISS设计原则,让用户轻松构建或升级成Unity的热更新项目.
本篇主要介绍C#Like如何和Unity交互:
假设我们热更新代码里有个类,继承于LikeBehaviour,里面有若干MonoBehaviour的生命周期函数,然后在预制体或场景里想要绑定这个类,就像该类就是继承于MonoBehaviour一样.
using System;
using UnityEngine;
using UnityEngine.UI;
namespace CSharpLike
{
///
/// 热更脚本和Unity交互数据的例子
///
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()来获取的Unity组件.
//例如Image/Button/Slider/MeshRenderer/...等等
Text text = GetComponent("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("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");//关闭自身
}
}
}
using UnityEngine;
namespace CSharpLike
{
///
/// 这个HotUpdateBehaviour是额外带"OnApplicationFocus/OnApplicationPause/OnApplicationQuit"的.
/// "Awake/OnEnable/Start/OnDisable/OnDestroy"是由基类HotUpdateBehaviour带上了.
/// (更多的生命周期详见Unity官网: https://docs.unity3d.com/ScriptReference/MonoBehaviour.html).
///
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");
}
}
}
传统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好一些 |
缺点 | 非热更新 | 频繁获取或修改的性能较差 | 代码量会多一些 |
传统Unity代码MonoBehaviour | 热更新代码LikeBehaviour方式1 | 热更新代码LikeBehaviour方式2 | |
---|---|---|---|
定义 | public Text TextMsg; | 无需定义 | 同传统Unity代码 |
预制体设置 | 设置LoadTextAsset为拖放的文本资源文件 | "Text Assets",新加Key为Key为LoadTextAsset,Value为拖放的文本资源文件 | 同方式1 |
预绑定 | 无 | 无 | 在Start或Awake函数内绑定 TextMsg = GetComponent |
读取 | 直接使用TextMsg,例如 Debug.Log(TextMsg.text); |
Debug.Log(GetComponent |
同传统Unity代码 |
优点 | 性能好 | 代码精简,无需在代码里定义数据 | 从传统Unity代码升级方便, 原则上仅需在Start或Awake里绑定即可. 性能上比方式1好一些 |
缺点 | 非热更新 | 频繁获取或修改的性能较差 | 代码量会多一些 |
GameObject的直接使用GetGameObject("ButtonStart")来代替.
特别地:绑定其他基类为LikeBehaviour的对象的方式:
var obj = HotUpdateBehaviour.GetComponentByType(GetGameObject("XXXXX"), typeof(ExampleInteractivePrefabData)) as ExampleInteractivePrefabData;
在Awake里绑定其他基类为LikeBehaviour的对象时候,可能对象为空,因为该对象尚未初始化,需要要移到Start里绑定!
传统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;
}
}
}
HotUpdateBehaviour.GetHotUpdateBridge().MemberCall("Add", 1, 2);
//默认的类名叫'CSharpLike.HotUpdateClassBridge',如果你调用'CSharpLike.XXXXX'类的函数'void YYYY()'你可以这样子调用
//HotUpdateBehaviour.GetHotUpdateBridge("CSharpLike.XXXXX").MemberCall("YYYY");