一、Lua语言学习
二、ToLua框架
三、使用ToLua框架对Lua&C#进行交互

四、使用Lua对GameObj进行操作
五、将游戏对象打包&解包
六、将Lua脚本文件进行打包&解包

七、热更新实践
八、使用服务器进行热更新

一、Lua语言学习

Lua是很轻量级的脚本语言,Table也是个很神奇的东西,前面刚开始看的时候以为是Python(╯▔皿▔)╯废话不多说,是菜鸟就点进去吧 Lua菜鸟教程

二、ToLua框架

1.ToLua下载及安装

TuLua下载地址:TuLua
下载后解压并使用Unity以新项目打开,文件加载后进入项目里会有提示是否自动生成常用类型注册文件,点击确定:

现在已经进入TuLua框架了

2.TuLua框架认识

Unity菜单栏里多了Lua选项

资源包里有一下几个文件夹:

1.Editor:里面只有一个CustomSettingsC#脚本,这个脚本是自定义配置文件,相当于一个注册文件,将我们C#类、委托等在里面进行注册后,Lua就能和C#交互了。
2.Lua:存放Lua脚本的一个文件夹,可以把Lua脚本文件放进里面。
3.Plugins:插件目录
4.Source:LuaConst.cs–Lua路径存在的一些配置文件 Generate文件夹:存放一些在CustomSettings里面注册后生成的绑定代码脚本,这些脚本就是将Lua和C#进行绑定交互的。
5.ToLua:
BaseType:基础类型绑定代码
Core:ToLua提供的一些核心功能
Examples:Tolua实例代码,提供学习基础用
Mic:杂项
Reflection:反射相关代码

三、使用ToLua框架对Lua&C#进行交互

尝试在输出面板上使用Lua&C#交互并输出“HelloWorld”:

先创建一个Scripts文件夹,再创建2个脚本LuaTest.cs和Mian.cs

LuaTest.cs:创建一个函数,放回字符串

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LuaInterface;public class LuaTest : MonoBehaviour
{public static string TestPrint(){return "Hello World";}
}

然后把LuaTest.cs这个脚本在前面所说的CustomSettings脚本里面去进行注册:

在上图函数进行注册导出:我在函数最末端进行了注册导出

然后点击Unity菜单栏的Lua–>clear warp files,随后会自动弹出是否重新自动生成类型注册,点击确定:

在Source-Generate里面就会生成我妈注册后的交互文件:可以不用管他,现在可以使用Lua对C#进行调用了

在Lua文件夹里面创建一个Lua文件:Test.Lua

打开,可以用专门的Edit打开,也可以用记事本打开,由于我没去下载Edit,我就用记事本了,输入以下代码:

local h = LuaTest.TestPrint() //因为LuaTest这个类上面已经ToLua导出,所以Lua可以直接调用并接收返回值。
print(h)//将字符串输出

之后,我们在之前创建的Mian.cs里面对这个Lua脚本进行调用:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LuaInterface;public class Main : MonoBehaviour
{private LuaState lua = null;\\创建一个虚拟机void Start(){//调用Lua必定的步骤开始:new LuaResLoader();//加载Lua文件lua = new LuaState();//虚拟机初始化lua.Start();//开始虚拟机LuaBinder.Bind(lua);//绑定虚拟机//调用Lua必定的步骤结束。lua.DoFile("Test.lua");//调用运行Test.Lua脚本}
}

将此脚本挂载在场景里,开始:

已将字符串输出。

以上就是实现Lua&C#交互的基本步骤。

Lua语言挺简洁的,很容易看懂,要是使用的是热更新对游戏进行开发,那岂不是所有的逻辑处理都得到Lua里进行,而C#这边的文件基本要保持不变,虽然过程繁琐,但是熟悉了也就清晰了。Lua的Table很神奇,组合了数据和哈希表,还能当类使用。那么问题来了,怎么用Lua对Unity实现更多操作啊,后续看吧。

四、使用Lua脚本对GameObj进行操作

目标:使用Lua对场景的Sphere进行控制

创建场景,Sphere,Plane

创建Lua脚本Controller.lua:

controller = {}             --//创建一个类
local this  = controller   --//模拟C#中的this--//对Unity中的类和方法进行加载
local GameObject = UnityEngine.GameObject
local Input = UnityEngine.Input
local Rigidbody = UnityEngine.Rigidbody
local Color = UnityEngine.Colorlocal Sphere
local rigi
local force--//模拟Unity中Start方法
function this.Start()Sphere = GameObject.Find("Sphere")Sphere : GetComponent("Renderer").material.color = Color(0.1,1,1)Sphere : AddComponent(typeof(Rigidbody))rigi = Sphere : GetComponent("Rigidbody")force = 5
end--//模拟Unity中Update方法
function this.Update()local h = Input.GetAxis("Horizontal")local v = Input.GetAxis("Vertical")rigi : AddForce(Vector3(h,0,v)*force)
end

创建C#脚本Controller.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LuaInterface;public class Controller : MonoBehaviour
{private LuaState lua = null;private LuaFunction luaFunc = null;      //创建一个存放Lua类里面函数的载体void Start(){new LuaResLoader();lua = new LuaState();lua.Start();LuaBinder.Bind(lua);lua.DoFile("Controller.lua");CallFunc("controller.Start"); //调用下面CallFunc函数去调用Controller.lua脚本中的Start函数}private void Update(){CallFunc("controller.Update");//调用下面的CallFunc函数}void CallFunc(string func){luaFunc = lua.GetFunction(func);//此处的func因该为lua脚本中的table类的名字,而不是lua脚本文件名的名字luaFunc.Call();//开始调用Lua脚本里面的函数}
}

将Controller.cs挂载在Sphere上,运行Uinty,Sphere成功改变颜色,并且有了Rigidbody,也可对小球进行移动控制。

以上的两个脚本,Lua脚本Controller.lua模拟了unity的Start和Update函数,且这两个函数在C#脚本Controller.cs中被对应的Start和Update调用,实现了lua处理逻辑,c#调用,从而实现了更新时只更改Lua脚本,不更改C#脚本的功能,从而可以实现热更新。

五、将游戏对象打包&解包

1.重新创建一个场景AssertBundleTest,创建一个Sphere,做成预制体:

2.点击预制体:在右下角可以设置生成的AssertBundle的名字和后缀:假设我们要生成sphere.uinity3d:

3.创建打包生成AssertBundle的脚本:在Editor里创建一个脚本CreateAssetBundle.cs

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Windows;public class CreateAssetBundle
{[MenuItem("AssetBundle/Build AssetBundles")]//在菜单栏创建新选项,点击执行下面函数static void BuildAssetBundle(){string streamPath = Application.streamingAssetsPath;//保持包的路径if (Directory.Exists(streamPath))//若包路径存在,删除掉Directory.Delete(streamPath);Directory.CreateDirectory(streamPath);//创建新的包路径AssetDatabase.Refresh();//刷新BuildPipeline.BuildAssetBundles(streamPath, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);//开始打包:参数1.打包路径,参数2.打包格式,参数3.打包平台}
}

4.编译脚本,在菜单栏中点击AssetBundle–>Build AssetBundles,会生成如下文件:

总共生成4个文件,我们打开文件夹看看:


以上就是打包后的结果。

5.将打包的sphere.unity3d进行解包:创建C#脚本LoadAssetBundle.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Windows;public class LoadAssetBundle : MonoBehaviour
{void Start(){string path = Application.streamingAssetsPath + "/sphere.unity3d";//要解包的资源路径AssetBundle myAssetBundle = AssetBundle.LoadFromMemory(File.ReadAllBytes(path));//加载解包Object[] obj = myAssetBundle.LoadAllAssets<GameObject>();//遍历包里的所有OBJforeach (var o in obj)Instantiate(o);//实例化}
}

删除掉场景中的sphere,将上面脚本挂载在相机,运行,资源被解包了:

解包的方式有4中:
(1).LoadFormMemory:从内存中加载
(2).LoadFormFile:从本地加载
(3).WWW:从本地或服务器加载
(4).UnityWebRequest:从服务器端加载
根据不同需求可以对选择不同的加载方式。

6.打包中的依赖关系:
我们给5中创建的sphere加一个材质,就用我的证件照吧,创建Textures文件夹,将我的图片放进去:

拖进Sphere,自动生成Materials,我们将Textures中的me和Materials中的me打包在一起:


名字一样就可打包在一起。
然后AssetBundle–>Build AssetBundles,生成以下文件:

多了me.unity3d,打开看下:

包含了me.png和me.mat。
再看看sphere.unity3d:

增加了依赖:me.unity3d。
这就是他们的依赖关系,一旦有依赖,就会在Dependencies中表示出来。

7.对有依赖关系的物体进行解包:
若我对有依赖关系的sphere直接解包,会生成以下模样,会没有材质贴图:

所以我要先对他的依赖进行解包,再对sphere解包:修改一下解包的脚本:LoadAssetBundle.cs:
1.加载总依赖资源包StreamingAssets
2.根据名称找到加载目标的依赖项
3.加载所有依赖项资源

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Windows;public class LoadAssetBundle : MonoBehaviour
{void Start(){string path = Application.streamingAssetsPath + "/sphere.unity3d";AssetBundle myAssetBundle = AssetBundle.LoadFromMemory(File.ReadAllBytes(path));Object[] obj = myAssetBundle.LoadAllAssets<GameObject>();LoadDependencies();//解包依赖项foreach (var o in obj)Instantiate(o);}void LoadDependencies(){string path = Application.streamingAssetsPath + "/StreamingAssets";//获取总依赖性资源包路径AssetBundle assetBundle = AssetBundle.LoadFromFile(path);//加载总依赖项资源包AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");//获取资源包依赖信息string[] DependenciesName = manifest.GetAllDependencies("sphere.unity3d");//获取shhere.unitye3d的依赖项foreach (var name in DependenciesName)AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + name);//加载解包依赖项}
}

实现了有依赖关系的加载

六、将Lua脚本文件进行打包&解包

尝试将一、中的的Lua脚本Controller.lua进行打包:
再设置AssertBundle名字的时候出现这个错误

原因是Unity是无法识别Lua文件,需要更改下Lua文件后缀,将其改为Controller.lua.bytes
重新AssetBundle–>Build AssetBundles:已有Lua的AssetBundle生成:

由于Lua的后缀是bytes,所以解包的时候要进行处理:修改下LoadAssetBundle:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Windows;public class LoadAssetBundle : MonoBehaviour
{void Start(){string path = Application.streamingAssetsPath + "/sphere.unity3d";AssetBundle myAssetBundle = AssetBundle.LoadFromFile(path);Object[] obj = myAssetBundle.LoadAllAssets<GameObject>();LoadDependencies();foreach (var o in obj)Instantiate(o);LoadLua();//加载Lua文件}void LoadDependencies(){string path = Application.streamingAssetsPath + "/StreamingAssets";AssetBundle assetBundle = AssetBundle.LoadFromFile(path);AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");string[] DependenciesName = manifest.GetAllDependencies("sphere.unity3d");foreach (var name in DependenciesName)AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + name);}void LoadLua(){string path = Application.streamingAssetsPath + "/lua.unity3d";AssetBundle assetBundle = AssetBundle.LoadFromFile(path);TextAsset text = assetBundle.LoadAsset("Controller.lua") as TextAsset;if(File.Exists(Application.dataPath + "/Lua/Controller.lua")){File.Delete(Application.dataPath + "/Lua/Controller.lua");}File.WriteAllBytes(Application.dataPath + "/Lua/Controller.lua", text.bytes);}
}

将一、中的Controller.cs挂载到二、中的预制体里,将LoadAssetBundle挂载在相机,点击运行:
运行的时候,LoadAssetBundle.cs将Lua文件Controller.lua从AssetBundle中加载出来,也将挂载了Controller.cd的sphere加载出来,从而可以控制sphere行走,实现了Lua文件的解包。

七、热更新实践

将三、中的Lua脚本文件,预制体,材质和贴图都删掉:

点击开始后:

依然有小球生成,这个小球就是从AssetBundle包生成出来的,若我们将AssetBundle存放在服务器里,就可以进行热更新了。

八、使用服务器进行热更新

参考了:
https://blog.csdn.net/u013617851/article/details/81945906, https://blog.csdn.net/linxinfa/article/details/88246345

在Jarjin的LuaFramword_UGUI框架里,有实现从服务器进行热更新的放下,下载下来实践一下:

把Build好的AssetBundle放进服务器软件:

把本地的StreamingAssers删掉,先运行下看看:

出错,没有资源包,我们把热更新的资源包地址更改下,改为我服务器的地址:在LuaFramework/Scrips/ConstDefine/AppConst.cs下修改:

重新运行游戏:

服务器也被访问了:

我看一下他是怎么去实现从服务器端进行热更新的:
在LuaFrameWork.GameManager里面,每次一开始运行游戏的时候,都会执行

在Init()里,有释放资源动作,其中就有更新资源包的功能,他会去加载StreamingSetting里面的file.txt文档,进行文件检查,看是否本地缺少文件,如果缺少文件,就会自动下载更新:

从开始学习Lua的基本语法,达到能看懂Lua代码的目的,到学习使用tolua框架,已经初步了解了此框架的大概用法。现在学的东西都很基础,等后面熟悉了再去看看这个框架的结构和原理。

Unity热更新ToLua框架学习相关推荐

  1. [Unity热更新]tolua# LuaFramework(七):lua使用DOTween

    相关链接: http://blog.csdn.net/u010665359/article/details/50950989 http://blog.csdn.net/u010665359/artic ...

  2. Unity热更新机制

    前言 游戏上线后,难免会有一些测试阶段没发现的bug,bug这东西,可大可小. 如果出现重大bug,而又没有热更技术,那么我们为了修复bug就只能强制玩家去商店下载新包,那造成的玩家流失是非常可怕的. ...

  3. C# 实现 rtc_通过Xlua实现unity热更新的一个小例子

    通过Xlua实现unity热更新的一个小例子 一.介绍 ​ 热更新是指在更新游戏资源或者逻辑的时候不需要开发者将游戏再打包.发布.玩家重新下载安装包,而是可以通过将需要更新的资源打包成AssetBun ...

  4. unity案例 mysql lua_通过Xlua实现unity热更新的一个小例子

    通过Xlua实现unity热更新的一个小例子 一.介绍 ​ 热更新是指在更新游戏资源或者逻辑的时候不需要开发者将游戏再打包.发布.玩家重新下载安装包,而是可以通过将需要更新的资源打包成AssetBun ...

  5. [Unity热更新]04.卸载方式

    [Unity热更新]04.卸载方式 参考链接: https://www.jianshu.com/p/b37ee8cea04c 1.AssetBundle.Unload(false):释放AssetBu ...

  6. unity热更新json_unity3d热更新插件uLua学习整理

    前言IOS不能热更新,不是因为不能用反射,是因为 System.Reflection.Assembly.Load 无法使用 System.Reflection.Emit 无法使用 System.Cod ...

  7. Unity热更新技术学习——AssetsBundle详解

    文章目录 热更新 AssetsBundle Resources AssetsBundle 存储目录 目录实例 构建AssetsBundle 清单文件 AB包 AssetBundle依赖 AssetBu ...

  8. Unity 热更新方案之——ILRuntime

    文章目录 前言 一.ILRuntime是什么? 二.ILRuntime使用 1.跨域委托 2.跨域继承 3.CLR绑定与重定向 前言 做游戏离不开热更新,目前市面上热更新方案用的比较多的是Lua(XL ...

  9. Unity热更新方案探索与讨论

    热更新必要性 App Store审核周期长 应用更新频繁 更新版本对留存数据有很大影响 Lua相关 Lua:脚本,解释性语言 LuaJit:扩展高效版本,支持编译成二进制代码. Tolua++:C/C ...

最新文章

  1. 不该建索引及不走索引的原因
  2. delphi dbgrid 焦点 行号_火箭VS爵士领衔,多场焦点对决!今日NBA全部比赛视频直播预告...
  3. spark集群测试小案例
  4. 【转】Android 4.4前后版本读取图库图片和拍照完美解决方案
  5. php 类静态变量 和 常量消耗内存及时间对比
  6. shell--6、Shell printf 命令
  7. mysqlbinlog 查看binlog时报错unknown variable 'default-character-set=utf8'
  8. 收藏一些常用下载地址
  9. 计算机网络的功能分布计算,网络中心的分布计算(转帖)
  10. Git学习笔记(九) 历史穿梭
  11. 机器学习算法之SVM的多分类
  12. 台式计算机可以连接蓝牙吗,台式电脑可以连接蓝牙音响吗
  13. ModifyStyle()调用不起作用
  14. c语言大赛评分用数组,C语言大赛现场评分系统
  15. 怎么用计算机程序求根公式,一元四次方程求根公式
  16. 2017.9.29 红红火火恍恍惚惚
  17. 一个懒鬼胡乱写的多解
  18. 一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如,6的因子为1,2,3,而6=1+2+3,因此6是“完数”。编程序找出1000之内的所有完数,并输出其因子。
  19. 屏蔽烦人的百度搜索热点
  20. vostro3470装win7_dell latitude3470怎么安装win7系统

热门文章

  1. onunload,onbeforeunload,load事件
  2. 云原生周刊 | 美国国防部发布零信任战略与路线图
  3. insetSelective 和insert的区别
  4. 数字孪生技术实现和案例
  5. 计算机网络自顶向下方法 第二章套接字编程作业 邮件客户 答案
  6. linux 挂载新硬盘
  7. Linux系统磁盘的挂入和装载
  8. APP软件开发定制返利网分销商城APP
  9. 写交织(AXI4不在支持写交织功能)
  10. 车联网的信息安全问题及安全威胁