动态编程和Lua热更新

文章目录

    • 前言
    • 动态读取程序集实现热更新
    • Lua和Untiy的交互
    • Lua脚本的热更新

前言

计算机语言有动态和静态之分,静态语言主要是像C和C++之类的语言。

特点:需要预先编译为目标机器代码,CPU才能正确执行其指令。

动态语言,通常称为脚本

特点:运行在其他语言实现的程序中,不需要预先编译,而是在程序运行的过程中实时编译,因此具有很强的灵活性

C#和Java是比较特殊的语言,需要编译,但不是编译成机器代码,而是一种中间语言,在程序运行时,再由运行时程序将其编译成目标代码

特点:性能上略有一定损失,但更加高效、安全,相比动态语言性能卓越,语法健壮,无法真正实时编译

动态语言的最大优势:热更新,也就是不重新编译程序,只更新某一部分实现对内容的更新。游戏公司对游戏留了一些接口,能让玩家对发布的游戏内容进行自行修改,类似于创意工坊,就比如说人气游戏《饥荒》联机版的Mod层出不穷,一定程度上来说,这些Mod也成为了游戏的一部分,让《饥荒》这一款游戏做到了时时新,难以过时。这方面使用比较多的技术就是Lua,可以看到饥荒的很多Mod文件都是.Lua 结尾的。

Lua是一门很小巧的语言,真正做到了动态实时编译,可以运行在其他语言之中,因此Lua也被称为嵌入式语言

动态读取程序集实现热更新

通俗来说,也就是动态调用编译好的程序集,也就是**.dll文件**,这样在程序发布后,只需要更新.dll文件,即可实现对程序内容的更新。

(ps:IOS平台不支持)

创建.dll文件

//在解决方案管理器中右键引用,添加引用,选择浏览,添加入整个UnityEngine文件夹
using UntiyEngine;
namespace UntiyDll{
    public class Myplugin:MonoBehaviour
    {
        //release生成.dll文件后,只需要放入Unity工程项目的Assets文件夹下的Plugins文件夹中,具体再放哪个文件夹看这个网址
        //https://blog.csdn.net/linxinfa/article/details/102978005
        
 	}
}

在Untiy中测试热更新.dll文件

void Start()
{
    //运行时,会自动生成一个脚本挂载到物体上
    this.gameObject.AddComponent();
}

通过反射访问.dll文件

using System.Reflection;
//在untiy中做热更新,通常会把需要更新的内容放到Untiy的StreamingAssets路径下,此时必须用文件读取的方式读取.dll,然后通过反射执行.dll文件提供的功能
void Start()
{
	byte[] bs=System.IO.File.ReadAllBytes(Application.streamingAssetsPath+"/UnityDLL.dll");
    Assembly ass=Assembly.Load(bs);
    System.Type t =ass.GetType("UntiyDll.MyPlugin");//通过反射获取MyPlugin类
    //多出来的步骤就是,通过文件读取程序集,然后再通过反射获取类
    Component myPlugin=this.gameObject.AddComponent(t);
}
//实现热更新,主要是通过网络下载需要更新的文件,保存到API中的一个可写的路径中,程序先访问Application.dataPath指向的路径,如果目标文件不存在,再到StreamingAssets中读取默认文件

Lua和Untiy的交互

新建Unity工程,在Untiy store中下载MoonSharp插件并导入

新建lua脚本,保存在StreamingAssets路径下

function fun()
    print("hello,lua");
    return "hello,lua";
end

在Untiy工程中创建脚本LuaManager.cs

using MoonSharp.Interpreter;

void Start()
{
	Script luaScript=new Script();//创建lua解释器
	string luaPath=System.IO.Path.Combine(Application.streamingAssetsPath,"test.lua");//获取文件路径
	string luatxt=System.IO.File.ReadAllText(luaPath);//读取脚本
	DynValue dyn=luaScript.DoString(luatxt);//用解释器运行Lua脚本
	DynValue lua_fuc=luaScript.Globals.Get("fun");//查找函数
	DynValue result=luaScript.Call(lua_fuc);//调用函数
	Debug.Log(result.ToObject());//输出lua函数返回值
	
}

将Untiy功能导入lua

static GameObject CreateGameObject(string name)
{
    return new GameObject(string);
}

UserData.RegisterType();//注册静态类Debug
UserData.RegisterType();
UserData.RegisterType();
UserData.RegisterType();

luaScript.Globals["Debug"]=typeof(Debug);
luaScript.Globals["GameObject"]=(System.Func)CreateGameObject;

Lua脚本的热更新

  1. Lua脚本或AssetBundle数据包存放在HTTP服务器
  2. 客户端,将lua脚本存放到StreamingAssets路径
  3. 客户端运行后,先比对本地和服务器的版本是否一致,如果相同,到Application.dataPath指向的路径下查找Lua脚本,如果不存在,则使用StreamingAssets中默认的脚本
  4. 如果版本号不一致,则下载服务器最新的lua脚本,存储到Application.dataPath指向的路径下,读取最新的Lua脚本
WWW www=new WWW("http://xxxxx/test.lua");//使用HTTP协议下载lua
string luatxt=www.text;//获取Lua脚本的字符串
//代替上面获取文件路径和读取脚本

你可能感兴趣的:(C#,c#,c++,开发语言,lua)