概述
学习完xLua后的实践小项目
准备工作
新建工程导入必要资源
VScode环境搭建
包括一些设置
开发工作
1.拼面板
主面板部分
背包面板部分
格子面板
2.Lua基本逻辑准备
InitClass.lua 脚本
Lua
--常用别名都在这里面定位
--准备我们之前导入的脚本
--面向对象相关
require("Object")
--字符串拆分
require("SplitTools")
--Json解析
Json = require("JsonUtility")
--Unity相关的
GameObject = CS.UnityEngine.GameObject
Resources = CS.UnityEngine.Resources
Transform = CS.UnityEngine.Transform
RectTransform = CS.UnityEngine.RectTransform
--图集对象类
SpriteAtlas = CS.UnityEngine.U2D.SpriteAtlas
Vector3 = CS.UnityEngine.Vector3
Vector2 = CS.UnityEngine.Vector2
--Unity相关
UI = CS.UnityEngine.UI
Image = UI.Image
Text = UI.Text
Button = UI.Button
Toggle = UI.Toggle
--就是Scroll View
ScrollRect = UI.ScrollRect
--自己写的C#脚本相关
--直接得到AB包资源管理器的 单例对象
ABMgr = CS.ABMgr.GetInstance()
测试
3.数据准备
数据准备
创建图集
excel数据转Json
代码读取
配置表读取到Lua中
玩家数据准备
4.核心面板逻辑处理
MainPanel lua脚本
Lua
--只要是一个新的对象(如面板)我们就要新建一张表
MainPanel = {}
--不是必须写 因为lua的特性 不存在声明变量的概念
--这样写的目的 是当别人看这个lua代码时 知道这个表(对象)有什么变量很重要
--关联的面板对象
MainPanel.panelObj = nil
--对应的面板控件
MainPanel.btnRole = nil --这里只处理了btnRole按钮的逻辑
MainPanel.btnSkill = nil --btnSkill的逻辑也是一样进行添加即可
--需要做 实例化面板对象
--为这个面板 处理对应的逻辑 比如按钮点击等等
--初始化该面板 实例化对象 控件事件监听
function MainPanel:Init()
--面板对象没有实例化过 才去实例化处理
if self.panelObj == nil then
--1.实例化面板对象 ABMgr + 设置父对象
self.panelObj = ABMgr:LoadRes("ui", "MainPanel", typeof(GameObject))
self.panelObj.transform:SetParent(Canvas, false)
--2.找到对应控件
--找到子对象 再找到身上挂载的 脚本(如button脚本)
self.btnRole = self.panelObj.transform:Find("btnRole"):GetComponent(typeof(Button))
print(self.btnRole)
--3.为控件加上事件监听 进行点击等等的逻辑处理
--如果直接用.传入自己的函数 那么在函数内部 没有办法用self获取内容 所有只能用匿名函数包裹一层
--因为括号里是要传一个函数名,如果用 :那就是调用函数了
--self.btnRole.onClick:AddListener(self.BtnRoleClick)
self.btnRole.onClick:AddListener(function()
self:BtnRoleClick()
end)
end
end
--显示自己的方法
function MainPanel:ShowMe()
self:Init()
self.panelObj:SetActive(true)
end
--隐藏自己的方法
function MainPanel:HideMe()
self.panelObj:SetActive(false)
end
function MainPanel:BtnRoleClick()
--print(123123)
--print(self.panelObj)
--等我们写了背包面板
--在这显示我们的 背包面板
end
调用
补充
效果演示
BagPanel lua脚本
Lua
--一个面板对应一个表
BagPanel = {}
--"成员变量" 方便我们查看
--面板对象没有实例化过
BagPanel.panelObj = nil
--各个控件
BagPanel.btnClose = nil
BagPanel.togEquip = nil
BagPanel.togItem = nil
BagPanel.togGem = nil
BagPanel.svBag = nil
BagPanel.Content = nil
--"成员方法"
--初始化方法
function BagPanel:Init()
--判空
if self.panelObj == nill then
--实例化面板对象 和设置父对象
self.panelObj = ABMgr:LoadRes("ui", "BagPanel", typeof(GameObject))
self.panelObj.transform:SetParent(Canvas, false)
--找控件
--关闭按钮
self.btnClose = self.panelObj.transform:Find("btnClose"):GetComponent(typeof(Button))
--找3个toggle
local group = self.panelObj.transform:Find("Group")
self.togEquip = group:Find("togEquip"):GetComponent(typeof(Toggle))
self.togItem = group:Find("togItem"):GetComponent(typeof(Toggle))
self.togGem = group:Find("togGem"):GetComponent(typeof(Toggle))
--Scroll View 控件
self.svBag = self.panelObj.transform:Find("svBag"):GetComponent(typeof(ScrollRect))
self.Content = self.svBag.transform:Find("Viewport"):Find("Content") -- 找到Content
--加事件
--关闭按钮
self.btnClose.onClick:AddListener(function()
self:HideMe()
end)
--单选框事件
--切页签
self.togEquip.onValueChanged:AddListener(function(value)
if value == true then
self:ChangeType(1)
end
end)
self.togItem.onValueChanged:AddListener(function(value)
if value == true then
self:ChangeType(2)
end
end)
self.togGem.onValueChanged:AddListener(function(value)
if value == true then
self:ChangeType(3)
end
end)
end
end
--显示和隐藏方法
function BagPanel:ShowMe()
self:Init()
self.panelObj:SetActive(true)
end
function BagPanel:HideMe()
self.panelObj:SetActive(false)
end
--逻辑处理函数 用来切页签的
--type 1装备 2道具 3宝石
function BagPanel:ChangeType(type)
--print("当前类型为"..type) --测试
--切页 根据玩家信息 来进行格子创建
end
添加
效果
ItemGrid (在BagPanel里用items来存储格子,并进行逻辑处理)
Lua
--一个面板对应一个表
BagPanel = {}
--"成员变量" 方便我们查看
--面板对象没有实例化过
BagPanel.panelObj = nil
--各个控件
BagPanel.btnClose = nil
BagPanel.togEquip = nil
BagPanel.togItem = nil
BagPanel.togGem = nil
BagPanel.svBag = nil
BagPanel.Content = nil
--用来存储当前 显示的格子
BagPanel.items = {}
--当前页签ID 避免重复刷新
BagPanel.nowType = -1
--"成员方法"
--初始化方法
function BagPanel:Init()
--判空
if self.panelObj == nill then
--实例化面板对象 和设置父对象
self.panelObj = ABMgr:LoadRes("ui", "BagPanel", typeof(GameObject))
self.panelObj.transform:SetParent(Canvas, false)
--找控件
--关闭按钮
self.btnClose = self.panelObj.transform:Find("btnClose"):GetComponent(typeof(Button))
--找3个toggle
local group = self.panelObj.transform:Find("Group")
self.togEquip = group:Find("togEquip"):GetComponent(typeof(Toggle))
self.togItem = group:Find("togItem"):GetComponent(typeof(Toggle))
self.togGem = group:Find("togGem"):GetComponent(typeof(Toggle))
--Scroll View 控件
self.svBag = self.panelObj.transform:Find("svBag"):GetComponent(typeof(ScrollRect))
self.Content = self.svBag.transform:Find("Viewport"):Find("Content") -- 找到Content
--加事件
--关闭按钮
self.btnClose.onClick:AddListener(function()
self:HideMe()
end)
--单选框事件
--切页签
self.togEquip.onValueChanged:AddListener(function(value)
if value == true then
self:ChangeType(1)
end
end)
self.togItem.onValueChanged:AddListener(function(value)
if value == true then
self:ChangeType(2)
end
end)
self.togGem.onValueChanged:AddListener(function(value)
if value == true then
self:ChangeType(3)
end
end)
end
end
--显示和隐藏方法
function BagPanel:ShowMe()
self:Init()
self.panelObj:SetActive(true)
--第一次打开面板时显示页签1的数据
if self.nowType == -1 then
self:ChangeType(1)
end
end
function BagPanel:HideMe()
self.panelObj:SetActive(false)
end
--逻辑处理函数 用来切页签的
--type 1装备 2道具 3宝石
function BagPanel:ChangeType(type)
--print("当前类型为"..type) --测试
--判断如果已经是该页签 就别更新了
if self.nowType == type then
return
end
--切页 根据玩家信息 来进行格子创建
--更新之前 把老的格子删除掉 BagPanel.items
for i = 1, #self.items do
--销毁格子对象
GameObject.Destroy(self.items[i].obj)
end
self.items = {}
--再根据当前选择的类型 来创建新的格子 BagPanel.items
--要根据 传入的 type 来选择 显示的数据
local nowItems = nil
if type == 1 then
nowItems = PlayerData.equips
elseif type == 2 then
nowItems = PlayerData.items
else
nowItems = PlayerData.gems
end
--创建格子
for i = 1, #nowItems do
--有格子资源 直接加载格子资源 实例化 改变图片 和 文本 以及位置即可
local grid = {}
--用一张新表 代表 格子对象 里面的属性 存储对应想要的信息
grid.obj = ABMgr:LoadRes("ui", "ItemGrid")
--设置父对象
grid.obj.transform:SetParent(self.Content, false)
--继续设置位置 math.floor 向下取整
grid.obj.transform.localPosition = Vector3((i - 1) % 4 * 140, math.floor((i - 1) / 4) * 140)
--找控件
grid.imgIcon = grid.obj.transform:Find("imgIcon"):GetComponent(typeof(Image))
grid.Text = grid.obj.transform:Find("Text"):GetComponent(typeof(Text))
--设置它的图标
--通过 道具ID 去读取 道具配置表 得到 图标信息
local data = ItemData[nowItems[i].id]
--想要的是data中的 图标信息
--根据名字 先加载图集 再加载图集中的 图标信息 (用到字符串分割)
local strs = string.split(data.icon, "_")
--加载图集
local spriteAtlas = ABMgr:LoadRes("ui", strs[1], typeof(SpriteAtlas))
grid.imgIcon.sprite = spriteAtlas:GetSprite(strs[2])
--设置它的数量
grid.Text.text = nowItems[i].num
--把它存起来
table.insert(self.items, grid)
end
end
效果
小总结:其实就是用一个table将格子存储起来
缺点就是不够面向对象
5.面向对象优化
格子面向对象
ItemGrid lua脚本
Lua
--用到之前讲过的知识 Object(面向对象)
--生成一个table 集成Object 主要目的是要它里面实现的 继承方法subClass 和 new
Object:subClass("ItemGrid")
--"成员变量"
ItemGrid.obj = nil
ItemGrid.imgIcon = nil
ItemGrid.Text = nil
--成员函数
--实例化格子对象
function ItemGrid:Init(father, posX, posY)
--实例化格子对象
self.obj = ABMgr:LoadRes("ui", "ItemGrid")
--设置父对象
self.obj.transform:SetParent(father, false)
--继续设置位置 math.floor 向下取整
self.obj.transform.localPosition = Vector3(posX, posY, 0)
--找控件
self.imgIcon = self.obj.transform:Find("imgIcon"):GetComponent(typeof(Image))
self.Text = self.obj.transform:Find("Text"):GetComponent(typeof(Text))
end
--初始化格子信息
--data 是外面传入的 道具信息 里面包含了 id和num
function ItemGrid:InitData(data)
--通过 道具ID 去读取 道具配置表 得到 图标信息
local itemdata = ItemData[data.id]
--想要的是data中的 图标信息
--根据名字 先加载图集 再加载图集中的 图标信息 (用到字符串分割)
local strs = string.split(itemdata.icon, "_")
--加载图集
local spriteAtlas = ABMgr:LoadRes("ui", strs[1], typeof(SpriteAtlas))
self.imgIcon.sprite = spriteAtlas:GetSprite(strs[2])
--设置它的数量
self.Text.text = data.num
end
--加自己的逻辑
function ItemGrid:Destroy()
GameObject.Destroy(self.obj)
self.obj = nil
end
BagPanel 脚本的变动
Lua
--一个面板对应一个表
BagPanel = {}
--"成员变量" 方便我们查看
--面板对象没有实例化过
BagPanel.panelObj = nil
--各个控件
BagPanel.btnClose = nil
BagPanel.togEquip = nil
BagPanel.togItem = nil
BagPanel.togGem = nil
BagPanel.svBag = nil
BagPanel.Content = nil
--用来存储当前 显示的格子
BagPanel.items = {}
--当前页签ID 避免重复刷新
BagPanel.nowType = -1
--"成员方法"
--初始化方法
function BagPanel:Init()
--判空
if self.panelObj == nill then
--实例化面板对象 和设置父对象
self.panelObj = ABMgr:LoadRes("ui", "BagPanel", typeof(GameObject))
self.panelObj.transform:SetParent(Canvas, false)
--找控件
--关闭按钮
self.btnClose = self.panelObj.transform:Find("btnClose"):GetComponent(typeof(Button))
--找3个toggle
local group = self.panelObj.transform:Find("Group")
self.togEquip = group:Find("togEquip"):GetComponent(typeof(Toggle))
self.togItem = group:Find("togItem"):GetComponent(typeof(Toggle))
self.togGem = group:Find("togGem"):GetComponent(typeof(Toggle))
--Scroll View 控件
self.svBag = self.panelObj.transform:Find("svBag"):GetComponent(typeof(ScrollRect))
self.Content = self.svBag.transform:Find("Viewport"):Find("Content") -- 找到Content
--加事件
--关闭按钮
self.btnClose.onClick:AddListener(function()
self:HideMe()
end)
--单选框事件
--切页签
self.togEquip.onValueChanged:AddListener(function(value)
if value == true then
self:ChangeType(1)
end
end)
self.togItem.onValueChanged:AddListener(function(value)
if value == true then
self:ChangeType(2)
end
end)
self.togGem.onValueChanged:AddListener(function(value)
if value == true then
self:ChangeType(3)
end
end)
end
end
--显示和隐藏方法
function BagPanel:ShowMe()
self:Init()
self.panelObj:SetActive(true)
--第一次打开面板时显示页签1的数据
if self.nowType == -1 then
self:ChangeType(1)
end
end
function BagPanel:HideMe()
self.panelObj:SetActive(false)
end
--逻辑处理函数 用来切页签的
--type 1装备 2道具 3宝石
function BagPanel:ChangeType(type)
--print("当前类型为"..type) --测试
--判断如果已经是该页签 就别更新了
if self.nowType == type then
return
end
--切页 根据玩家信息 来进行格子创建
--更新之前 把老的格子删除掉 BagPanel.items
for i = 1, #self.items do
--销毁格子对象
--GameObject.Destroy(self.items[i].obj)
self.items[i]:Destroy()
end
self.items = {}
--再根据当前选择的类型 来创建新的格子 BagPanel.items
--要根据 传入的 type 来选择 显示的数据
local nowItems = nil
if type == 1 then
nowItems = PlayerData.equips
elseif type == 2 then
nowItems = PlayerData.items
else
nowItems = PlayerData.gems
end
--创建格子
for i = 1, #nowItems do
-- --有格子资源 直接加载格子资源 实例化 改变图片 和 文本 以及位置即可
-- local grid = {}
-- --用一张新表 代表 格子对象 里面的属性 存储对应想要的信息
-- grid.obj = ABMgr:LoadRes("ui", "ItemGrid")
-- --设置父对象
-- grid.obj.transform:SetParent(self.Content, false)
-- --继续设置位置 math.floor 向下取整
-- grid.obj.transform.localPosition = Vector3((i - 1) % 4 * 140, math.floor((i - 1) / 4) * 140, 0)
-- --找控件
-- grid.imgIcon = grid.obj.transform:Find("imgIcon"):GetComponent(typeof(Image))
-- grid.Text = grid.obj.transform:Find("Text"):GetComponent(typeof(Text))
-- --设置它的图标
-- --通过 道具ID 去读取 道具配置表 得到 图标信息
-- local data = ItemData[nowItems[i].id]
-- --想要的是data中的 图标信息
-- --根据名字 先加载图集 再加载图集中的 图标信息 (用到字符串分割)
-- local strs = string.split(data.icon, "_")
-- --加载图集
-- local spriteAtlas = ABMgr:LoadRes("ui", strs[1], typeof(SpriteAtlas))
-- grid.imgIcon.sprite = spriteAtlas:GetSprite(strs[2])
-- --设置它的数量
-- grid.Text.text = nowItems[i].num
--改
--根据数据 创建一个格子对象
local grid = ItemGrid:new()
--要实例化对象 设置位置
grid:Init(self.Content, (i - 1) % 4 * 140, math.floor((i - 1) / 4) * 140)
--初始化它的信息 数量和图标
grid:InitData(nowItems[i])
--把它存起来
table.insert(self.items, grid)
end
end
面板面向对象
1.先写一个基类 BasePanel
Lua
--利用面向对象
Object:subClass("BasePanel")
BasePanel.panelObj = nil
--相当于模拟一个字典 键为 控件名 值为控件本身
BasePanel.controls = {}
--事件监听标识
BasePanel.isInitEvent = false
function BasePanel:Init(name)
if self.panelObj == nil then
--公共的实例化对象的方法
self.panelObj = ABMgr:LoadRes("ui", name, typeof(GameObject))
self.panelObj.transform:SetParent(Canvas, false)
--GetComponentsInChildren 可以得到所有挂载某一脚本的子对象
--找到所有UI控件 存起来 (因为所有UI控件的父类是UIBehaviour)
local allControls = self.panelObj:GetComponentsInChildren(typeof(UIBehaviour))
--如果存入一些对于我们来说没用UI控件
--为了避免 找各种无用控件 我们定一个规则 拼面板时 控件命名一定按规范来
--Button btn名字打头
--Toggle tog名字打头
--Image img名字打头
--ScrollRect sv名字打头
for i = 0, allControls.Length - 1 do
local controlName = allControls[i].name
--按照名字的规则 去找控件 必须满足命名规则 才存起来
if string.find(controlName, "btn") ~= nil or
string.find(controlName, "tog") ~= nil or
string.find(controlName, "img") ~= nil or
string.find(controlName, "sv") ~= nil or
string.find(controlName, "txt") ~= nil then
--为了让我们在得的时候 能够 确定得的控件类型 所以我们需要存储类型
--利用反射 Type 得到 控件的类名
local typeName = allControls[i]:GetType().Name
--避免出现一个对象上 挂载多个UI控件 出现覆盖的问题
--都会被存到一个容器中 相当于像列表数组的形式
--最终存储形式为
--{ btnRole = { Image = 控件, Button = 控件 }, togItem = {Toggle = 控件 }}
if self.controls[controlName] ~= nil then
--通过自定义索引的形式 去加一个新的 "成员变量"
self.controls[controlName][typeName] = allControls[i]
else
self.controls[controlName] = {[typeName] = allControls[i]}
end
end
end
end
end
--得到控件 根据 控件依附对象的名字 和 控件的类型字符串名字 Button Image Toggle
function BasePanel:GetControl(name, typeName)
if self.controls[name] ~= nil then
local sameNameControls = self.controls[name]
if sameNameControls[typeName] ~= nil then
return sameNameControls[typeName]
end
end
return nil
end
function BasePanel:ShowMe(name)
self:Init(name)
self.panelObj:SetActive(true)
end
function BasePanel:HideMe()
self.panelObj:SetActive(false)
end
MainPanel 改
Lua
--只要是一个新的对象(如面板)我们就要新建一张表
BasePanel:subClass("MainPanel")
--需要做 实例化面板对象
--为这个面板 处理对应的逻辑 比如按钮点击等等
--初始化该面板 实例化对象 控件事件监听
function MainPanel:Init(name)
--调用父类里面的逻辑
self.base.Init(self, name)
--为了只添加一次事件监听
if self.isInitEvent == false then
print(self:GetControl("btnRole", "Image"))
self:GetControl("btnRole", "Button").onClick:AddListener(function()
self:BtnRoleClick()
end)
self.isInitEvent = true
end
end
function MainPanel:BtnRoleClick()
--print(123123)
--print(self.panelObj)
--等我们写了背包面板
--在这显示我们的 背包面板
BagPanel:ShowMe("BagPanel")
end
BagPanel 改
Lua
--一个面板对应一个表
BasePanel:subClass("BagPanel")
BagPanel.Content = nil
--用来存储当前 显示的格子
BagPanel.items = {}
--当前页签ID 避免重复刷新
BagPanel.nowType = -1
--"成员方法"
--初始化方法
function BagPanel:Init(name)
self.base.Init(self, name)
if self.isInitEvent == false then
--找没有挂载UI控件的 对象 还是需要手动去找
self.Content = self:GetControl("svBag", "ScrollRect").transform:Find("Viewport"):Find("Content") -- 找到Content
--加事件
--关闭按钮
self:GetControl("btnClose", "Button").onClick:AddListener(function()
self:HideMe()
end)
--单选框事件
--切页签
self:GetControl("togEquip", "Toggle").onValueChanged:AddListener(function(value)
if value == true then
self:ChangeType(1)
end
end)
self:GetControl("togItem", "Toggle").onValueChanged:AddListener(function(value)
if value == true then
self:ChangeType(2)
end
end)
self:GetControl("togGem", "Toggle").onValueChanged:AddListener(function(value)
if value == true then
self:ChangeType(3)
end
end)
self.isInitEvent = true
end
end
--显示和隐藏方法
function BagPanel:ShowMe(name)
self.base.ShowMe(self, name)
--第一次打开面板时显示页签1的数据
if self.nowType == -1 then
self:ChangeType(1)
end
end
--逻辑处理函数 用来切页签的
--type 1装备 2道具 3宝石
function BagPanel:ChangeType(type)
--print("当前类型为"..type) --测试
--判断如果已经是该页签 就别更新了
if self.nowType == type then
return
end
--切页 根据玩家信息 来进行格子创建
--更新之前 把老的格子删除掉 BagPanel.items
for i = 1, #self.items do
--销毁格子对象
--GameObject.Destroy(self.items[i].obj)
self.items[i]:Destroy()
end
self.items = {}
--再根据当前选择的类型 来创建新的格子 BagPanel.items
--要根据 传入的 type 来选择 显示的数据
local nowItems = nil
if type == 1 then
nowItems = PlayerData.equips
elseif type == 2 then
nowItems = PlayerData.items
else
nowItems = PlayerData.gems
end
--创建格子
for i = 1, #nowItems do
-- --有格子资源 直接加载格子资源 实例化 改变图片 和 文本 以及位置即可
-- local grid = {}
-- --用一张新表 代表 格子对象 里面的属性 存储对应想要的信息
-- grid.obj = ABMgr:LoadRes("ui", "ItemGrid")
-- --设置父对象
-- grid.obj.transform:SetParent(self.Content, false)
-- --继续设置位置 math.floor 向下取整
-- grid.obj.transform.localPosition = Vector3((i - 1) % 4 * 140, math.floor((i - 1) / 4) * 140, 0)
-- --找控件
-- grid.imgIcon = grid.obj.transform:Find("imgIcon"):GetComponent(typeof(Image))
-- grid.Text = grid.obj.transform:Find("Text"):GetComponent(typeof(Text))
-- --设置它的图标
-- --通过 道具ID 去读取 道具配置表 得到 图标信息
-- local data = ItemData[nowItems[i].id]
-- --想要的是data中的 图标信息
-- --根据名字 先加载图集 再加载图集中的 图标信息 (用到字符串分割)
-- local strs = string.split(data.icon, "_")
-- --加载图集
-- local spriteAtlas = ABMgr:LoadRes("ui", strs[1], typeof(SpriteAtlas))
-- grid.imgIcon.sprite = spriteAtlas:GetSprite(strs[2])
-- --设置它的数量
-- grid.Text.text = nowItems[i].num
--改
--根据数据 创建一个格子对象
local grid = ItemGrid:new()
--要实例化对象 设置位置
grid:Init(self.Content, (i - 1) % 4 * 140, math.floor((i - 1) / 4) * 140)
--初始化它的信息 数量和图标
grid:InitData(nowItems[i])
--把它存起来
table.insert(self.items, grid)
end
end
Main
最终效果和之前一样
6.Lua文件迁移工具
编辑器工具开发步骤
1.新建一个脚本
大部分放在Editor编辑器脚本中
2.继承 Editor编辑器 引用命名空间 using UnityEditor;
3.写个方法,加上特性 [MenuItem("XLua/自动生成txt后缀的Lua")]
cs
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
public class LuaCopyEditor : Editor
{
[MenuItem("XLua/自动生成txt后缀的Lua")]
public static void CopyLuaToTxt()
{
//首先要找到 我们的所有Lua文件
string path = Application.dataPath + "/Lua/";
//判断路径是否存在
if( !Directory.Exists(path))
return;
//得到每一个lua文件的路径 才能进行迁移拷贝
string[] strs = Directory.GetFiles(path, "*.lua");
//然后把Lua文件拷贝到一个新的文件夹中
//首先定一个新路径
string newPath = Application.dataPath + "/LuaTxt/";
//为了避免一些被删除的lua文件 不再使用 我们应该先清空目标路径的文件
//判断新路径文件夹 是否存在
if(!Directory.Exists(newPath))
Directory.CreateDirectory(newPath);
else
{
//得到该路径中 所有后缀 .txt 的文件 把它们都删除了
string[] oldFileStrs = Directory.GetFiles(newPath, "*.txt");
for(int i = 0; i < oldFileStrs.Length; i++){
File.Delete(oldFileStrs[i]);
}
}
List<string> newFileNames = new List<string>();
string fileName;
for(int i = 0; i < strs.Length; i++)
{
//得到新的文件路径 用于拷贝
fileName = newPath + strs[i].Substring(strs[i].LastIndexOf("/") + 1) + ".txt";
newFileNames.Add(fileName);
File.Copy(strs[i], fileName);
}
//调用刷新
AssetDatabase.Refresh();
//后面的逻辑只是用代码的形式自动的让生成的lua.txt脚本打包到AssetBundle中,后面直接打包即可,其实就是一些API的调用
//刷新后再来改指定包 因为 如果不刷新 第一次改变 会没有用
for(int i = 0; i < newFileNames.Count; i++){
//用到 Unity API
//改API传入的路径 必须是 相对Assets文件夹的 Assets/.../...
AssetImporter importer = AssetImporter.GetAtPath(newFileNames[i].Substring(newFileNames[i].IndexOf("Assets")));
if(importer != null)
importer.assetBundleName = "lua";
}
}
}
生成完AB包后,资源就可以直接从AB中加载
完成
效果演示:
LuaBag