• xLua背包实践


    主要学习目标

    1.巩固学习的AB包+Lua语法+xLua解决方案的3部分知识
    2.学会Unity+Lua+VSCode环境调试
    3.学会Unity结合xLua进行游戏功能开发
    4.学会制作Lua文件迁徙小工具

    准备工作

    1.导入xlua

    将xlua文件夹下的Assets中的Plugins和XLua文件夹导入Unity

    2.ab包导入

    导入asset Bundle Browser,新版本中已经下架,可以在官方手册中通过git下载。

    设置如图

    3.导入ProjectBase

    4.导入相关lua文件

    5.C#Main以及Lua 的Main

    1. void Start()
    2. {
    3. LuaMgr.GetInstance().Init();
    4. LuaMgr.GetInstance().DoLuaFile("Main");
    5. }
    print("准备就绪")

    vscode环境搭建

    1.下载扩展

    (///快捷注释)

    (debugger for Unity)

    2.改变Unity启动的编辑器

    3.验证C#环境搭建成功

    跳出transfrom说明成功

    选择Attach to Unity即可开始调试

    4.lua环境搭建

    下载Emmylua扩展

    添加新的调试配置

    需要jdk1.8以上并设置环境变量

    设置好后就可以正常调试了。

    主面板拼凑

    Canvas设置

    背包面板拼凑

    加上toggleGroup组件

    记得给每个tog的group指定

    左对齐

    格子面板拼凑

    效果

    预设体图样

    常用类别名准备

    新建InitClass.lua

    1. --常用别名都在这里定位
    2. --准备我们之前导入的脚本
    3. --面向对象
    4. require("Object")
    5. --字符串拆分
    6. require("SplitTools")
    7. --Json解析
    8. Json = require("JsonUtility")
    9. --Unity相关的
    10. GameObject = CS.UnityEngine.GameObject
    11. Resources = CS.UnityEngine.Resources
    12. Transform = CS.UnityEngine.Transform
    13. RectTransform = CS.UnityEngine.RectTransform
    14. --图集对象类
    15. SpriteAtlas = CS.UnityEngine.U2D.SpriteAtlas
    16. Vector3 = CS.UnityEngine.Vector3
    17. Vector2 = CS.UnityEngine.Vector2
    18. --UI相关的
    19. UI = CS.UnityEngine.UI
    20. Image = UI.Image
    21. Button = UI.Button
    22. Text = UI.Text
    23. Toggle = UI.Toggle
    24. ScrollRect = UI.ScrollRect
    25. --自己写的C#脚本相关
    26. --直接得到AB包资源管理器的单例对象
    27. ABMgr = CS.ABMgr.GetInstance()

    Main.lua

    1. print("准备就绪")
    2. --初始化所有准备好的类别名
    3. require("InitClass")

    数据准备

    道具表配置

    生成json表,打包进AB包

    先编辑excel表

    icon命名参考下面图集,加Icon是为了区分其它图集,表明是Icon图集中的资源

    图集设置

    使用转json工具将excel表转为json(推荐bejson网站)

    注意有的转json网站会将数字用字符串表示,同时最后一行可能多了逗号或者多空一行。

    将json文件打成json ab包中,之前的预设体和icon图集打到ui包中

    之后就build。

    Lua读取json表及准备玩家数据

    Main.lua修改

    1. print("准备就绪")
    2. --初始化所有准备好的类别名
    3. require("InitClass")
    4. --初始化道具表信息
    5. require("ItemData")
    6. --玩家信息
    7. --1.从本地读取 本地存储 有PlayerPrefs和json或者二进制
    8. --2.网络游戏 从服务器读取
    9. require("PlayerData")
    10. PlayerData:Init()

    新建ItemData.lua

    1. --将json数据读取道lua中的表中进行存储
    2. --首先应该先把Json表 从AB包中加载出来
    3. --TextAsset 是InitClass中定义的TextAsset = CS.UnityEngine.TextAsset
    4. local txt = ABMgr:LoadRes("json","ItemData",typeof(TextAsset))
    5. --获取它的文本信息 进行json解析
    6. local itemList = Json.decode(txt.text)
    7. print(itemList[1]) --打印出一个table
    8. print(itemList[1].id .. itemList[1].name)
    9. --加载出来是一个像数组结构的数据
    10. --不方便我们通过 id 来获取里面的内容 所以 我们用一张新表 转存一次
    11. --而且这张表 在任何地方 都能被使用
    12. -- 一张用来存储道具信息的表
    13. -- 键值对形式 键是道具ID 值是道具表一行信息
    14. ItemData = {}
    15. for _, value in pairs(itemList) do
    16. ItemData[value.id] = value
    17. end
    18. for key,value in pairs(ItemData) do
    19. print(key,value.tips)
    20. end

    PalyerData.lua

    1. PlayerData = {}
    2. --目前只做背包功能 所以只需要它们的道具信息
    3. PlayerData.equips = {}
    4. PlayerData.items = {}
    5. PlayerData.gems = {}
    6. --为玩家数据写一个 初始化方法后 以后直接改这里的数据来源即可
    7. function PlayerData:Init()
    8. --道具信息 不管存本地 还是服务器 都不会把道具的所有信息存起来
    9. --道具ID和数量
    10. --目前因为没有服务器 为了测试 就写死道具数据作为玩家数据
    11. table.insert(self.equips,{id = 1, num = 1})
    12. table.insert(self.equips,{id = 2, num = 1})
    13. table.insert(self.items,{id = 3, num = 50})
    14. table.insert(self.items,{id = 4, num = 30})
    15. table.insert(self.gems,{id = 5, num = 99})
    16. table.insert(self.gems,{id = 6, num = 88})
    17. end

    主面板逻辑

    编写MainPanel.lua

    1. --只要是一个新的对象(面板) 我们就新建一张表
    2. MainPanel = {}
    3. --不是必须写 因为lua的特性 不存在声明变量的概念
    4. --这样写的目的 是当别人看到这个lua代码时 知道这个表(对象)有什么变量很重要
    5. --关联的面板对象
    6. MainPanel.panelObj = nil
    7. --对应的面板控件
    8. MainPanel.btnRole = nil
    9. MainPanel.btnSkill = nil
    10. --需要做 实例化面板对象
    11. --为这个面板 处理对应的逻辑 比如按钮点击等等
    12. --初始化该面板 实例化对象 控件事件监听
    13. function MainPanel:Init()
    14. --面板对象没有实例化过 才去实例化
    15. if self.panelObj == nil then
    16. --1.实例化面板对象 ABMgr + 设置父对象
    17. self.panelObj = ABMgr:LoadRes("ui","MainPanel",typeof(GameObject))
    18. self.panelObj.transform:SetParent(Canvas,false)
    19. --2.找到对应控件
    20. --找到子对象 再找到身上挂载的 想要的脚本
    21. self.btnRole = self.panelObj.transform:Find("btnRole"):GetComponent(typeof(Button))
    22. print(self.btnRole)
    23. --3.为控件加上监听事件 进行点击等等逻辑处理
    24. --以下方法,如果直接传入自己的函数 那么在函数内部 没办法用self获取内容
    25. --self.btnRole.onClick:AddListener(self.BtnRoleClick)
    26. self.btnRole.onClick:AddListener(function ()
    27. self:BtnRoleClick()
    28. end)
    29. end
    30. end
    31. function MainPanel:ShowMe()
    32. self:Init()
    33. self.panelObj:SetActive(true)
    34. end
    35. function MainPanel:HideMe()
    36. self.panelObj:SetActive(false)
    37. end
    38. function MainPanel:BtnRoleClick()
    39. --print(123123)
    40. --print(self.panelObj)
    41. --等写了背包面板
    42. --在这写显示背包
    43. end

    更新Main.lua

    1. print("准备就绪")
    2. --初始化所有准备好的类别名
    3. require("InitClass")
    4. --初始化道具表信息
    5. require("ItemData")
    6. --玩家信息
    7. --1.从本地读取 本地存储 有PlayerPrefs和json或者二进制
    8. --2.网络游戏 从服务器读取
    9. require("PlayerData")
    10. PlayerData:Init()
    11. --之后的逻辑
    12. require("MainPanel")
    13. MainPanel:ShowMe()

    背包面板逻辑

    新建BagPanel.lua

    1. -- 一个面板 对应一个表
    2. BagPanel = {}
    3. --“成员变量”
    4. --面向对象
    5. BagPanel.panelObj = nil
    6. --各个控件
    7. BagPanel.btnClose = nil
    8. BagPanel.togEquip = nil
    9. BagPanel.togItem = nil
    10. BagPanel.togGem = nil
    11. BagPanel.svBag = nil
    12. BagPanel.Content = nil
    13. --“成员方法"
    14. --初始化方法
    15. function BagPanel:Init()
    16. if self.panelObj == nil then
    17. --1.实例化面板对象 ABMgr + 设置父对象
    18. self.panelObj = ABMgr:LoadRes("ui","BagPanel",typeof(GameObject))
    19. self.panelObj.transform:SetParent(Canvas,false)
    20. --2.找到对应控件
    21. --找到子对象 再找到身上挂载的 想要的脚本
    22. --关闭按钮
    23. self.btnClose = self.panelObj.transform:Find("btnClose"):GetComponent(typeof(Button))
    24. --3个toggle
    25. local group = self.panelObj.transform:Find("Group")
    26. self.togEquip = group:Find("togEquip"):GetComponent(typeof(Toggle))
    27. self.togItem = group:Find("togItem"):GetComponent(typeof(Toggle))
    28. self.togGem = group:Find("togGem"):GetComponent(typeof(Toggle))
    29. --sv相关svBag
    30. self.svBag = self.panelObj.transform:Find("svBag"):GetComponent(typeof(ScrollRect))
    31. self.Content = self.svBag.transform:Find("Viewport"):Find("Content")
    32. --3.为控件加上监听事件 进行点击等等逻辑处理
    33. --以下方法,如果直接传入自己的函数 那么在函数内部 没办法用self获取内容
    34. --self.btnRole.onClick:AddListener(self.BtnRoleClick)
    35. --关闭按钮
    36. self.btnClose.onClick:AddListener(function ()
    37. self:HideMe()
    38. end)
    39. --单选框事件
    40. --切页签
    41. --toggle 对应委托 是UnityAction
    42. self.togEquip.onValueChanged:AddListener(function (value)
    43. if value == true then
    44. self:ChangeType(1)
    45. end
    46. end)
    47. self.togItem.onValueChanged:AddListener(function (value)
    48. if value == true then
    49. self:ChangeType(2)
    50. end
    51. end)
    52. self.togGem.onValueChanged:AddListener(function (value)
    53. if value == true then
    54. self:ChangeType(3)
    55. end
    56. end)
    57. end
    58. end
    59. --显示隐藏
    60. function BagPanel:ShowMe()
    61. self:Init()
    62. self.panelObj:SetActive(true)
    63. end
    64. function BagPanel:HideMe()
    65. self.panelObj:SetActive(false)
    66. end
    67. --逻辑处理函数 用来切页签
    68. --type 1装备 2道具 3宝石
    69. function BagPanel:ChangeType(type)
    70. print("当前类型为".. type)
    71. --切页 根据玩家信息 来进行格子创建
    72. end

    新增内容MainPanel

    1. function MainPanel:BtnRoleClick()
    2. BagPanel:ShowMe()
    3. --print(123123)
    4. --print(self.panelObj)
    5. --等写了背包面板
    6. --在这写显示背包
    7. end

    新建CSharpCallLua.cs

    为了能xlua调用UnityAction

    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using XLua;
    6. public class CSharpCallLua
    7. {
    8. [CSharpCallLua]
    9. public static List cSharpCallLuaList = new List();
    10. //记得代码生成
    11. //目的是为了生成xlua代码 ???
    12. }

    可以参考https://blog.csdn.net/woodengm/article/details/112614506

    格子逻辑

    之前的MainPanel和BagPanel每次初始化都是一个表,只能表示一个对象

    而格子会有很多个则没法用这种做法做。

    粗暴的方法(后面有面向对象的方法)

    BagPanel更新

    1. ...
    2. --用来存储当前显示的格子
    3. BagPanel.items = {}
    4. BagPanel.nowType = -1
    5. ....
    6. --显示隐藏
    7. function BagPanel:ShowMe()
    8. self:Init()
    9. self.panelObj:SetActive(true)
    10. if self.nowType == -1 then
    11. self:ChangeType(1)
    12. end
    13. end
    14. ...
    15. --逻辑处理函数 用来切页签
    16. --type 1装备 2道具 3宝石
    17. function BagPanel:ChangeType(type)
    18. --如果已经是该页,就不更新
    19. if self.nowType == type then
    20. return
    21. end
    22. --切页 根据玩家信息 来进行格子创建
    23. --更新之前 把老的格子删掉 BagPanel.items
    24. for i = 1, #self.items do
    25. --销毁格子对象
    26. GameObject.Destroy(self.items[i].obj)
    27. end
    28. self.items = {}
    29. --再根据当前选择的类型 来创建新的格子 BagPanel.items
    30. --要根据传入的type 来选择显示的数据
    31. local nowItems = nil
    32. if type == 1 then
    33. nowItems = PlayerData.equips
    34. elseif type == 2 then
    35. nowItems = PlayerData.items
    36. else
    37. nowItems = PlayerData.gems
    38. end
    39. --创建格子
    40. for i = 1, #nowItems do
    41. --有格子资源 在这 加载格子资源 实例化 改变图片 和文本 以及位置
    42. local grid = {}
    43. --用一张新表 代表 各自对象 里面的属性 存储对应想要的信息
    44. grid.obj = ABMgr:LoadRes("ui","ItemGrid");
    45. --设置父对象
    46. grid.obj.transform:SetParent(self.Content,false)
    47. --继续设置它的位置
    48. grid.obj.transform.localPosition = Vector3((i-1)%4 * 175, math.floor((i-1)/4) * 175,0)
    49. grid.imgIcon = grid.obj.transform:Find("imgIcon"):GetComponent(typeof(Image))
    50. grid.Text = grid.obj.transform:Find("num"):GetComponent(typeof(Text))
    51. --设置它的图标
    52. --通过 道具id 去读取 道具配置表 得到图标信息
    53. local data = ItemData[nowItems[i].id]
    54. --想要的是data中的图标信息
    55. --根据名字 先加载图集 再加载图集中的 图标信息
    56. local strs = string.split(data.icon, "_")
    57. --加载图集
    58. local spritAtlas = ABMgr:LoadRes("ui",strs[1],typeof(SpriteAtlas))
    59. --加载图标
    60. grid.imgIcon.sprite = spritAtlas:GetSprite(strs[2])
    61. --设置它的数量
    62. grid.Text.text = nowItems[i].num
    63. --把他存起来
    64. table.insert(self.items,grid)
    65. --这里实现了显示逻辑,但每次切换type要记得把老格子删除,逻辑在上面
    66. end
    67. end

    优化格子对象

    前面虽然实现了格子的基本逻辑,但因为不是面向对象的实现方式,不能实现格子的各种功能,如果需要与格子进行交互,就只能再bagPanel里实现前面的方法就不可行。

    创建ItemGrid.lua

    1. --用到之前讲过的 GameObject
    2. --生成一个table 继承Object 主要目的是要它里面实现的 继承方法 subClass 和 new
    3. Object:subClass("ItemGrid")
    4. --"成员变量"
    5. ItemGrid.obj = nil
    6. ItemGrid.imgIcon = nil
    7. ItemGrid.Text = nil
    8. --成员函数
    9. --实例化格子对象
    10. function ItemGrid:Init(father,posX,posY)
    11. self.obj = ABMgr:LoadRes("ui","ItemGrid");
    12. --设置父对象
    13. self.obj.transform:SetParent(father,false)
    14. --继续设置它的位置
    15. self.obj.transform.localPosition = Vector3(posX,posY,0)
    16. --找控件
    17. self.imgIcon = self.obj.transform:Find("imgIcon"):GetComponent(typeof(Image))
    18. self.Text = self.obj.transform:Find("num"):GetComponent(typeof(Text))
    19. end
    20. --实例化格子对象
    21. --data 是外面传入的 道具信息 里面包含了 id 和 num
    22. function ItemGrid:InitData(data)
    23. --通过 道具id 去读取 道具配置表 得到图标信息
    24. local itemData = ItemData[data.id]
    25. --想要的是data中的图标信息
    26. --根据名字 先加载图集 再加载图集中的 图标信息
    27. local strs = string.split(itemData.icon, "_")
    28. --加载图集
    29. local spritAtlas = ABMgr:LoadRes("ui",strs[1],typeof(SpriteAtlas))
    30. --加载图标
    31. self.imgIcon.sprite = spritAtlas:GetSprite(strs[2])
    32. --设置它的数量
    33. self.Text.text = data.num
    34. end
    35. --初始化格子信息
    36. --加自己的逻辑
    37. function ItemGrid:Destroy()
    38. GameObject.Destroy(self.obj)
    39. self.obj = nil
    40. end

    修改BagPanel

    1. --更新之前 把老的格子删掉 BagPanel.items
    2. for i = 1, #self.items do
    3. --销毁格子对象
    4. self.items[i]:Destroy()
    5. end
    6. ...
    7. --创建格子
    8. for i = 1, #nowItems do
    9. --根据数据 创建一个格子对象
    10. local grid = ItemGrid:new()
    11. --要实例化对象 设置位置
    12. grid:Init(self.Content,(i-1)%4*175,math.floor((i-1)/4)*175)
    13. --初始化它的信息 数量 和 图标
    14. grid:InitData(nowItems[i])
    15. --把他存起来
    16. table.insert(self.items,grid)
    17. --这里实现了显示逻辑,但每次切换type要记得把老格子删除,逻辑在上面
    18. end
    19. end

    修改Main.lua

    1. ...
    2. --之后的逻辑
    3. require("MainPanel")
    4. MainPanel:ShowMe()
    5. require("BagPanel")
    6. require("ItemGrid")

    面板面向对象

    面板里有Init()等相同的函数或变量,可以创建面板基类

    新建BasePanel.lua

    1. --利用面向对象
    2. Object:subClass("BasePanel")
    3. BasePanel.panelObj = nil
    4. --相当于模拟一个字典 键为 控件名 值为控件本身
    5. BasePanel.controls = {}
    6. --用来判断是否已经初始化过了,因为父类的方法,子类不能用self.panelObj == nil 来判断
    7. --所以用这个变量来判断
    8. --作为事件监听标识
    9. BasePanel.isInitEvent = false
    10. function BasePanel:Init(name)
    11. if self.panelObj == nil then
    12. --公共的实例化对象的方法
    13. self.panelObj = ABMgr:LoadRes("ui",name,typeof(GameObject))
    14. self.panelObj.transform:SetParent(Canvas,false)
    15. --GetComponentsInChildren() 得到所有挂载的
    16. --找所有UI控件 存起来
    17. --所有UI控件都继承UIBehaviour
    18. local allControls = self.panelObj:GetComponentsInChildren(typeof(UIBehaviour))
    19. --如果存入没用的UI控件怎么办
    20. --为了避免找 各种无用控件 我们定一个规则 拼面板时 控件名按一定规则来
    21. --Button btn名字
    22. --Toggle tog名字
    23. --Image img名字
    24. --ScrollRect sv名字
    25. for i = 0, allControls.Length - 1 do
    26. local controlName = allControls[i].name
    27. --对应c#中的数组,从0开始
    28. if string.find(controlName,"btn") ~= nil or
    29. string.find(controlName,"tog") or
    30. string.find(controlName,"img") or
    31. string.find(controlName,"sv") or
    32. string.find(controlName,"txt") then
    33. --为了让我们在得的时候 能够确定控件类型 我们需要存储类型
    34. --利用反射 Type 得到 控件的类名
    35. local typeName = allControls[i]:GetType().Name
    36. --一个对象可能有多个ui组件 如同时又img txt,因此用表来存组件,名字为键
    37. --最终存储形式
    38. --{btnRole = {Image = 控件, Button = 控件 } ,
    39. -- toggle = {Toggle = 控件 } }
    40. if self.controls[allControls[i].name] ~= nil then
    41. --table.insert(self.controls[allControls[i].name],allControls[i])
    42. self.controls[controlName][typeName] = allControls[i]
    43. else
    44. --self.controls[allControls[i].name] = {allControls[i]}
    45. --这仍有点问题,我们该怎么区分表里的btn和img这些类别呢,因此要用到上面存储的类型
    46. --以下是正确的
    47. self.controls[controlName] = {[typeName] = allControls[i]}
    48. end
    49. end
    50. end
    51. end
    52. end
    53. --得到控件 根据 控件依附对象的名字 和 控件的类型字符串名字 Button Image Toggle
    54. function BasePanel:GetControl(name,typeName)
    55. if self.controls[name] ~= nil then
    56. local sameNameControls = self.controls[name]
    57. if sameNameControls[typeName] ~= nil then
    58. return sameNameControls[typeName]
    59. end
    60. end
    61. return nil
    62. end
    63. function BasePanel:ShowMe(name)
    64. self:Init(name)
    65. self.panelObj:SetActive(true)
    66. end
    67. function BasePanel:HideMe()
    68. self.panelObj:SetActive(false)
    69. end

    修改MainPanel.lua和BagPanel.lua

    1. BasePanel:subClass("MainPanel")
    2. function MainPanel:Init(name)
    3. --使用父类的方法,但用 . 而不是 :
    4. --要传入自己
    5. --里面已经有判空
    6. self.base.Init(self,name)
    7. --为了只添加一次事件监听
    8. if self.isInitEvent == false then
    9. btnRole = self:GetControl("btnRole","Button")
    10. btnRole.onClick:AddListener(function ()
    11. self:BtnRoleClick()
    12. end)
    13. self.isInitEvent = true
    14. end
    15. end
    16. function MainPanel:BtnRoleClick()
    17. BagPanel:ShowMe("BagPanel")
    18. end
    1. BasePanel:subClass("BagPanel")
    2. BagPanel.Content = nil
    3. --用来存储当前显示的格子
    4. BagPanel.items = {}
    5. BagPanel.nowType = -1
    6. --“成员方法"
    7. --初始化方法
    8. function BagPanel:Init(name)
    9. self.base.Init(self,name)
    10. --2.找到对应控件
    11. --找到子对象 再找到身上挂载的 想要的脚本
    12. --关闭按钮
    13. if self.isInitEvent == false then
    14. --找到没有挂载UI控件的对象还是需要手动去找
    15. self.Content = self:GetControl("svBag","ScrollRect").transform:Find("Viewport"):Find("Content")
    16. local group = self.panelObj.transform:Find("Group")
    17. self:GetControl("btnClose","Button").onClick:AddListener(function ()
    18. self:HideMe()
    19. end)
    20. --单选框事件
    21. --切页签
    22. --toggle 对应委托 是UnityAction
    23. local group = self.panelObj.transform:Find("Group")
    24. self:GetControl("togEquip","Toggle").onValueChanged:AddListener(function (value)
    25. if value == true then
    26. self:ChangeType(1)
    27. end
    28. end)
    29. self:GetControl("togItem","Toggle").onValueChanged:AddListener(function (value)
    30. if value == true then
    31. self:ChangeType(2)
    32. end
    33. end)
    34. self:GetControl("togGem","Toggle").onValueChanged:AddListener(function (value)
    35. if value == true then
    36. self:ChangeType(3)
    37. end
    38. end)
    39. self.isInitEvent = true
    40. end
    41. end
    42. --显示隐藏
    43. function BagPanel:ShowMe(name)
    44. self.base.ShowMe(self,name)
    45. if self.nowType == -1 then
    46. self:ChangeType(1)
    47. end
    48. end
    49. --逻辑处理函数 用来切页签
    50. --type 1装备 2道具 3宝石
    51. function BagPanel:ChangeType(type)
    52. --如果已经是该页,就不更新
    53. if self.nowType == type then
    54. return
    55. end
    56. --切页 根据玩家信息 来进行格子创建
    57. --更新之前 把老的格子删掉 BagPanel.items
    58. for i = 1, #self.items do
    59. --销毁格子对象
    60. self.items[i]:Destroy()
    61. end
    62. self.items = {}
    63. --再根据当前选择的类型 来创建新的格子 BagPanel.items
    64. --要根据传入的type 来选择显示的数据
    65. local nowItems = nil
    66. if type == 1 then
    67. nowItems = PlayerData.equips
    68. elseif type == 2 then
    69. nowItems = PlayerData.items
    70. else
    71. nowItems = PlayerData.gems
    72. end
    73. --创建格子
    74. for i = 1, #nowItems do
    75. --根据数据 创建一个格子对象
    76. local grid = ItemGrid:new()
    77. --要实例化对象 设置位置
    78. grid:Init(self.Content,(i-1)%4*175,math.floor((i-1)/4)*175)
    79. --初始化它的信息 数量 和 图标
    80. grid:InitData(nowItems[i])
    81. --把他存起来
    82. table.insert(self.items,grid)
    83. --这里实现了显示逻辑,但每次切换type要记得把老格子删除,逻辑在上面
    84. end
    85. end

    lua文件迁移小工具

    LuaCopyEditor.cs

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using System.IO;
    4. using System.IO.Enumeration;
    5. using Unity.VisualScripting;
    6. using UnityEditor;
    7. using UnityEngine;
    8. public class LuaCopyEditor : Editor
    9. {
    10. [MenuItem("XLua/自动生成txt后缀的lua")]
    11. public static void CopyLuaToTxt(){
    12. //找到所有lua文件
    13. string path = Application.dataPath + "/Lua/";
    14. if(!Directory.Exists(path))
    15. return;
    16. //得到每一个lua文件的路径 才能迁移拷贝
    17. //得到.lua文件路径
    18. string[] strs = Directory.GetFiles(path,"*.lua");
    19. //把lua文件拷贝到新的文件夹中
    20. //首先 定一个新路径
    21. string newPath = Application.dataPath + "/LuaTxt/";
    22. //为了避免一些被删除的lua文件 不再使用 我们应该先清空目标路径
    23. //判断新路径文件夹是否存在
    24. if(!Directory.Exists(newPath))
    25. Directory.CreateDirectory(newPath);
    26. else{
    27. //得到该路径中 所有后缀.txt的文件 把他们全部删除
    28. string[] oldFileStrs = Directory.GetFiles(newPath,"*.txt");
    29. for(int i = 0; i < oldFileStrs.Length; i++){
    30. File.Delete(oldFileStrs[i]);
    31. }
    32. }
    33. List<string> newFileNames = new List<string>();
    34. string fileName;
    35. for(int i = 0; i < strs.Length; i++){
    36. //得到新的文件路径 用于拷贝
    37. fileName = newPath + strs[i].Substring(strs[i].LastIndexOf("/") + 1) + ".txt";
    38. newFileNames.Add(fileName);
    39. File.Copy(strs[i],fileName);
    40. }
    41. AssetDatabase.Refresh();
    42. //刷新过后再来改指定AB包 如果不刷新 第一次改变 会没用
    43. for(int i = 0; i < newFileNames.Count; i++){
    44. //Unity API
    45. //该API传入的路径 必须是 相对Assets文件夹的 Assets/.../...
    46. AssetImporter importer = AssetImporter.GetAtPath( newFileNames[i].Substring(newFileNames[i].IndexOf("Assets")));
    47. if(importer != null)
    48. importer.assetBundleName = "lua";
    49. }
    50. }
    51. }

    LuaMgr中可以注释掉

            //luaEnv.AddLoader(MyCustomLoader);

    只使用

         luaEnv.AddLoader(MyCustomLoaderFormAB);

    即从AB包中加载

    注意事项

    每次ab包打包时,要将xlua代码清楚后打包,不然会报错

    记得打包完后重新生成xlua代码

  • 相关阅读:
    记录Linux系统中vim同时开多个窗口编辑文件
    【AOP系列】8.API统一处理
    LeetCode 2594. Minimum Time to Repair Cars【数组,二分】1915
    44岁的「老板」想变年轻
    RabbitMQ应用场景
    【ES】笔记-Set集合实践
    计算机毕设 基于大数据的社交平台数据爬虫舆情分析可视化系统
    查询性能的优化
    TDengine OSS 与 qStudio 实现无缝协同,革新数据分析和管理方式
    JavaScrip练习
  • 原文地址:https://blog.csdn.net/m0_61939767/article/details/138585695