Unity热更新方案C#Like(十八)-详解如何和Unity交互

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即可.
  1.  创建一个预制体叫SampleInteractivePrefabData
  2. 如下图上部,里面包含1个Text组件(msg)和1个返回按钮(back,里面的OnClick组件绑定HotUpdateBehaviour.OnClick事件,参数写OnClickBack)和1个开始按钮(buttonStart,里面的OnClick组件绑定HotUpdateBehaviour.OnClick事件,参数填OnClick(456,"xyz"),即点击该按钮的时候相当于执行代码 OnClick(456,"xyz"); 一样)
  3. 如下图的下部,选中SampleInteractivePrefabData节点后,在Inspector面板添加组件HotUpdateBehaviour.然后设置该组件:
  4. 设置"Integers",新加一个Key为iValueA,Value为123的,即相当于MonoBehaviour脚本"public int iValueA;"绑定一个数值123一样
  5. 设置"Game Objects",新加Key为ButtonStart,Value为拖放buttonStart节点,即相当于MonoBehaviour脚本"public GameObject ButtonStart;"拖放buttonStart节点绑定一样.
  6. 设置"Game Objects",新加Key为TestMsg,Value为拖放msg节点,即相当于MonoBehaviour脚本"public Text TextMsg;"拖放msg节点绑定一样.
  7. 设置"Text Assets",新加Key为Key为LoadTextAsset,Value为拖放的文本资源文件,即相当于MonoBehaviour脚本"public TextAsset LoadTextAsset;"拖放文本资源文件绑定一样.
  8. 最后,设置绑定的完整类名:"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");  
  • 注意:这个类里的函数你就当做是静态

热更新代码如何调用非热更新代码:

  • 这个没有什么限制,热更新的代码可以任意调用非热更新的代码.

 本系列文章导读:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

C#Like

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

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

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

打赏作者

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

抵扣说明:

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

余额充值