[ゲーム開発の回答]Unityはluaを使用してテーブルをツリー構造に変換し、マルチレベルの折りたたみコンテンツリストUIの形式で表示します(ツリー構造| UGUI|折りたたみと展開|lua)

この記事の最終的な効果
画像の説明を追加してください

I.はじめに

みなさん、こんにちは。私は新しいです。
ファンからこの質問がありました。
ここに画像の説明を挿入
プレーンテキストのデータを取得したと思いましたが、解析方法がわかりませんでした。データを解析したいだけなら、ツリーを使用する必要はまったくありませんでした。
フォーマットを見ると、yes 、プレーンテキストデータを取得し、フォーマットがyesluaの場合、メソッドを使用してプレーンテキストを実行し、オブジェクトを取得できます。次に例を示します。tableluatableloadstringtable

local data_str = '{ a = 1, b = 2, { c=3, d = 4}, { e = { x = 5 }}}'
local func = loadstring('return ' .. data_str)
local tb = func()
-- TODO 解析tb这个table

ここで注意しなければならないのは、バージョン以降でloadstringメソッドがlua 5.2変更されているloadため、バージョン以上の場合lua5.2注意が必要ですlua。ソースコードlbaselib.cファイルを表示できます。
ここに画像の説明を挿入ここに画像の説明を挿入
実際、彼の意味を誤解して送ってくれました。別のデータ
ここに画像の説明を挿入
そしてそれをこの形で示すと言われました、
ここに画像の説明を挿入

このフォーマットはlua正しくありませんtable。この時点で、彼はWebページを作成していると思ったので、それを使用するかどうか尋ねましたjavascript
ここに画像の説明を挿入

確認後、使用されluaます。彼はそれを変換しましtableたが、ツリーを使用して再帰的トラバーサルを構築する方法がわかりません。
ここに画像の説明を挿入

最後に、私は彼が遭遇した問題を理解しました、まあ、良い人々は最後まで助けてくれます、それでは特定の実装について話しましょう〜

注:上記红点は、私が以前に書いた別の記事を参照しています。[ゲーム開発の実践] luaを使用してUnityにレッドドットシステムを実装する方法を教えます(プレフィックスツリー|データ構造|デザインパターン|アルゴリズム|プロジェクトソースコードを含む)

第二に、Unitylua環境

使いたいのでluaUnityデフォルトではフレームワークC#を作成する必要があります。ちょうどいいタイミングで、フレームワークを統合しluaたゲームフレームワークを自分で作成しました。詳しくは、以前書いたこのブログをご覧ください。 :[ゲーム開発フレームワーク]自家製Unity一般ゲームフレームワークUnityXFramework、詳細なチュートリアル(Unity3Dスキルツリー| tolua |フレームワーク|ホットアップデート)フレームワークオープンソースアドレス:https ://gitcode.net/linxinfa/UnityXFrameworkここでロジックを記述します環境のフレームワーク〜UnityXFrameworktolua

ここに画像の説明を挿入lua

3、ツリーノード

1.スクリプトを作成します:TreeNode.lua

まず、ディレクトリにLuaFramework/Lua/Logic新しいTreeディレクトリ
ここに画像の説明を挿入
を作成し、Treeディレクトリに新しいTreeNode.luaスクリプトを作成します。
ここに画像の説明を挿入

2.パッケージノード

まず、ノードが必要とする情報について考え、絵を描きます
ここに画像の説明を挿入
。次に、コードを書き留めます。TreeNode.luaスクリプトコードは次のとおりです。

-- TreeNode.lua 树节点

TreeNode = TreeNode or {
    
    }
TreeNode.__index = TreeNode

function TreeNode.New(name)
    local self = {
    
    }
    -- 节点名
    self.name = name
    -- 值
    self.value = nil
    -- 父节点
    self.parent = nil
    -- 子节点
    self.child = nil
    -- 缩进
    self.tab = 0

    -- 是否展开
    self.isopen = true
    -- UI对象
    self.uiObj = nil

    setmetatable(self, TreeNode)
    return self
end

第四に、ツリーロジック

1.スクリプトを作成します:TreeLogic.lua

次のように、Treeディレクトリに新しいTreeLogic.luaスクリプトを作成し、最初にメソッドを
ここに画像の説明を挿入
記述して、 1つ残しておきましょう。InitTODO

-- TreeLogic.lua 树逻辑

TreeLogic = TreeLogic or {
    
    }
local this = TreeLogic

-- 根节点
this.root = nil

-- 初始化
function TreeLogic.Init()
    -- TODO
    
end

2.テストデータを作成します

ツリーを構築する場合は、最初にデータを用意する必要があります。要件に応じて、データは1つtableであり、単に1つ書き込むだけです。

-- 测试数据
local data_table = {
    
    
    name = "林新发",
    university = "华南理工大学",
    major = '信息工程',
    job = 'Unity3D游戏开发工程师',
    blog = 'https://blog.csdn.net/linxinfa',
    hobby = {
    
    '吉他', '钢琴', '画画', '撸猫'},
    dream = {
    
    
        developer = {
    
    
            target = '成为一名优秀的独立游戏开发者',
            style = {
    
    'ARPG', 'FPS', 'SLG', 'MOBA'}
        },
        painter = {
    
    
            target = '成为一个独立画家',
            magnum_opus = {
    
    '暴走柯南', '皮皮猫', '光'}
        },
        musician = {
    
    
            target = '成为一个独立音乐人',
            magnum_opus = {
    
    '尘土', '树与风'}
        }
    }
}

3.ツリーの構築

次に、テストデータを使用してツリーを構築し、メソッドをカプセル化しますMakeTree。実際には、構築プロセス中にノードの構築に焦点を当て、ノードの名前と値を設定し、親子ノードを設定するだけで済みます。ノードの関係、そして再帰的に実行します。
コードは以下のように表示されます

-- TreeLogic.lua

-- 构造树
-- tb: 数据table
-- parent: 父节点
function TreeLogic.MakeTree(tb, parent)
    -- 遍历table
    for k, v in pairs(tb) do
        -- 新建一个节点
        local node = TreeNode.New(k)
        node.value = v
        -- 设置父节点
        node.parent = parent
        -- 子节点缩进+1
        node.tab = parent.tab + 1
        -- 父节点的child塞入node
        if nil == parent.child then
            parent.child = {
    
    }
        end
        parent.child[k] = node
        -- 如果v是table,则递归遍历
        if type(v) == 'table' then
            -- 有子节点,默认不展开
            node.isopen = false
            this.MakeTree(v, node)
        end
    end
    return parent
end

次に、メソッド内のメソッドをInit呼び出します。MakeTree

-- 初始化
function TreeLogic.Init()

    -- 测试数据 data_table = {}
    -- ...
        
    -- 根节点
    this.root = TreeNode.New("Root")
    -- 构造树
    this.root = this.MakeTree(data_table, this.root)
end

この時点で30、行の周りのコードを使用してノードのカプセル化とツリーの構築を完了しました。次のステップはUIツリーの表示です。

4.ツリーを印刷します

表示を行う前にUI、ツリーを印刷する方法をカプセル化して、ツリー構造を確認することもできます。

-- 把树转为字符串
function TreeLogic.TreeToString(node, str)
    if nil ~= node.value then
        local tabspace = ''
        for i = 1, node.tab do
            tabspace = tabspace .. '    '
        end
        if 'table' == type(node.value) then
            str = str .. string.format('%s▼ %s :\n', tabspace, node.name)
        else
            str = str .. string.format('%s● %s : %s\n', tabspace, node.name, tostring(node.value))
        end
    end

    if nil ~= node.child then
        for _, child_node in pairs(node.child) do
            -- 递归
            str = this.TreeToString(child_node, str)
        end
    end
    return str
end

電話しましょう

-- 打印树
local str = ''
str = this.TreeToString(this.root, str)
log(str)

出力は以下の通りです
ここに画像の説明を挿入
出力は正常です、どうぞよろしくお願いします〜

5番目に、UGUIを使用してツリーを表示します

1.インターフェースプリセットを作成します

次のようにTreePanel.prefabインターフェイスプリセットを作成します。インターフェイス階層は次のとおりです。コンポーネントを垂直レイアウトに使用します。これにより、子ノードを追加すると、自動的に垂直に配置され、そのうちの1つはクリックの監視に接続され、1つは子ノードになります。子ノードが1つあります。座標を右に移動することで実現できます。
ここに画像の説明を挿入

ここに画像の説明を挿入
VerticalLayoutGroup
ここに画像の説明を挿入
itemButtonTextText
ここに画像の説明を挿入

2.インターフェイススクリプトを作成します:TreePanel.lua

ディレクトリにフォルダLuaFramework/Lua/View作成し、スクリプトを作成し、インターフェイスコードを記述します。インターフェイスコードのテンプレートを作成しました。以前に作成したフレームワークチュートリアルを参照できます。[ゲーム開発フレームワーク]自家製Unity一般ゲームフレームワークUnityXFramework 、詳細なチュートリアル(Unity3Dスキルツリー| tolua |フレームワーク|ホットアップデート)セクション:ツリーノードを再帰的に拡張してノードを閉じるロジックを書き留めることに焦点を当てます〜TreeTreePanel.lua
ここに画像の説明を挿入
8.2
ここに画像の説明を挿入

3.ノードを展開します(再帰)

ノードを開くメソッドをカプセル化するために、ExpanNode再帰を使用し、コードにコメントを書き込んだので、ここでは説明しません。

-- TreePanel.lua

-- 展开节点
function TreePanel.ExpanNode(node)
    if nil == node.child then
        return
    end
    local index = 1
    for _, child_node in pairs(node.child) do
        -- 创建节点的UI对象
        local uiObj = LuaUtil.CloneObj(this.tiemForClone)

        local text = uiObj.transform:GetChild(0):GetComponent("Text")
        child_node.uiObj = uiObj

        if not LuaUtil.IsNilOrNull(node.uiObj) then
            -- 子节点塞在父节点下面
            local siblingIndex = node.uiObj:GetComponent("RectTransform"):GetSiblingIndex()
            child_node.uiObj:GetComponent("RectTransform"):SetSiblingIndex(siblingIndex + index)
            index = index + 1
        end
        if type(child_node.value) == 'table' then
            text.text = (child_node.isopen and '▼ ' or '► ') .. child_node.name
        else
            text.text = '● ' .. child_node.name .. ': ' .. child_node.value
        end
        -- 坐标缩进
        text.transform.localPosition = text.transform.localPosition + Vector3.New((child_node.tab-1)*50, 0,0)
        uiObj:GetComponent("Button").onClick:AddListener(function()
     
            if not child_node.isopen then
                child_node.isopen = true
                -- 递归, 展开子节点
                this.ExpanNode(child_node)
            else
                -- 关闭子节点
                this.CloseNode(child_node)
            end

            if type(child_node.value) == 'table' then
                text.text =  ( child_node.isopen and '▼ ' or '► ') .. child_node.name
            end
        end)
    end
end

ツリーのルートノードを渡す必要があります。メソッドをTreeLogic.lua追加します。GetTree

-- TreeLogic.lua

function TreeLogic.GetTree()
    return this.root
end

ExpanNode次に、次のようにメソッドを呼び出します。

local tree = TreeLogic.GetTree()
this.ExpanNode(tree)

4.ノードを閉じます(再帰的)

CloseNodeノードを閉じると、次のように、引き続き再帰を使用してメソッドもカプセル化されます。

-- 关闭子节点
function TreePanel.CloseNode(node)
    if LuaUtil.IsNilOrNull(node.child) then
        return
    end
    node.isopen = false

    for _, child in pairs(node.child) do
        child.isopen = false
        LuaUtil.SafeDestroyObj(child.uiObj)
        if nil ~= child.child then
            -- 递归关闭子节点
            this.CloseNode(child)
        end
    end
end

6.テスト

さて、効果をテストしましょう、画像の説明を追加してください
完璧です、それを1日と呼びましょう〜
私はフレームワークにコードを送信しました。レビューのためにプロジェクトをダウンロードできます、https://gitcode.net/linxinfa/UnityXFramework
ここに画像の説明を挿入

私はLinXinfaです。https:
//blog.csdn.net/linxinfa、小さな会社で静かにUnity働いている開発者Unityです。学びたい人をもっと助け、お互いを励まし合うことができればと思います〜

おすすめ

転載: blog.csdn.net/linxinfa/article/details/123549096