xLua游戏开发框架实战指南
## 一、框架架构设计
### 整体分层架构
```
┌─────────────────────────────────────────┐
游戏业务层(Lua)
- 游戏逻辑/UI/数据配置
├─────────────────────────────────────────┤
Lua框架层(Lua)
- 模块管理/事件系统/MVC框架
├─────────────────────────────────────────┤
桥接层(C# + Lua)
- 类型转换/函数调用/数据同步
├─────────────────────────────────────────┤
基础服务层(C#)
- 网络通信/资源管理/对象池/配置加载
├─────────────────────────────────────────┤
Unity引擎层
└─────────────────────────────────────────┘
```
## 二、环境搭建与初始化
### 1. xLua环境管理器
```csharp
// LuaManager.cs - 核心Lua环境管理
using UnityEngine;
using XLua;
public class LuaManager : MonoSingleton
{
private LuaEnv luaEnv;
private LuaTable luaFramework;
private bool initialized = false;
private void Awake()
{
DontDestroyOnLoad(gameObject);
}
public void Initialize()
{
if (initialized) return;
// 创建Lua环境
luaEnv = new LuaEnv();
// 设置Lua路径
SetupLuaPath();
// 加载核心框架脚本
LoadFrameworkScripts();
// 初始化Lua框架
InitializeLuaFramework();
// 启动垃圾回收
StartGCCoroutine();
initialized = true;
Debug.Log("xLua环境初始化完成");
}
private void SetupLuaPath()
{
// 设置Lua脚本搜索路径
string luaPath = Application.dataPath + "/LuaScripts/?.lua;";
luaPath += Application.dataPath + "/LuaScripts/?/init.lua;";
// 支持热更新路径
if (Application.isMobilePlatform || Application.isConsolePlatform)
{
luaPath += Application.persistentDataPath + "/LuaScripts/?.lua;";
luaPath += Application.persistentDataPath + "/LuaScripts/?/init.lua;";
}
luaEnv.AddLoader((ref string filepath) =>
{
string scriptPath = filepath.Replace('.', '/');
string fullPath = Application.dataPath + "/LuaScripts/" + scriptPath + ".lua";
if (System.IO.File.Exists(fullPath))
{
return System.IO.File.ReadAllBytes(fullPath);
}
// 尝试热更新路径
fullPath = Application.persistentDataPath + "/LuaScripts/" + scriptPath + ".lua";
if (System.IO.File.Exists(fullPath))
{
return System.IO.File.ReadAllBytes(fullPath);
}
return null;
});
}
private void LoadFrameworkScripts()
{
// 加载核心框架模块
string[] frameworkScripts = {
"core/utils",
"core/class",
"core/event",
"core/module",
"core/mvc",
"core/ui"
};
foreach (string script in frameworkScripts)
{
luaEnv.DoString($"require('{script}')");
}
}
private void InitializeLuaFramework()
{
// 获取Lua框架表
luaFramework = luaEnv.Global.Get("Framework");
if (luaFramework != null)
{
// 初始化框架
LuaFunction initFunc = luaFramework.Get("Initialize");
initFunc?.Call();
}
}
private void StartGCCoroutine()
{
StartCoroutine(GCCoroutine());
}
private System.Collections.IEnumerator GCCoroutine()
{
while (true)
{
yield return new WaitForSeconds(1f);
luaEnv?.Tick();
// 定期执行完整GC
if (Time.frameCount % 300 == 0)
{
luaEnv?.FullGc();
}
}
}
public LuaEnv GetLuaEnv()
{
return luaEnv;
}
public void DoString(string script, string chunkName = "chunk")
{
luaEnv?.DoString(script, chunkName);
}
public void Require(string moduleName)
{
luaEnv?.DoString($"require('{moduleName}')");
}
private void OnDestroy()
{
if (luaFramework != null)
{
LuaFunction shutdownFunc = luaFramework.Get("Shutdown");
shutdownFunc?.Call();
luaFramework.Dispose();
}
luaEnv?.Dispose();
luaEnv = null;
}
}
```
## 三、Lua框架核心模块
### 1. 基础工具库
```lua
-- core/utils.lua
local M = {}
-- 打印函数
function M.print(...)
local args = {...}
for i, v in ipairs(args) do
args[i] = tostring(v)
end
print("[Lua] " .. table.concat(args, " "))
end
-- 判断表是否为空
function M.isEmpty(t)
return t == nil or next(t) == nil
end
-- 深拷贝
function M.deepcopy(t)
local copy = {}
for k, v in pairs(t) do
if type(v) == "table" then
copy[k] = M.deepcopy(v)
else
copy[k] = v
end
end
return copy
end
-- 表合并
function M.merge(t1, t2)
local result = M.deepcopy(t1)
for k, v in pairs(t2) do
if type(v) == "table" and type(result[k]) == "table" then
result[k] = M.merge(result[k], v)
else
result[k] = v
end
end
return result
end
-- 防抖函数
function M.debounce(func, delay)
local timer = nil
return function(...)
if timer then
CS.UnityEngine.CoroutineUtility.StopCoroutine(timer)
end
local args = {...}
timer = CS.UnityEngine.CoroutineUtility.StartCoroutine(function()
CS.UnityEngine.Yield(CS.UnityEngine.WaitForSeconds(delay))
func(unpack(args))
timer = nil
end)
end
end
-- 节流函数
function M.throttle(func, delay)
local lastCall = 0
return function(...)
local now = CS.UnityEngine.Time.time
if now - lastCall >= delay then
lastCall = now
func(...)
end
end
end
return M
```
### 2. 类系统实现
```lua
-- core/class.lua
local utils = require("core.utils")
local M = {}
-- 创建类
function M.class(className, super)
local cls = {}
cls.__className = className
cls.__super = super
cls.__instances = {}
-- 元表
setmetatable(cls, {
__index = function(t, k)
if super then
return super[k]
end
return nil
end,
__call = function(cls, ...)
local instance = {}
setmetatable(instance, {
__index = cls
})
if cls.ctor then
cls.ctor(instance, ...)
end
table.insert(cls.__instances, instance)
return instance
end
})
return cls
end
-- 类方法:获取实例数量
function M.GetInstanceCount(cls)
return #cls.__instances
end
-- 类方法:获取所有实例
function M.GetAllInstances(cls)
return cls.__instances
end
-- 类方法:销毁实例
function M.Destroy(instance)
local cls = getmetatable(instance).__index
for i, inst in ipairs(cls.__instances) do
if inst == instance then
table.remove(cls.__instances, i)
end
end
end
-- 单例模式
function M.singleton(className, ctor)
local instance = nil
return function(...)
if not instance then
instance = ctor(...)
end
return instance
end
end
return M
```
### 3. 事件系统
```lua
-- core/event.lua
local utils = require("core.utils")
local M = {}
-- 事件管理器
local EventManager = M.class("EventManager")
function EventManager:ctor()
self.listeners = {}
self.onceListeners = {}
end
-- 监听事件
function EventManager:on(eventName, callback, target)
if not self.listeners[eventName] then
self.listeners[eventName] = {}
end
table.insert(self.listeners[eventName], {
callback = callback,
target = target
})
end
-- 一次性监听
function EventManager:once(eventName, callback, target)
if not self.onceListeners[eventName] then
self.onceListeners[eventName] = {}
end
table.insert(self.onceListeners[eventName], {
callback = callback,
target = target
})
end
-- 移除监听
function EventManager:off(eventName, callback, target)
local function removeListener(listeners)
if not listeners[eventName] then
return
end
for i = #listeners[eventName], 1, -1 do
local listener = listeners[eventName][i]
if listener.callback == callback and listener.target == target then
table.remove(listeners[eventName], i)
end
end
end
removeListener(self.listeners)
removeListener(self.onceListeners)
end
-- 派发事件
function EventManager:emit(eventName, ...)
local function dispatch(listeners)
if not listeners[eventName] then
return
end
for i, listener in ipairs(listeners[eventName]) do
if listener.target then
listener.callback(listener.target, ...)
else
listener.callback(...)
end
end
end
-- 先派发一次性监听
dispatch(self.onceListeners)
self.onceListeners[eventName] = nil
-- 派发普通监听
dispatch(self.listeners)
end
-- 清空所有监听
function EventManager:clear()
self.listeners = {}
self.onceListeners = {}
end
-- 全局事件管理器实例
local globalEventManager = EventManager()
-- 全局接口
function M.on(eventName, callback, target)
globalEventManager:on(eventName, callback, target)
end
function M.once(eventName, callback, target)
globalEventManager:once(eventName, callback, target)
end
function M.off(eventName, callback, target)
globalEventManager:off(eventName, callback, target)
end
function M.emit(eventName, ...)
globalEventManager:emit(eventName, ...)
end
function M.getEventManager()
return globalEventManager
end
return M
```
## 四、模块管理系统
```lua
-- core/module.lua
local utils = require("core.utils")
local class = require("core.class")
local M = {}
-- 模块基类
local Module = M.class("Module")
function Module:ctor(name)
self.name = name
self.enabled = false
self.initialized = false
end
function Module:initialize()
utils.print("Module " .. self.name .. " initializing...")
self.initialized = true
end
function Module:enable()
if not self.initialized then
self:initialize()
end
self.enabled = true
utils.print("Module " .. self.name .. " enabled")
end
function Module:disable()
self.enabled = false
utils.print("Module " .. self.name .. " disabled")
end
function Module:update(deltaTime)
-- 子类重写
end
function Module:lateUpdate(deltaTime)
-- 子类重写
end
function Module:fixedUpdate(deltaTime)
-- 子类重写
end
function Module:destroy()
utils.print("Module " .. self.name .. " destroyed")
self.initialized = false
self.enabled = false
end
-- 模块管理器
local ModuleManager = M.class("ModuleManager")
function ModuleManager:ctor()
self.modules = {}
self.updateList = {}
self.lateUpdateList = {}
self.fixedUpdateList = {}
end
-- 注册模块
function ModuleManager:registerModule(module)
if self.modules[module.name] then
utils.print("Module " .. module.name .. " already registered")
return
end
self.modules[module.name] = module
utils.print("Module " .. module.name .. " registered")
end
-- 获取模块
function ModuleManager:getModule(name)
return self.modules[name]
end
-- 启用模块
function ModuleManager:enableModule(name)
local module = self:getModule(name)
if module then
module:enable()
-- 添加到更新列表
if module.update then
table.insert(self.updateList, module)
end
if module.lateUpdate then
table.insert(self.lateUpdateList, module)
end
if module.fixedUpdate then
table.insert(self.fixedUpdateList, module)
end
end
end
-- 禁用模块
function ModuleManager:disableModule(name)
local module = self:getModule(name)
if module then
module:disable()
-- 从更新列表中移除
for i = #self.updateList, 1, -1 do
if self.updateList[i] == module then
table.remove(self.updateList, i)
end
end
for i = #self.lateUpdateList, 1, -1 do
if self.lateUpdateList[i] == module then
table.remove(self.lateUpdateList, i)
end
end
for i = #self.fixedUpdateList, 1, -1 do
if self.fixedUpdateList[i] == module then
table.remove(self.fixedUpdateList, i)
end
end
end
end
-- 更新所有启用的模块
function ModuleManager:update(deltaTime)
for _, module in ipairs(self.updateList) do
if module.enabled then
module:update(deltaTime)
end
end
end
function ModuleManager:lateUpdate(deltaTime)
for _, module in ipairs(self.lateUpdateList) do
if module.enabled then
module:lateUpdate(deltaTime)
end
end
end
function ModuleManager:fixedUpdate(deltaTime)
for _, module in ipairs(self.fixedUpdateList) do
if module.enabled then
module:fixedUpdate(deltaTime)
end
end
end
-- 销毁所有模块
function ModuleManager:destroyAll()
for name, module in pairs(self.modules) do
module:destroy()
end
self.modules = {}
self.updateList = {}
self.lateUpdateList = {}
self.fixedUpdateList = {}
end
-- 全局模块管理器实例
local globalModuleManager = ModuleManager()
-- 全局接口
function M.registerModule(module)
globalModuleManager:registerModule(module)
end
function M.getModule(name)
return globalModuleManager:getModule(name)
end
function M.enableModule(name)
globalModuleManager:enableModule(name)
end
function M.disableModule(name)
globalModuleManager:disableModule(name)
end
function M.getModuleManager()
return globalModuleManager
end
return M
```
## 五、MVC框架实现
```lua
-- core/mvc.lua
local utils = require("core.utils")
local class = require("core.class")
local event = require("core.event")
local M = {}
-- Model基类
local Model = M.class("Model")
function Model:ctor(name)
self.name = name
self.data = {}
self.listeners = {}
end
-- 设置数据
function Model:set(key, value)
local oldValue = self.data[key]
self.data[key] = value
-- 通知数据变化
self:notifyChange(key, value, oldValue)
end
-- 获取数据
function Model:get(key)
return self.data[key]
end
-- 监听数据变化
function Model:observe(key, callback)
if not self.listeners[key] then
self.listeners[key] = {}
end
table.insert(self.listeners[key], callback)
end
-- 移除监听
function Model:unobserve(key, callback)
if not self.listeners[key] then
return
end
for i = #self.listeners[key], 1, -1 do
if self.listeners[key][i] == callback then
table.remove(self.listeners[key], i)
end
end
end
-- 通知数据变化
function Model:notifyChange(key, newValue, oldValue)
if self.listeners[key] then
for _, callback in ipairs(self.listeners[key]) do
callback(newValue, oldValue)
end
end
end
-- View基类
local View = M.class("View")
function View:ctor(name)
self.name = name
self.gameObject = nil
self.transforms = {}
self.components = {}
end
-- 绑定GameObject
function View:bind(gameObject)
self.gameObject = gameObject
self:onBind()
end
-- 绑定完成后回调
function View:onBind()
-- 子类重写
end
-- 获取Transform
function View:getTransform(path)
if not self.transforms[path] then
self.transforms[path] = self.gameObject.transform:Find(path)
end
return self.transforms[path]
end
-- 获取组件
function View:getComponent(path, componentType)
local key = path .. "_" .. componentType
if not self.components[key] then
local transform = self:getTransform(path)
if transform then
self.components[key] = transform:GetComponent(componentType)
end
end
return self.components[key]
end
-- 显示
function View:show()
if self.gameObject then
self.gameObject:SetActive(true)
end
end
-- 隐藏
function View:hide()
if self.gameObject then
self.gameObject:SetActive(false)
end
end
-- Controller基类
local Controller = M.class("Controller")
function Controller:ctor(name)
self.name = name
self.model = nil
self.view = nil
self.commands = {}
end
-- 绑定Model和View
function Controller:bind(model, view)
self.model = model
self.view = view
self:onBind()
end
-- 绑定完成后回调
function Controller:onBind()
-- 子类重写
end
-- 注册命令
function Controller:registerCommand(commandName, commandFunc)
self.commands[commandName] = commandFunc
end
-- 执行命令
function Controller:executeCommand(commandName, ...)
local command = self.commands[commandName]
if command then
command(self, ...)
else
utils.print("Command not found: " .. commandName)
end
end
-- MVC工厂
local MVCFactory = M.class("MVCFactory")
function MVCFactory:ctor()
this.models = {}
this.views = {}
this.controllers = {}
end
-- 创建Model
function MVCFactory:createModel(name, modelClass)
local model = modelClass(name)
self.models[name] = model
return model
end
-- 创建View
function MVCFactory:createView(name, viewClass, gameObject)
local view = viewClass(name)
view:bind(gameObject)
self.views[name] = view
return view
end
-- 创建Controller
function MVCFactory:createController(name, controllerClass, modelName, viewName)
local model = self.models[modelName]
local view = self.views[viewName]
local controller = controllerClass(name)
controller:bind(model, view)
self.controllers[name] = controller
return controller
end
-- 获取Model
function MVCFactory:getModel(name)
return self.models[name]
end
-- 获取View
function MVCFactory:getView(name)
return self.views[name]
end
-- 获取Controller
function MVCFactory:getController(name)
return self.controllers[name]
end
-- 全局MVC工厂实例
local globalMVCFactory = MVCFactory()
-- 全局接口
function M.createModel(name, modelClass)
return globalMVCFactory:createModel(name, modelClass)
end
function M.createView(name, viewClass, gameObject)
return globalMVCFactory:createView(name, viewClass, gameObject)
end
function M.createController(name, controllerClass, modelName, viewName)
return globalMVCFactory:createController(name, controllerClass, modelName, viewName)
end
function M.getModel(name)
return globalMVCFactory:getModel(name)
end
function M.getView(name)
return globalMVCFactory:getView(name)
end
function M.getController(name)
return globalMVCFactory:getController(name)
end
return M
```
## 六、C#侧框架入口
```csharp
// GameFramework.cs - 框架入口
using UnityEngine;
using XLua;
public class GameFramework : MonoSingleton
{
private LuaTable luaFramework;
private bool frameworkInitialized = false;
private void Start()
{
// 初始化Lua环境
LuaManager.Instance.Initialize();
// 获取Lua框架
luaFramework = LuaManager.Instance.GetLuaEnv().Global.Get("Framework");
if (luaFramework != null)
{
// 启动框架
StartFramework();
}
}
private void StartFramework()
{
if (frameworkInitialized) return;
// 调用Lua框架的启动方法
LuaFunction startFunc = luaFramework.Get("Start");
startFunc?.Call();
frameworkInitialized = true;
Debug.Log("游戏框架启动完成");
}
private void Update()
{
if (!frameworkInitialized) return;
// 调用Lua框架的更新方法
LuaFunction updateFunc = luaFramework.Get("Update");
updateFunc?.Call(Time.deltaTime);
}
private void LateUpdate()
{
if (!frameworkInitialized) return;
// 调用Lua框架的延迟更新方法
LuaFunction lateUpdateFunc = luaFramework.Get("LateUpdate");
lateUpdateFunc?.Call(Time.deltaTime);
}
private void FixedUpdate()
{
if (!frameworkInitialized) return;
// 调用Lua框架的固定更新方法
LuaFunction fixedUpdateFunc = luaFramework.Get("FixedUpdate");
fixedUpdateFunc?.Call(Time.fixedDeltaTime);
}
private void OnApplicationPause(bool pauseStatus)
{
if (!frameworkInitialized) return;
// 调用Lua框架的暂停回调
LuaFunction pauseFunc = luaFramework.Get("OnApplicationPause");
pauseFunc?.Call(pauseStatus);
}
private void OnDestroy()
{
if (!frameworkInitialized) return;
// 调用Lua框架的销毁方法
LuaFunction destroyFunc = luaFramework.Get("OnDestroy");
destroyFunc?.Call();
}
}
```
## 七、完整框架启动脚本
```lua
-- Framework/init.lua - 框架主入口
local utils = require("core.utils")
local event = require("core.event")
local module = require("core.module")
local mvc = require("core.mvc")
local Framework = {}
-- 框架初始化
function Framework.Initialize()
utils.print("========================================")
utils.print(" xLua游戏框架初始化中...")
utils.print("========================================")
-- 注册核心模块
Framework:RegisterCoreModules()
-- 注册游戏模块
Framework:RegisterGameModules()
-- 初始化事件系统
Framework:InitializeEventSystem()
utils.print("========================================")
utils.print(" xLua游戏框架初始化完成")
utils.print("========================================")
end
-- 注册核心模块
function Framework:RegisterCoreModules()
utils.print("注册核心模块...")
-- 资源管理模块
local ResourceManager = require("modules.resource_manager")
module.registerModule(ResourceManager("ResourceManager"))
-- 配置管理模块
local ConfigManager = require("modules.config_manager")
module.registerModule(ConfigManager("ConfigManager"))
-- 网络管理模块
local NetworkManager = require("modules.network_manager")
module.registerModule(NetworkManager("NetworkManager"))
-- UI管理模块
local UIManager = require("modules.ui_manager")
module.registerModule(UIManager("UIManager"))
-- 音频管理模块
local AudioManager = require("modules.audio_manager")
module.registerModule(AudioManager("AudioManager"))
end
-- 注册游戏模块
function Framework:RegisterGameModules()
utils.print("注册游戏模块...")
-- 玩家模块
local PlayerModule = require("modules.player_module")
module.registerModule(PlayerModule("PlayerModule"))
-- 战斗模块
local BattleModule = require("modules.battle_module")
module.registerModule(BattleModule("BattleModule"))
-- 关卡模块
local LevelModule = require("modules.level_module")
module.registerModule(LevelModule("LevelModule"))
end
-- 初始化事件系统
function Framework:InitializeEventSystem()
utils.print("初始化事件系统...")
-- 注册全局事件
event.on("APP_PAUSE", function(paused)
if paused then
utils.print("应用暂停")
else
utils.print("应用恢复")
end
end)
event.on("LEVEL_LOADED", function(levelName)
utils.print("关卡加载完成: " .. levelName)
end)
end
-- 框架启动
function Framework.Start()
utils.print("========================================")
utils.print(" 启动xLua游戏框架...")
utils.print("========================================")
-- 启用核心模块
module.enableModule("ResourceManager")
module.enableModule("ConfigManager")
module.enableModule("NetworkManager")
module.enableModule("UIManager")
module.enableModule("AudioManager")
-- 加载配置
Framework:LoadConfigurations()
-- 启动游戏模块
Framework:StartGameModules()
-- 加载主场景
Framework:LoadMainScene()
utils.print("========================================")
utils.print(" xLua游戏框架启动完成")
utils.print("========================================")
end
-- 加载配置
function Framework:LoadConfigurations()
utils.print("加载游戏配置...")
local configManager = module.getModule("ConfigManager")
if configManager then
configManager:LoadAllConfigs()
end
end
-- 启动游戏模块
function Framework:StartGameModules()
utils.print("启动游戏模块...")
module.enableModule("PlayerModule")
module.enableModule("BattleModule")
module.enableModule("LevelModule")
end
-- 加载主场景
function Framework:LoadMainScene()
utils.print("加载主场景...")
local levelModule = module.getModule("LevelModule")
if levelModule then
levelModule:LoadLevel("MainScene")
end
end
-- 框架更新
function Framework.Update(deltaTime)
local moduleManager = module.getModuleManager()
moduleManager:update(deltaTime)
end
-- 框架延迟更新
function Framework.LateUpdate(deltaTime)
local moduleManager = module.getModuleManager()
moduleManager:lateUpdate(deltaTime)
end
-- 框架固定更新
function Framework.FixedUpdate(deltaTime)
local moduleManager = module.getModuleManager()
moduleManager:fixedUpdate(deltaTime)
end
-- 应用暂停回调
function Framework.OnApplicationPause(paused)
event.emit("APP_PAUSE", paused)
end
-- 框架销毁
function Framework.OnDestroy()
utils.print("销毁xLua游戏框架...")
local moduleManager = module.getModuleManager()
moduleManager:destroyAll()
event.getEventManager():clear()
end
-- 导出框架接口
_G.Framework = Framework
return Framework
```
## 八、核心模块示例实现
### 资源管理模块
```lua
-- modules/resource_manager.lua
local utils = require("core.utils")
local class = require("core.class")
local event = require("core.event")
local moduleBase = require("core.module")
local ResourceManager = moduleBase.Module:extend("ResourceManager")
function ResourceManager:ctor(name)
ResourceManager.super.ctor(self, name)
self.loadedAssets = {}
self.loadingRequests = {}
end
function ResourceManager:initialize()
utils.print("初始化资源管理器...")
-- 预加载核心资源
self:PreloadCoreAssets()
ResourceManager.super.initialize(self)
end
-- 预加载核心资源
function ResourceManager:PreloadCoreAssets()
local coreAssets = {
"UI/Prefabs/MainPanel",
"UI/Prefabs/HUDPanel",
"Audio/BGM/MainTheme"
}
utils.print("预加载核心资源...")
for i, assetPath in ipairs(coreAssets) do
self:LoadAssetAsync(assetPath, function(asset)
utils.print("预加载完成: " .. assetPath)
end)
end
end
-- 异步加载资源
function ResourceManager:LoadAssetAsync(assetPath, callback)
-- 检查是否已加载
if self.loadedAssets[assetPath] then
if callback then
callback(self.loadedAssets[assetPath])
end
return
end
-- 检查是否正在加载
if self.loadingRequests[assetPath] then
table.insert(self.loadingRequests[assetPath], callback)
return
end
-- 开始加载
self.loadingRequests[assetPath] = {callback}
CS.ResourceLoader.Instance:LoadAssetAsync(assetPath, function(asset)
self.loadedAssets[assetPath] = asset
-- 通知所有等待的回调
for _, cb in ipairs(self.loadingRequests[assetPath]) do
if cb then
cb(asset)
end
end
self.loadingRequests[assetPath] = nil
utils.print("资源加载完成: " .. assetPath)
-- 派发资源加载完成事件
event.emit("RESOURCE_LOADED", assetPath, asset)
end)
end
-- 同步加载资源
function ResourceManager:LoadAsset(assetPath)
-- 检查是否已加载
if self.loadedAssets[assetPath] then
return self.loadedAssets[assetPath]
end
-- 同步加载
local asset = CS.ResourceLoader.Instance:LoadAsset(assetPath)
if asset then
self.loadedAssets[assetPath] = asset
utils.print("资源加载完成: " .. assetPath)
event.emit("RESOURCE_LOADED", assetPath, asset)
end
return asset
end
-- 卸载资源
function ResourceManager:UnloadAsset(assetPath)
if self.loadedAssets[assetPath] then
CS.Resources.UnloadAsset(self.loadedAssets[assetPath])
self.loadedAssets[assetPath] = nil
utils.print("资源卸载完成: " .. assetPath)
end
end
-- 获取已加载资源
function ResourceManager:GetLoadedAsset(assetPath)
return self.loadedAssets[assetPath]
end
-- 清理未使用资源
function ResourceManager:CleanupUnusedAssets()
CS.Resources.UnloadUnusedAssets()
utils.print("清理未使用资源完成")
end
return ResourceManager
```
## 九、框架使用示例
### 游戏逻辑实现
```lua
-- game/player.lua
local utils = require("core.utils")
local class = require("core.class")
local mvc = require("core.mvc")
local event = require("core.event")
local PlayerModel = mvc.Model:extend("PlayerModel")
function PlayerModel:ctor(name)
PlayerModel.super.ctor(self, name)
-- 初始化玩家数据
self:set("level", 1)
self:set("exp", 0)
self:set("hp", 100)
self:set("maxHp", 100)
self:set("attack", 10)
self:set("defense", 5)
self:set("gold", 1000)
end
function PlayerModel:addExp(amount)
local currentExp = self:get("exp")
local level = self:get("level")
self:set("exp", currentExp + amount)
-- 检查升级
local expNeeded = level * 100
if currentExp + amount >= expNeeded then
self:levelUp()
end
end
function PlayerModel:levelUp()
local level = self:get("level")
self:set("level", level + 1)
self:set("maxHp", self:get("maxHp") + 10)
self:set("attack", self:get("attack") + 2)
self:set("defense", self:get("defense") + 1)
utils.print("玩家升级到 " .. self:get("level") .. " 级!")
event.emit("PLAYER_LEVEL_UP", self:get("level"))
end
function PlayerModel:takeDamage(damage)
local currentHp = self:get("hp")
local defense = self:get("defense")
local actualDamage = math.max(0, damage - defense)
self:set("hp", math.max(0, currentHp - actualDamage))
utils.print("玩家受到 " .. actualDamage .. " 点伤害, 剩余生命: " .. self:get("hp"))
if self:get("hp") <= 0 then
event.emit("PLAYER_DEAD")
end
end
function PlayerModel:heal(amount)
local currentHp = self:get("hp")
local maxHp = self:get("maxHp")
self:set("hp", math.min(maxHp, currentHp + amount))
utils.print("玩家恢复 " .. amount .. " 点生命, 当前生命: " .. self:get("hp"))
end
local PlayerView = mvc.View:extend("PlayerView")
function PlayerView:onBind()
-- 绑定UI元素
self.hpText = self:getComponent("HPText", "Text")
self.levelText = self:getComponent("LevelText", "Text")
self.expText = self:getComponent("ExpText", "Text")
self.hpSlider = self:getComponent("HPSlider", "Slider")
self.expSlider = self:getComponent("ExpSlider", "Slider")
-- 更新UI
self:updateUI()
end
function PlayerView:updateUI()
if self.hpText then
self.hpText.text = "HP: " .. self.model:get("hp") .. "/" .. self.model:get("maxHp")
end
if self.levelText then
self.levelText.text = "Lv. " .. self.model:get("level")
end
if self.expText then
self.expText.text = "EXP: " .. self.model:get("exp")
end
if self.hpSlider then
self.hpSlider.value = self.model:get("hp") / self.model:get("maxHp")
end
if self.expSlider then
local expNeeded = self.model:get("level") * 100
self.expSlider.value = self.model:get("exp") / expNeeded
end
end
local PlayerController = mvc.Controller:extend("PlayerController")
function PlayerController:onBind()
-- 监听数据变化
self.model:observe("hp", function(newValue, oldValue)
self.view:updateUI()
end)
self.model:observe("level", function(newValue, oldValue)
self.view:updateUI()
end)
self.model:observe("exp", function(newValue, oldValue)
self.view:updateUI()
end)
-- 注册命令
self:registerCommand("ATTACK", function(controller, target)
local damage = controller.model:get("attack")
target:takeDamage(damage)
end)
self:registerCommand("HEAL", function(controller, amount)
controller.model:heal(amount)
end)
end
return {
Model = PlayerModel,
View = PlayerView,
Controller = PlayerController
}
```
## 十、项目目录结构
```
Assets/
├── Scripts/
│ ├── Core/
│ │ ├── LuaManager.cs
│ │ ├── GameFramework.cs
│ │ └── MonoSingleton.cs
│ ├── Services/
│ │ ├── ResourceLoader.cs
│ │ ├── NetworkManager.cs
│ │ └── AudioManager.cs
│ └── Game/
│ └── GameController.cs
├── LuaScripts/
│ ├── core/
│ │ ├── utils.lua
│ │ ├── class.lua
│ │ ├── event.lua
│ │ ├── module.lua
│ │ └── mvc.lua
│ ├── modules/
│ │ ├── resource_manager.lua
│ │ ├── config_manager.lua
│ │ ├── network_manager.lua
│ │ ├── ui_manager.lua
│ │ ├── audio_manager.lua
│ │ ├── player_module.lua
│ │ ├── battle_module.lua
│ │ └── level_module.lua
│ ├── game/
│ │ ├── player.lua
│ │ ├── enemy.lua
│ │ ├── battle.lua
│ │ └── ui/
│ │ ├── main_panel.lua
│ │ └── hud_panel.lua
│ └── Framework/
│ └── init.lua
└── Resources/
├── UI/
│ └── Prefabs/
├── Audio/
│ └── BGM/
└── Config/
```
## 十一、使用流程
### 1. 初始化流程
```csharp
// 在Unity中创建空的GameObject,挂载GameFramework脚本
// 游戏启动时会自动初始化整个框架
```
### 2. 编写Lua游戏逻辑
```lua
-- 在LuaScripts/game/目录下编写游戏逻辑
-- 例如:player.lua
```
### 3. 运行游戏
```
1. 在Unity中点击运行
2. 框架会自动初始化
3. Lua脚本会被加载执行
4. 游戏逻辑开始运行
```
## 十二、总结
这套xLua游戏框架的核心优势:
1. **模块化设计**:清晰的功能划分,易于扩展和维护
2. **完整的MVC架构**:数据、视图、控制器分离,代码结构清晰
3. **强大的事件系统**:模块间松耦合通信
4. **热更新支持**:Lua代码可以实时更新,无需重启游戏
5. **丰富的工具库**:提供常用的开发工具函数
6. **性能优化**:对象池、资源管理等优化机制
通过这套框架,你可以快速搭建一个功能完善、结构清晰的游戏项目,充分发挥xLua的优势,实现高效的游戏开发和热更新功能。
这个框架已经为你准备好了基础架构,你可以在此基础上根据项目需求进行扩展和定制,逐步构建出属于自己的游戏开发框架。