打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
【新提醒】【Unity热更新专题(八)uLua示例Demo简析及SimpleFramework工作流程】
  我们在进行热更新的完整案例之前。有必要分析一下uLua的实例代码,了解一下SimpleFramework工作流程,在我们制作实例时便于理解。

  1、LuaState

[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using UnityEngine;
using System.Collections;
using LuaInterface;
public class HelloWorld : MonoBehaviour {
// Use this for initialization
void Start () {
LuaState l = new LuaState();
string str = "print('hello world 世界')";
l.DoString(str);
}
// Update is called once per frame
void Update () {
}
}



  这个示例代码中就使用了LuaState。

  2、LuaScriptMgr

[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using UnityEngine;
using System.Collections;
using LuaInterface;
public class CreateGameObject02 : MonoBehaviour {
private string script = @"
luanet.load_assembly('UnityEngine')
GameObject = UnityEngine.GameObject
ParticleSystem = UnityEngine.ParticleSystem
local newGameObj = GameObject('NewObj')
newGameObj:AddComponent(ParticleSystem.GetClassType())
";
//非反射调用
void Start () {
LuaScriptMgr lua = new LuaScriptMgr();
lua.Start();
lua.DoString(script);
}
// Update is called once per frame
void Update () {
}
}



  这个示例代码中就使用了LuaScriptMgr。

  上面的两个示例中,要注意一下的代码:

[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
private string script = @"
luanet.load_assembly('UnityEngine')
GameObject = UnityEngine.GameObject
ParticleSystem = UnityEngine.ParticleSystem
local newGameObj = GameObject('NewObj')
newGameObj:AddComponent(ParticleSystem.GetClassType())
";



  大概工作流程就是先加载UnityEngine,然后创建一个GameObject变量,再调用AddComponent方法。其实就和Unity里面使用的差不多。很简单。不多说。

  3、在Unity中访问Lua中的变量

[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
using UnityEngine;
using System.Collections;
using LuaInterface;
public class AccessingLuaVariables01 : MonoBehaviour {
private string script = @"
luanet.load_assembly('UnityEngine')
GameObject = luanet.import_type('UnityEngine.GameObject')
ParticleSystem = luanet.import_type('UnityEngine.ParticleSystem')
particles = {}
for i = 1, Objs2Spawn, 1 do
local newGameObj = GameObject('NewObj')
local ps = newGameObj:AddComponent(luanet.ctype(ParticleSystem))
ps:Stop()
table.insert(particles, ps)
end
var2read = 42
";
void Start () {
LuaState l = new LuaState();
l["Objs2Spawn"] = 5;            //就是这里
l.DoString(script);
print("Read from lua: " + l["var2read"].ToString());
LuaTable particles = (LuaTable)l["particles"];
foreach( ParticleSystem ps in particles.Values )
{
ps.Play();
}
}
void Update () {
}
}



  4、执行Lua脚本文件,调用Lua方法,在Lua中使用协程

[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using UnityEngine;
using System.Collections;
using LuaInterface;
public class ScriptsFromFile_01 : MonoBehaviour
{
public TextAsset scriptFile;
// Use this for initialization
void Start()
{
LuaState l = new LuaState();
l.DoString(scriptFile.text);
}
// Update is called once per frame
void Update()
{
}
}



  而我们的File文件就是在同目录下的与类同名的txt文件。




  注意,我们这里定义的File文件,是TextAsset类型。

[AppleScript] 纯文本查看 复制代码
public TextAsset scriptFile;



  接下来就是调用Lua的方法。也很简单。

[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using UnityEngine;
using System.Collections;
using LuaInterface;
public class CallLuaFunction_01 : MonoBehaviour {
private string script = @"
function luaFunc(message)
print(message)
return 42
end
";
void Start () {
LuaState l = new LuaState();
l.DoString(script);
LuaFunction f = l.GetFunction("luaFunc");
object[] r = f.Call("I called a lua function!");
print(r[0]);
}
void Update () {
}
}



  协程的使用:

[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using UnityEngine;
using System.Collections;
using LuaInterface;
public class LuaCoroutines : MonoBehaviour
{
private string script = @"
function fib(n)
local a, b = 0, 1
while n > 0 do
a, b = b, a + b
n = n - 1
end
return a
end
function CoFunc()
print('Coroutine started')
local i = 0
for i = 0, 10, 1 do
print(fib(i))
coroutine.wait(1)
end
print('Coroutine ended')
end
function myFunc()
coroutine.start(CoFunc)
end
";
private LuaScriptMgr lua = null;
void Awake ()
{
lua  = new LuaScriptMgr();
lua.Start();
lua.DoString(script);
LuaFunction f = lua.GetLuaFunction("myFunc");
f.Call();
f.Release();
}
void Update ()
{
lua.Update();
}
void LateUpdate()
{
lua.LateUpate();
}
void FixedUpdate()
{
lua.FixedUpdate();
}
}



  好了。uLua的示例代码我们就分析到这里了。接下来的可以自己琢磨,对于我们的案例来说已经够了。下面我们来分析一下自带热更新的案例的工作流程。也就是我们的SimpleFramework的工作流程。

  5、框架启动GlobalGenerator,生成appview和gamemanager

  在这里我们首先要看一下框架的目录。

  整个SimpleFramework采用的是PureMVC的框架。看下图。




  GlobalGenerator.cs

[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using UnityEngine;
using System.Collections;
namespace SimpleFramework {
/// <summary>
/// 全局构造器,每个场景里都有,所以每个场景都会初始化一遍,也会初始化游戏管理器一次
/// 如果游戏管理器已经存在了,就跳过了,否则创建游戏管理器,来保证游戏里只有一个GameManager
/// </summary>
public class GlobalGenerator : MonoBehaviour {
void Awake() {
InitGameMangager();
}
/// <summary>
/// 实例化游戏管理器
/// </summary>
public void InitGameMangager() {
string name = "GameManager";
gameObject.AddComponent<AppView>();
GameObject manager = GameObject.Find(name);
if (manager == null) {
manager = new GameObject(name);
manager.name = name;
AppFacade.Instance.StartUp();   //启动游戏
}
}
}
}



  这段代码就是我们热更新的入口。

  这里GlobalGenerator的任务就完成了。

  appview和gamemanager都是框架相关的东西。这里我们就只对GameManager进行分析。

  6、GameManager中对资源的更新处理及处理Lua的View的加载和初始化

  GameManager的功能就如这个标题所说。

  代码中也有详细注释。

  我们就不贴代码了。

  我们关注一下GameManager组件下的脚本。




  然后。我们要重点分析Lua文件夹下的Lua脚本。




  GameManager.cs:

  ①加载所有Lua脚本

[AppleScript] 纯文本查看 复制代码
1
2
public LuaScriptMgr uluaMgr;
private List<string> downloadFiles = new List<string>();



  ②初始化


[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
void Init() {
DontDestroyOnLoad(gameObject)//防止销毁自己
CheckExtractResource(); //释放资源
Screen.sleepTimeout = SleepTimeout.NeverSleep;
Application.targetFrameRate = AppConst.GameFrameRate;
}



  我们可以看看AppConst.cs文件,里面主要是一些配置。

[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
namespace SimpleFramework {
public class AppConst {
public const bool DebugMode = false;                       //调试模式-用于内部测试
/// <summary>
/// 如果想删掉框架自带的例子,那这个例子模式必须要
/// 关闭,否则会出现一些错误。
/// </summary>
public const bool ExampleMode = true;                       //例子模式
/// <summary>
/// 如果开启更新模式,前提必须启动框架自带服务器端。
/// 否则就需要自己将StreamingAssets里面的所有内容
/// 复制到自己的Webserver上面,并修改下面的WebUrl。
/// </summary>
public const bool UpdateMode = false;                       //更新模式-默认关闭
public const int TimerInterval = 1;
public const int GameFrameRate = 30;                       //游戏帧频
public const bool UsePbc = true;                           //PBC
public const bool UseLpeg = true;                          //LPEG
public const bool UsePbLua = true;                         //Protobuff-lua-gen
public const bool UseCJson = true;                         //CJson
public const bool UseSproto = true;                        //Sproto
public const bool LuaEncode = false;                        //使用LUA编码
public const string AppName = "SimpleFramework";           //应用程序名称
public const string AppPrefix = AppName + "_";             //应用程序前缀
public const string ExtName = ".assetbundle";              //素材扩展名
public const string AssetDirname = "StreamingAssets";      //素材目录
public const string WebUrl = "http://localhost:6688/";      //测试更新地址
public static string UserId = string.Empty;                 //用户ID
public static int SocketPort = 0;                           //Socket服务器端口
public static string SocketAddress = string.Empty;          //Socket服务器地址
}
}



  ④资源初始化结束

[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public void OnResourceInited() {
LuaManager.Start();
LuaManager.DoFile("Logic/Network");      //加载游戏
LuaManager.DoFile("Logic/GameManager");   //加载网络
initialize = true;
NetManager.OnInit();    //初始化网络
object[] panels = CallMethod("LuaScriptPanel");
//---------------------Lua面板---------------------------
foreach (object o in panels) {
string name = o.ToString().Trim();
if (string.IsNullOrEmpty(name)) continue;
name += "Panel";    //添加
LuaManager.DoFile("View/" + name);
Debug.LogWarning("LoadLua---->>>>" + name + ".lua");
}
//------------------------------------------------------------
CallMethod("OnInitOK");   //初始化完成
}



  我们看到熟悉的字眼了。

[AppleScript] 纯文本查看 复制代码
1
2
LuaManager.DoFile("Logic/Network");      //加载游戏
LuaManager.DoFile("Logic/GameManager");   //加载网络



  这正是我们Lua文件夹Logic文件夹下的脚本,我们来看看这两个脚本。

  Network.lua文件主要是网络相关的文件,我们就不分析了,重点看GameManager.lua。它相当于Lua脚本文件的起点。

[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
require "3rd/pblua/login_pb"
require "3rd/pbc/protobuf"
local lpeg = require "lpeg"
local json = require "cjson"
local util = require "3rd/cjson.util"
local sproto = require "3rd/sproto/sproto"
local core = require "sproto.core"
local print_r = require "3rd/sproto/print_r"
require "Logic/luaclass"
require "Logic/CtrlManager"
require "Common/functions"
require "Controller/PromptCtrl"



  文件相关。不解释。

[AppleScript] 纯文本查看 复制代码
1
2
GameManager = {};
local this = GameManager;



  单例。你懂的。

[AppleScript] 纯文本查看 复制代码
1
2
3
4
function GameManager.LuaScriptPanel()
return 'Prompt', 'Message';
end



  返回我们的UI相关类。

  我们结合两个文件一起看。


[AppleScript] 纯文本查看 复制代码
1
2
3
4
function GameManager.LuaScriptPanel()
return 'Prompt', 'Message';
end



[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
object[] panels = CallMethod("LuaScriptPanel");
//---------------------Lua面板---------------------------
foreach (object o in panels) {
string name = o.ToString().Trim();
if (string.IsNullOrEmpty(name)) continue;
name += "Panel";    //添加
LuaManager.DoFile("View/" + name);
Debug.LogWarning("LoadLua---->>>>" + name + ".lua");
}



  这两段代码是相关联的。


[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
local transform;
local gameObject;
PromptPanel = {};
local this = PromptPanel;
--启动事件--
function PromptPanel.Awake(obj)
gameObject = obj;
transform = obj.transform;
this.InitPanel();
warn("Awake lua--->>"..gameObject.name);
end
--初始化面板--
function PromptPanel.InitPanel()
this.btnOpen = transform:FindChild("Open").gameObject;
this.gridParent = transform:FindChild('ScrollView/Grid');
end
--单击事件--
function PromptPanel.OnDestroy()
warn("OnDestroy---->>>");
end



[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
local transform;
local gameObject;
MessagePanel = {};
local this = MessagePanel;
--启动事件--
function MessagePanel.Awake(obj)
gameObject = obj;
transform = obj.transform;
this.InitPanel();
warn("Awake lua--->>"..gameObject.name);
end
--初始化面板--
function MessagePanel.InitPanel()
this.btnClose = transform:FindChild("Button").gameObject;
end
--单击事件--
function MessagePanel.OnDestroy()
warn("OnDestroy---->>>");
end



  这两段代码得以执行。初始化UI界面。

  这里有个疑问?初始化界面是怎么得以实现的?

  其实也很简单,结合工程来看:

  这是初始化后得到的界面。




  其实我们早就把界面打包成Prefab了。




  对,就是这么来的,每个prefab对应生成AssetBundle。达到热的目的。

  好多啊。写得挺乱的。将就着看吧。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
ToLua SimpleFramework NGUI/UGUI基础知识[2]
[Unity XLua]热更新XLua入门(二)-俄罗斯方块实例篇
使用Unity制作3D无尽跑酷游戏(下)
让你的游戏支持热更新 - 在Unity3D中使用lua
toLua与Xlua使用方法总结
使用Unity创建塔防游戏
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服