游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3083|回复: 0

【技术点】Unity的热更新sLua

[复制链接]

8717

主题

8783

帖子

1万

积分

版主

Rank: 7Rank: 7Rank: 7

积分
11952
发表于 2018-5-11 16:15:29 | 显示全部楼层 |阅读模式
文/邪让多杰

需求环境

在【解决方案系列】中,我们需要考虑到我们能预估的项目问题,在现有的工作习惯中,赶工期是常见的一种现象,而这种现象的后果,就导致了测试的不完全,线上项目bug的频繁出现。

为了对线上的BUG进行Fix,我们就需要一定的技术手段,甚至通过游戏初期架构去解决这个影响游戏质量的重要问题。

这是一篇【技术点】文章,同时吸取了之前一篇的文章,我们就不进行复杂的项目架构,只对技术点进行简单的介绍,其他有关但又与主题无关的内容,我们就浅浅跳过。

逻辑热更新

在以往的Unity版本中,有多种热更新的方案留存于世,从之前的uLua到C# Ligh,再到后来的Tolua,Slua等等,甚至早起的PlayMaker都能解决逻辑热更新的问题。

而本篇,基于作者项目在使用的情况,我们将会使用Slua作为我们【解决方案】系列的逻辑热更新方案。

而多种热更新语言的比较,大家可自行谷歌,也可通过该篇进行一定了解:http://blog.csdn.net/langresser_king/article/details/45112519

插件信息

1、插件网站:http://www.slua.net/

2、插件GitHub:https://github.com/pangweiwei/slua/wiki

在插件的GitHub中,有中文的帮助,我们只用简单的将插件导入到工程中,就可以开始使用了。为了让调试变得方便,我们需要进行一些小改动。

使用方法

在查看此节前,确保你已经查看了该插件的基础信息。

sLua加载:

在原生下载的sLua插件中,作者把Lua文件放在Resource目录中,并去掉了后缀名,在我使用的过程中,没有后缀名的文件无法被Vs有效识别,为了方便的调试,我们就需要进行一些准备工作。

sLua已经考虑到了这种情况,所以他提供了方便的接口,供给我们进行更改。

  1. ///


  2.     /// 从resouce目录加载Lua脚本,并初始化
  3.     ///
  4.     ///Resouce下的目录
  5.     ///是否强制读取
  6.     public SLua.LuaTable RsLoad(string _rsPath)
  7.     {
  8.         Log("加载:" + _rsPath);

  9.         if (mluasvr.inited == false)
  10.         {
  11.             Log("还未初始化,等待初始化后加载:" + _rsPath);
  12.             waitLoadLua= _rsPath;
  13.             return null;
  14.         }

  15.         if (luaDict.ContainsKey(_rsPath))
  16.             return luaDict[_rsPath];

  17.         //设置执行脚本
  18.         //LuaState ls_state = new LuaState();

  19.         //设置脚本启动代理
  20.         LuaState.loaderDelegate= ((string fn) =>
  21.         {
  22.             //获取Lua文件执行目录
  23.             string file_path = Directory.GetCurrentDirectory() + "/Assets/Resources/" + fn;

  24.             file_path= file_path.Replace('/', '\');
  25.             file_path= file_path.Replace('.', '\');


  26.             Log("准备加载脚本:" + file_path);

  27.             var file = File.ReadAllBytes(file_path + ".lua");

  28.             if (file == null)
  29.                 LogError("加载Lua脚本失败,不存在的Lua脚本");
  30.             else
  31.                 Log("加载脚本成功.文件大小:" + file.Length);

  32.             return file;
  33.         });

  34.         //通过刚才设置的代理方法加载,就会从Res目录下读取带.lua的文件了
  35.         var self = (LuaTable)mluasvr.start(_rsPath);
  36.         if (self != null)
  37.         {
  38.             luaDict.Add(_rsPath, self);
  39.             return self;
  40.         }

  41.         LogError("脚本初始化错误,脚本:" + _rsPath);

  42.         return null;
  43.     }
复制代码

有了上面这一段代码后,我们就可以直接从Resource目录下调用带有.lua后缀名的lua文件。

热调试:

在我们调试Lua文件时,我们不希望频繁重启客户端,因为Unity编译一次需要很久时间,所以如果可以动态的将已经加载好的Lua文件重新加载,我们就进行快速Lua逻辑调试。

在上面的代码中,为了确保效率,我们将Lua对象放到了LuaDict中,避免了重复调用,而函数本身是可以重新加载Lua文件的,所以我们只需要把Lua文件从Dict中清除就好。

  1. ///


  2.   /// 移除脚本,移除后,会重新加载,这样就可以热更新了。
  3.   /// 平时用缓存里的,性能就没那么差了
  4.   ///
  5.   public void UnstallLuaScripts()
  6.   {
  7.       luaDict.Clear();
  8.   }

  9.   ///
  10.   /// 卸载指定脚本
  11.   ///
  12.   ///脚本目录+名字
  13.   public void UnstallLuaScript(string _name)
  14.   {
  15.       if (luaDict.ContainsKey(_name))
  16.           luaDict.Remove(_name);
  17.   }
复制代码

该有一些其他初始化的过程,不过都是些逻辑问题,大家可以在DJLuaManager.cs文件中插件相关代码。

测试:

有了上面简单的加载代码后,我们就可以测试Lua脚本了。在工程的10-1sLuaTest 场景中,我们能找到测试工具TestTool,上面挂在了脚本Behavior3JSTest.cs ,这是我自己用来测试Lua代码的小脚本。

  1. using UnityEngine;
  2. using System.Collections;

  3. public class Behavior3JSTest : MonoBehaviour
  4. {

  5.     public bool 加载 = true;
  6.     public string loadFunction;
  7.     //"/DJLua/Behavior3Js/main"
  8.     public bool 运行一次 = false;
  9.     public string runFunction;
  10.     //testbt
  11.     public bool 循环执行 = false;
  12.     public string loopFunction;

  13.     void Update()
  14.     {
  15.         if (加载 == true)
  16.         {
  17.             加载 = false;
  18.             DoSomething();
  19.         }

  20.         if (运行一次 == true)
  21.         {
  22.             runOnce();
  23.             运行一次 = false;
  24.         }

  25.         if (循环执行 == true)
  26.         {
  27.             runex();
  28.         }
  29.     }

  30.     void DoSomething()
  31.     {
  32.         DJLuaManager.GetInstance().UnstallLuaScripts();
  33.         DJLuaManager.GetInstance().RsLoad(loadFunction);

  34.     }

  35.     void runOnce()
  36.     {
  37.         DJLuaManager.GetInstance().ExecuteFunc(loadFunction, runFunction);
  38.     }

  39.     void runex()
  40.     {
  41.         DJLuaManager.GetInstance().ExecuteFunc(loadFunction, loopFunction);
  42.     }
  43. }
复制代码

每次加载的时候会卸载之前的脚本,而每次点击运行一次的时候,就会执行指定的函数。而在界面上,则有方便调试的窗口供给我们输入内容。

php7KO3vG.1477388108.png

当我们输入了正确的信息后,就可以得到反馈的结果。

phpZ5rNNu.1477388120.png

而当我们修改了Lua代码后,只用点击加载,不用重启客户端,就可以看到执行的效果。

当然,还有一个小小的Lua代码,文件名字叫sLuaTest.lua:

  1. --
  2. -- User: John
  3. -- Date: 2016年10月1日 星期六 农历九月初一
  4. -- Des: lua的测试脚本

  5. local mClass = { }

  6. function main()
  7.     Debug.Log("我被加载了");
  8.     return mClass
  9. end

  10. -- 节点被单击
  11. function mClass:testClick()
  12.     Debug.Log("我被点击了")
  13. end
复制代码

结束语

这就是sLua在Unity3d中的快速搭建,因为是【技术点】文章,稍微介绍下,相信大家通过文档能快速搭建出自己的项目。

而对于Lua的熟悉,可以使用《Lua 语言 15 分钟快速入门》来解决前期问题。


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-6-20 04:35

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表