引擎内嵌Lua脚本对象开发

您可以直接在编辑器内为应用对象实例绑定您的Lua逻辑脚本。现在可以支持的实例绑定对象有:世界Actor特定类型的节点。 引擎对象内嵌脚本对象可以解决如下情形:

  • 场景已被创建,并且希望直接对场景内物体便捷地附加一些脚本运行逻辑。
  • 对特定的场景对象(例如蒙太奇/过场动画实例对象)中的指定节点实例附加一些脚本运行逻辑。

编辑器会将lua脚本通过xscript资产文件管理的方式, 保存到磁盘上。 读入内存时, 每个脚本节点会为编辑器lua脚本生成一个code_entity的lua表对象,该表对象会在运行时被压入Lua栈中,并自动执行绑定对象的相应方法。例如OnHolderEnterance, OnHolderRelease, OnHolderTick, OnHolderRender为这个绑定Actor的脚本对象生成时、释放时Actor在Tick时Actor在Render时的方法代理。 特别地, 在OnHolderEnterance中,场景中的(其他)Actor对象可能还没有创建到场景中,因此,如果您希望在入口函数中查找场景中的某个Actor时,您需要在OnHolderTick中查找, 并通过变量设置只查找一次。

现在我们尝试为这个绑定的Actor绕Y轴进行旋转:

--this function will be called each tick after the ticking of the holder.
function code_entity:onHolderTick(actor, interval)
    -- rotate speed is pi/s
    local rotateSpeed = math.pi * interval / 1000.0
    actor:RotateY(rotateSpeed)
end

OnHolderTick中查找一次场景中的其他Actor, 并保存入self.actors表中:

--this function will be called each tick after the ticking of the holder.
function code_entity:onHolderTick(actor, interval)
    if not self.__first_find_actor_done then
        self.__first_find_actor_done = true
        local level = actor:GetLevelOwner()
        self.actors = {
            level:FindActor(ActorName1ThatYouWant),
            level:FindActor(ActorName2ThatYouWant),
            ...
        }
    end
end

这里我们尝试对这个绑定的Actor进行绕Y轴旋转操作,旋转角速度为pi每秒。输入的interval单位是毫秒,因此这里我们需要除以1000转化为秒。 点击主面板中的“播放”按钮,即可查看运行结果。打开”视图->显示->Lua日志“,即可查看Lua虚拟机运行您的绑定脚本时所输出的日志。如下: こんにちは、じゃ、まだね。为您好、再见的意思。输出这句话时,表明您绑定的Lua脚本代码已成功运行。

1. 绑定对象规范

1.1. 明确需要绑定的脚本对象

您可以通过为世界Actor特定类型的节点创建并绑定您的内嵌脚本。 一般地, 如果场景业务包含多个子场景(LevelScene), 我们建议您在游戏场景中对Actor进行绑定。游戏场景可以直接被游戏世界以Level的形式加载,所有Actor会存在在Level中。此时,您不能在游戏场景中绑定世界, 目前尚不支持直接将世界中的脚本绑定转换为对应Level的绑定。

绑定Actor时, holderActor, OnHolderEnterance, OnHolderRelease, OnHolderTick, OnHolderRender的接口方法定义为

 -- actor.entrance
local code_entity = {}

 -- this function will be called once when the binding holder is ready to work.
function code_entity:onHolderEntrance(script_ins, actor)
end

-- this function will be called once when the binding holder is ready to release.
function code_entity:onHolderRelease(actor)
end

-- this function will be called each tick after the ticking of the holder.
function code_entity:onHolderTick(actor, interval)
end

-- this function will be called each tick after the rendering of the holder.
function code_entity:onHolderRender(actor, viewport)
end

您可以通过actor来获取工作场景Level, 并在Level中创建您需要创建的Actor:

function code_entity:onHolderEntrance(script_ins, actor)
    local level = actor:GetLevelOwner()
    local newActor = level:CreateActor(SomeActorType, SomeActorName)
    print("The level is", level:GetLevelName())
end

当您需要新创建一个Actor时,我们建议您在具体的Level中创建,而不是在World中。在World中创建Actor, Actor将会被World的默认Level管理,这可能会导致您想控制的Level并不包含您新创建的Actor,从而无法通过您的Level进行管理(例如删除您的Level并不能删除掉您直接使用World创建的Actor)

总结

  • 1.游戏场景可以以"Level"形式加载到World中,作为World中的一个子场景, 此时建议您绑定Actor。
  • 2.新创建一个Actor时,我们建议您在具体的Level中创建, 而不是在World中。

绑定World时, holderWorld, OnHolderEnterance, OnHolderRelease, OnHolderTick, OnHolderRender的接口方法定义为

 -- world.entrance
local code_entity = {}

 -- this function will be called once when the binding holder is ready to work.
function code_entity:onHolderEntrance(script_ins, world)
end

-- this function will be called once when the binding holder is ready to release.
function code_entity:onHolderRelease(world)
end

-- this function will be called each tick after the ticking of the holder.
function code_entity:onHolderTick(world, interval)
end

-- this function will be called each tick after the rendering of the holder.
function code_entity:onHolderRender(world, viewport)
end

总结

  • 1.当世界中不存在需要专门处理的Actor,或者您想全局处理世界中的Actor时,可以通过绑定World来进行脚本绑定。
  • 2.如果您的场景有可能作为子场景以Level的形式加载时,当前对World的绑定将会丢失。此时您应考虑通过绑定Actor的形式进行脚本绑定。

1.2. 使用编辑器的脚本编辑器进行脚本对象绑定

1.2.1. 为Actor绑定脚本

点击"Actor"的属性选项卡-> 点击想要绑定的"Actor" -> 点击Actor的属性数据面板中的"编辑绑定脚本"。

1.2.2. 为世界绑定脚本

点击"World"的属性选项卡-> 点击World的属性数据面板中的"打开和绑定脚本"。

2. 内嵌脚本资产的文件位置放置规范

2.1. xscript 对象

xscript对象管理了world/actor/usernode所绑定的1个或者多个lua脚本。绑定后,xscript/lua文件对象请不要再挪动到其他位置,否则将会找不到。因此,您需要考虑好这些脚本对象资产应该放在哪里。 点击绑定脚本按钮即可打开 或者 创建 一个xscript对象,并放置到您所设置的位置上。

2.2. lua代码文件

您需要创建一个脚本节点,然后点击脚本节点属性面板中的"创建新的代码文件”,或者选择一个已经存在的Lua脚本进行脚本关联。如下:

在lua代码中,您可以require其他lua脚本文件,同理,您也应该考虑这些代码文件应该放到您的工程的什么位置。 lua代码文件可以被多个xscript绑定对象复用。 如果您在编辑器中进行调试,您可以点击“运行世界”按钮,这些Lua绑定脚本只会在运行时世界中生效,如下:

require使用的Lua文件由于lua的require机制,当lua代码文件已经加载时,并不会复生加载,因此,您在编辑器中对require的lua代码文件进行修改后,您需要删除Lua中放置require的表数据,才能重新加载您修改后的lua文件。您可以参考如下方法删除 require表数据:

--[[
  Lua的require(modelname)把一个lua文件加载存放到package.loaded[modelname]中,
  重复require同一个模块实际还是沿用第一次加载的chunk。
  在复用一个lua实例栈的环境下,如果想要修改代码文件,又不想重启Lua实例,可强制去掉require方法中的模块索引, 请在Lua实例启动入口处调用该方法
  注意:本方法如需要热更新,只能重启Lua实例了
  链接:https://www.jianshu.com/p/015c41bfb7d0
]]

--代码热更方法处理, 本方法不可热更
local hotFix = {}

--构造函数
function hotFix:clean(package_contain_path)
  print("ready to construct hot_fix! current packages:")
  local pcp = package_contain_path or "Asset"
  for k,v in pairs(package.loaded) do
    print(k,v)
  end
  while true do
    local found = false
    for k,v in pairs(package.loaded) do
      if type(k) == "string" then
        if string.find( k,pcp) and v ~= self then 
          print("require cache ".." wtih:" .. pcp .. " fixed =>", k, v)
          package.loaded[k] = nil
          found = true
          break
        end
      end
    end
    if not found then break end--not any more
  end
end

--类型字符串
function hotFix:__tostring()
    return "hot_fix"
end

return hotFix

3. 项目资源目录定义相关建议

编辑器的基本资源目录结构如下:

Root
|---Asset
       |----fx
       |----GameAssets
|---YourProject.project
|---YourScene.xscene
|---SequenceFrameDefaultDir(2D序列帧图片文件夹)

3.1. 引擎实例单一游戏项目

对于单一引擎实例游戏项目,资源管理相对简单,我们建议您就以基本资源目录结构进行组织和管理即可。如果有多场景,请以/Asset/为相对路径进行放置,即将场景及相关游戏资源放到Asset目录下。资源文件一旦定下来后如果需要挪动位置,请在编辑器内挪动。请尽量不要更改资源的位置。

3.2. 引擎实例直播多场景项目

在引擎的直播业务上,资源加载需求较为复杂。现在,一个引擎直播效果对应一个完整的引擎资源包,并且存在同时加载多个引擎资源包的需求。建议您在使用MagicCubeEditor制作素材资源的时候,遵循以下文件目录结构:

Root
|---Asset
       |----YourProjectName
                 |----fx
                 |----GameAssets
|---YourProject.project
|---YourScene.xscene
|---SequenceFrameDefaultDir(2D序列帧图片文件夹)

即在Asset下多一层以项目名称命名的目录YourProjectName, 然后将素材资源,包括Lua代码资源放到此目录下。这样可以保证在多个引擎资源搜索路径下,素材按项目加载时的正确性,否则可能会命中其他相同的相对路径,从而导致效果加载错误或者失败。

@Copyright © cosmos 2019 all right reserved,powered by Gitbook修订时间: 2021-04-12 18:28:14

results matching ""

    No results matching ""