2. Unity3d Lua框架 - xLua - Lua面向对象设计 静态类 数据结构类 消息系统 单例类 可更新脚本 可更新单例脚本

  1. Lua面向对象设计
  2. 静态类:只读:避免访问错误,访问控制仅在调试模式下生效
  3. 数据结构类:不可写、读不存在的域:避免访问错误,访问控制仅在调试模式下生效
  4. 消息系统
  5. 单例类
  6. 可更新脚本,等效于带有Unity侧Update、LateUpdate、FixedUpdate函数
  7. 可更新单例脚本,等效于MonoSignleton

支付宝捐赠

打赏红包

1 . BaseClass.lua

--[[
-- Lua面向对象设计
--]]

--保存类类型的虚表
local _class = {}
 
-- 自定义类型
ClassType = {
	class = 1,
	instance = 2,
}
 
function BaseClass(classname, super)
	assert(type(classname) == "string" and #classname > 0)
	-- 生成一个类类型
	local class_type = {}
	
	-- 在创建对象的时候自动调用
	class_type.__init = false
	class_type.__delete = false
	class_type.__cname = classname
	class_type.__ctype = ClassType.class
	
	class_type.super = super
	class_type.New = function(...)
		-- 生成一个类对象
		local obj = {}
		obj._class_type = class_type
		obj.__ctype = ClassType.instance
		
		-- 在初始化之前注册基类方法
		setmetatable(obj, { 
			__index = _class[class_type],
		})
		-- 调用初始化方法
		do
			local create
			create = function(c, ...)
				if c.super then
					create(c.super, ...)
				end
				if c.__init then
					c.__init(obj, ...)
				end
			end

			create(class_type, ...)
		end

		-- 注册一个delete方法
		obj.Delete = function(self)
			local now_super = self._class_type 
			while now_super ~= nil do	
				if now_super.__delete then
					now_super.__delete(self)
				end
				now_super = now_super.super
			end
		end

		return obj
	end

	local vtbl = {}
	_class[class_type] = vtbl
 
	setmetatable(class_type, {
		__newindex = function(t,k,v)
			vtbl[k] = v
		end
		, 
		--For call parent method
		__index = vtbl,
	})
 
	if super then
		setmetatable(vtbl, {
			__index = function(t,k)
				local ret = _class[super][k]
				--do not do accept, make hot update work right!
				--vtbl[k] = ret
				return ret
			end
		})
	end
 
	return class_type
end

2 . ConstClass.lua

--[[
-- 静态类:只读:避免访问错误,访问控制仅在调试模式下生效
-- 注意:
-- 1、调试模式下需要getmetatable再执行遍历
--]]

function ConstClass(classname, const_tb, super)
	assert(type(classname) == "string" and #classname > 0)
    local cls
    if super then
        cls = DeepCopy(super)
    else
        cls = {}
    end
	
	if const_tb then
		for i,v in pairs(const_tb) do
			cls[i] = v
		end
	end
	
    cls.__cname = classname
	cls.__tostring = function(self)
		return table.dump(self, true, 2)
	end
	
	if Config.Debug then
		-- 访问限制
		cls.__index = function(tb, key)
			local value = cls[key]
			if value == nil then
				error(tb.__cname.." read err: no key named : "..key.."\n"..table.dump(tb), 2)
			end
			return value
		end
		cls.__newindex = function(tb, key, value)
			if cls[key] == nil then
				error(tb.__cname.." write err: No key named : "..key.."\n"..table.dump(tb), 2)
			else
				error(tb.__cname.."(const) can not be writed : "..key, 2)
			end
		end
		return setmetatable({}, cls)
	else
		return cls
	end
end

3 . DataClass.lua

--[[
-- 数据结构类:不可写、读不存在的域:避免访问错误,访问控制仅在调试模式下生效
-- 注意:
-- 1、必须初始化,没有默认值的概念(和CS结构体一样)
-- 2、字符串全部初始化为空串:""
-- 3、table全部初始化为空表:{}
-- 4、函数(比如回调)初始化为空函数:function() end
-- 5、初始化一定不要使用nil--为nil的项lua会认为你是要删除这个项,全部设置为false
-- 6、调试模式下需要getmetatable再执行遍历
-- 7、如果提供了__init函数但是实例化时不带参数或者参数不全,将被初始化为false
--]]

-- 访问限制
local DatakIndex = function(mt, key)
	local value = nil
	if mt[key] ~= nil then 
		value = mt[key]
	end
	if value == nil then
		error(mt.__cname.." read err: no key named : "..key.."\n"..table.dump(mt), 2)
	end
	return value
end

local DataNewindex = function(mt, key, value)
	if mt[key] == nil then
		error(mt.__cname.." write err: No key named : "..key.."\n"..table.dump(mt), 2)
	end
	
	if value then
		rawset(mt, key, value)
	else
		rawset(mt, key, false)
	end
end

function DataClass(classname, data_tb, super)
	assert(type(classname) == "string" and #classname > 0)
    local cls
    if super then
        cls = DeepCopy(super)
    else
        cls = {}
    end
	
	if data_tb then
		for i,v in pairs(data_tb) do
			cls[i] = v
		end
	end
	
	cls.super = super
    cls.__cname = classname
	
    function cls.New(...)
		local data = DeepCopy(cls)
		local ret_data
		data.New = nil
		if Config.Debug then
			-- 访问限制
			data.__index = function(tb, key)
				return DatakIndex(data, key)
			end
			data.__newindex = function(tb, key, value)
				DataNewindex(data, key, value)
			end
			ret_data = setmetatable({}, data)
		else
			ret_data = setmetatable(data, data)
		end
		
		-- 调用初始化方法
		do
			local args = {...}
			local create
			create = function(c, ...)
				if c.super then
					create(c.super, ...)
				end
				if c.__init then
					c.__init(ret_data, ...)
				end
			end
			
			if #args > 0 then
				create(cls, ...)
			end
		end
		return ret_data
    end
	
    return cls
end

4 . Messenger.lua

--[[
-- 消息系统
-- 使用范例:
-- local Messenger = require "Framework.Common.Messenger";
-- local TestEventCenter = Messenger.New() --创建消息中心
-- TestEventCenter:AddListener(Type, callback) --添加监听
-- TestEventCenter:AddListener(Type, callback, ...) --添加监听
-- TestEventCenter:Broadcast(Type, ...) --发送消息
-- TestEventCenter:RemoveListener(Type, callback, ...) --移除监听
-- TestEventCenter:Cleanup() --清理消息中心
-- 注意:
-- 1、模块实例销毁时,要自动移除消息监听,不移除的话不能自动清理监听
-- 2、使用弱引用,即使监听不手动移除,消息系统也不会持有对象引用,所以对象的销毁是不受消息系统影响的
-- 3、换句话说:广播发出,回调一定会被调用,但回调参数中的实例对象,可能已经被销毁,所以回调函数一定要注意判空
--]]

local Messenger = BaseClass("Messenger");

local function __init(self)
	self.events = {}
end

local function __delete(self)
	self.events = nil	
	self.error_handle = nil
end

local function AddListener(self, e_type, e_listener, ...)
	local event = self.events[e_type]
	if event == nil then
		event = setmetatable({}, {__mode = "k"})
	end
	
	for k, v in pairs(event) do
		if k == e_listener then
			error("Aready cotains listener : "..tostring(e_listener))
			return
		end
	end
	
	event[e_listener] = setmetatable(SafePack(...), {__mode = "kv"}) 
	self.events[e_type] = event;
end

local function Broadcast(self, e_type, ...)
	local event = self.events[e_type]
	if event == nil then
		return
	end
	
	for k, v in pairs(event) do
		assert(k ~= nil)
		local args = ConcatSafePack(v, SafePack(...))
		k(SafeUnpack(args))
	end
end

local function RemoveListener(self, e_type, e_listener)
	local event = self.events[e_type]
	if event == nil then
		return
	end

	event[e_listener] = nil
end

local function RemoveListenerByType(self, e_type)
	self.events[e_type] = nil
end

local function Cleanup(self)
	self.events = {};
end

Messenger.__init = __init
Messenger.__delete = __delete
Messenger.AddListener = AddListener
Messenger.Broadcast = Broadcast
Messenger.RemoveListener = RemoveListener
Messenger.RemoveListenerByType = RemoveListenerByType
Messenger.Cleanup = Cleanup

return Messenger;
  1. Singleton.lua
--[[
-- 单例类
--]]

local Singleton = BaseClass("Singleton");

local function __init(self)
	assert(rawget(self._class_type, "Instance") == nil, self._class_type.__cname.." to create singleton twice!")
	rawset(self._class_type, "Instance", self)
end

local function __delete(self)
	rawset(self._class_type, "Instance", nil)
end

-- 只是用于启动模块
local function Startup(self)
end

-- 不要重写
local function GetInstance(self)
	if rawget(self, "Instance") == nil then
		rawset(self, "Instance", self.New())
	end
	assert(self.Instance ~= nil)
	return self.Instance
end

-- 不要重写
local function Delete(self)
	self.Instance = nil
end

Singleton.__init = __init
Singleton.__delete = __delete
Singleton.Startup = Startup
Singleton.GetInstance = GetInstance
Singleton.Destory = Destory

return Singleton;

  1. Updatable.lua
--[[
-- 可更新脚本,等效于带有Unity侧Update、LateUpdate、FixedUpdate函数
-- 注意:
-- 1、虽然支持Update、LateUpdate、FixedUpdate更新,但能不用就不用---不要定义这些函数即可,用太多可能对性能有影响
-- 2、使用Time获取时间相关信息,如:Time.deltaTime,Time.fixedDeltaTime,Time.frameCount等
--]]

local Updatable = BaseClass("Updatable")

-- 添加更新函数
local function AddUpdate(self)
	if self.Update ~= nil then
		self.__update_handle = BindCallback(self, self.Update)
		UpdateManager:GetInstance():AddUpdate(self.__update_handle)
	end
	if self.LateUpdate ~= nil then
		self.__lateupdate_handle = BindCallback(self, self.LateUpdate)
		UpdateManager:GetInstance():AddLateUpdate(self.__lateupdate_handle)
	end
	if self.FixedUpdate ~= nil then
		self.__fixedupdate_handle = BindCallback(self, self.FixedUpdate)
		UpdateManager:GetInstance():AddFixedUpdate(self.__fixedupdate_handle)
	end
end

-- 注销更新函数
local function RemoveUpdate(self)
	if self.__update_handle ~= nil then
		UpdateManager:GetInstance():RemoveUpdate(self.__update_handle)
		self.__update_handle = nil
	end
	if self.__lateupdate_handle ~= nil then
		UpdateManager:GetInstance():RemoveLateUpdate(self.__lateupdate_handle)
		self.__lateupdate_handle = nil
	end
	if self.__fixedupdate_handle ~= nil then
		UpdateManager:GetInstance():RemoveFixedUpdate(self.__fixedupdate_handle)
		self.__fixedupdate_handle = nil
	end
end

-- 构造函数
local function __init(self)
	self:EnableUpdate(true)
end

-- 析构函数
local function __delete(self)
	self:EnableUpdate(false)
end

-- 是否启用更新
local function EnableUpdate(self, enable)
	RemoveUpdate(self)
	if enable then
		AddUpdate(self)
	end
end

Updatable.__init = __init
Updatable.__delete = __delete
Updatable.EnableUpdate = EnableUpdate

return Updatable
  1. UpdatableSingleton.lua
--[[
-- 可更新单例脚本,等效于MonoSignleton
--]]

local UpdatableSingleton = BaseClass("UpdatableSingleton", Updatable)

local function __init(self)
	assert(rawget(self._class_type, "Instance") == nil, self._class_type.__cname.." to create UpdatableSingleton twice!")
	rawset(self._class_type, "Instance", self)
end

local function __delete(self)
	rawset(self._class_type, "Instance", nil)
end

-- 只是用于启动模块
local function Startup(self)
end

-- 不要重写
local function GetInstance(self)
	if rawget(self, "Instance") == nil then
		rawset(self, "Instance", self.New())
	end
	assert(self.Instance ~= nil)
	return self.Instance
end

-- 不要重写
local function Delete(self)
	self.Instance = nil
end

UpdatableSingleton.__init = __init
UpdatableSingleton.__delete = __delete
UpdatableSingleton.Startup = Startup
UpdatableSingleton.GetInstance = GetInstance
UpdatableSingleton.Destory = Destory

return UpdatableSingleton

支付宝捐赠

打赏红包

你可能感兴趣的:(Lua)