Unity-资源引用自动化工具

2019-08-18 23:07:22 浏览数 (1)

需求: 在实际项目中,往往我们需要在代码中引用一些子节点的GameObject或者Component,这些引用在代码中是写死的,然而在项目开发中美工人员需要在迭代的时候调整子节点的层级、顺序,这对程序来说代码将难以维护。 此时我们需要一个自动化工具,用于检查代码中使用子节点引用的代码,这些引用是否还可以正确引用,对于无法正确引用的组件、游戏物体进行警告提示。

实现思路: 基于上述需求,来进行分析

  • 使用一个配置文件,将引用存入一个结构体
  • 实现一个解析器,将配置文件中的结构体,通过键值的方式让键与具体的对应引用对应与,使用时使用解析器提供的方法,将键作为参数
  • 实现一个Unity编译器拓展的方法,遍历全部的Prefab,并找到其对应的_prefab.lua的配置文件,遍历其中的结构体并进行解析,将无法引用的失效路径输出警告

1.解析器的实现 使用多态的特性,让不同的解析器继承一个基类

代码语言:javascript复制
local parserBase = {}
function parserBase:Find()
    print("parserBase Find")
end
function parserBase:New(o)
    o = o or {}
    self.__index = self
    setmetatable(o, self)
    return o
end

不同类型解析器的具体实现,这里列举一个按钮解析器。按钮解析器继承解析器基类,根据根节点和路径找到子物体,在查找是否有对应的UI.Button组件。最后将解析器(方法)添加进入parsers的表中。

代码语言:javascript复制
local buttonParser = parserBase:New()
function buttonParser:Find(transform, path)
    local child = transform:Find(path)
    if child ~= nil then
        local btn = child:GetComponent(UI.Button)
        if btn ~= nil then
            Debug.Log("Success Find Button")
            return btn
        else
            Debug.LogWarning("Cant Find UI.Button Component: " .. gameObject.name .. "/" .. path)
        end
    else
        Debug.LogWarning("Cant Find GameObject: " .. gameObject.name .. "/" .. path)
    end
end
parsers["buttonParser"] = buttonParser.Find

2.配置文件的定义 配置文件中存放引用,键为一个自定义的名称,值为一个表,包括解析器使用哪个,子物体的路径。

代码语言:javascript复制
local parsers = require "CustomParser"

local commonPanelTable = {
    ["expBarButton"] = {parser = parsers.buttonParser, path = "Viewport/Content/ExperienceBar/Button"},
    ["TitleBar"] = {parser = parsers.goParser , path = "Viewport/Content/TitleBar",subStruct = require "TitleBar_prefab"},
    ["TitleBar_Transform"] = {parser = parsers.goParser , path = "Viewport/Content/TitleBar"},
}
return commonPanelTable

在一个结构下面可能有嵌套的结构,嵌套的结构为一个表,此表的结构和正常的一样

代码语言:javascript复制
local parsers = require "CustomParser"

local titleBarTable = {
    ["Text"] = {parser = parsers.textParser, path = "Text"},
}
return titleBarTable

3.通过解析器,解析一个配置文件,通过传入一个根节点和一个配置文件的table,得到一个可以直接通过索引直接使用的table

代码语言:javascript复制
function PrefabLuaParserTable:Parser(transform, prefabTab)
    local outputTab = {}

    for k, subTab in pairs(prefabTab) do
        local prefabSubTab = subTab
        outputTab[k] = prefabSubTab:parser(transform, prefabSubTab.path)
        if subTab.subStruct ~= nil then
            local subTransform = outputTab[k]
            outputTab[k] = self:Parser(subTransform, subTab.subStruct)
        end
    end
    return outputTab
end

具体使用实例

代码语言:javascript复制
local parserTab = self:Parser(commonPanel.transform, require "CommonPanel_prefab")
local cusText = parserTab["TitleBar"]["Text"]

4.编译器拓展,遍历全部的prefab,并找到其对应的_prefab.lua文件 调用上面的解析方法,来判断是否有引用已经无法使用了。

代码语言:javascript复制
function PrefabLuaParserTable:TraversePrefab(relativePath)
    local parserTool = LuaCallCSTool.StaticIT()
    local files = parserTool:FindAllPatternFiles("t:Prefab")

    for i = 1, #files do
        local go = parserTool:LoadAssetToGameObject(files[i])
        local parserTool = LuaCallCSTool.StaticIT()
        local prefabLuaFileName = relativePath .. go.name .. "_prefab"
        if io.open(prefabLuaFileName..".lua","r") then
            local prefabTab = require(prefabLuaFileName)
            if prefabTab ~= nil then
                print(go.name)
                local parserTab = self:Parser(go.transform, prefabTab)
            end
        end
    end
end

0 人点赞