unity lua属性绑定刷新

news2025/3/3 5:50:32

我们现在有一个 角色属性类叫heroModel,内容如下,当heroModel中的等级发生变化的时候,我们需要刷新界面显示等级信息,通常我们是在收到等级升级成功的协议的时候,发送一个事件,UI界面接受到这个事件的时候,刷新一下等级信息,如果不采用全局事件的方式,该怎么处理呢
我们能不能监听HeroModel的level这个属性,给这个属性绑定一个监听方法,当这个属性发生变化的时候,自动执行这个监听方法执行一些刷新操作。

local heroModel = {
        id = 1001,
        star = 1,
        level = 1, 
        life = 1000,
        atk = 100,
        def = 10,
    }
   

我们知道,lua有两个比较常见的原方法 __index 和 __newindex,__index是 元表提供的表对象内部数据获取元方法,__newindex是当对表中不存在的元素进行赋值时会被调用。当我们从heroModel中获取某一个属性值的时候,会先从heroModel中取值,如果heroModel中不存在该值,则会从原表中取值,同样当我们给heroModel赋值的时候,会先判断heroModel是否存在该属性,如果存在,直接赋值,不存在则从原方法 __newindex中进行赋值。加入heroModel中不存在level这个属性,那么我们给它赋值的时候,肯定会调用原方法__newindex ,这个时候我们就可以在这个原方法里面赋值的时候进行判断,属性level是否发生变化,如果发生了变化, 则执行一个回调方法

简单演示如下

local heroModel = {
         id = 1001, star = 1, level=1
     }

    ---创建原表
    local metaTable = {}
        metaTable.newInfo = {}  --保存新创建的属性值
        metaTable.bindDataList = {}  --存储回调方法
        metaTable.__index = function(t , k)
            printError("get " .. k)
            local res = metaTable.newInfo[k]
            return res
         end

        metaTable.__newindex = function(t, k, v)
            printError("set " .. k .. " = " .. tostring(v))
            if (not metaTable.newInfo[k] or metaTable.newInfo[k] ~= v) and metaTable.bindDataList[k] ~= nil then
                local callback = metaTable.bindDataList[k]
                callback()
            end
            metaTable.newInfo[k] = v
            return v
        end

    -- 将heroModel中的属性赋值到原表,并清空heroModel,这样操作之后,只要给heroModel进行赋值就会执行它的原方法 __newindex
     for k, v in pairs(heroModel) do
         metaTable.newInfo[k] = v
         heroModel[k] = nil
     end
    -- 设置元表
     setmetatable(heroModel, metaTable)

   -- 绑定回调方法
    metaTable.bindDataList["level"] = function()
        printError("level 值发生了变化")
    end

    --测试
    printError("----test---")
    printError("level 初始值 = "..tostring(heroModel.level)) --没有更新赋值时候进行调用
    heroModel.level = 10 --通过__newindex 刷新属性值,并执行回调
    heroModel.level = 11
    local b = heroModel.level --通关__index 获取新属性值
    printError("level新值 = " .. b)
    heroModel.kkk = 111 --通过__newindex 创建新属性值
    printError(heroModel.kkk) --通关__index 获取新属性值

输出结果

在这里插入图片描述

完整代码

DataBindModel = {}

---@class DataBindModel:nil
local DataBindModel = DataBindModel

---给实例添加绑定 内部方法 不要手动调用
---@param target dataBindInfo
function DataBindModel:__bindIns(target)
    if (target.dataBindvars) then
        return
    end
    local dataBindvars = {}
    local mateTable = getmetatable(target)
    setmetatable(dataBindvars, mateTable)

    for k, v in pairs(target) do
        dataBindvars[k] = v
        target[k] = nil
    end
    target.dataBindvars = dataBindvars
    target.bindInfo__ = {}
    target.isBind = false
    target.oldMateTable = mateTable
    local settable = { __index = function(t, key)
        return dataBindvars[key]
    end }
    settable.__newindex = DataBindModel.__newindex
    setmetatable(target, settable)
end

function DataBindModel:unBindIns(target)
    if (not target.dataBindvars) then
        return
    end
    local dataBindvars = target.dataBindvars
    local mateTable = target.oldMateTable
    target.oldMateTable = nil
    target.bindInfo__ = nil
    target.isBind = nil
    target.dataBindvars = nil
    setmetatable(target, mateTable)
    for k, v in pairs(dataBindvars) do
        target[k] = v
    end
end

function DataBindModel:newIndex(key)
    return self.dataBindvars[key]
end

function DataBindModel:__newindex(key, var)
    local vars = self.dataBindvars
    local oldValue = vars[key]
    vars[key] = var

    if (self.isBind) then

        if (oldValue ~= var) then
            local bindInfo__ = self.bindInfo__
            local bindData = bindInfo__[key]
            if (bindData) then
                local tempBindData = {}
                for i, bdata in ipairs(bindData) do
                    table.insert(tempBindData, bdata)
                end
                for i, bdata in ipairs(tempBindData) do
                    bdata.callBack(var, bdata, self)
                end
                tempBindData = nil
            end
        end
    end

end

---@param target any @model
---@param bindInfo dataBindInfo
function DataBindModel:bindKey(target, bindInfo)
    if not target then
        printWarningColor("FFB500FF", "dataModel is nil")
        return
    end

    if (not target.dataBindvars) then
        self:__bindIns(target)
    end
    local bindInfo__ = target.bindInfo__
    local bindData = bindInfo__[bindInfo.key]
    if (not bindData) then
        bindData = {}
        bindInfo__[bindInfo.key] = bindData
    end
    target.isBind = true
    local uiNode = bindInfo.uiNode
    if (uiNode and not tolua.isnull(uiNode)) then
        ---@type CS.NodeEventListener
        local nodeEventListener = uiNode:GetComponent(typeof(CS.NodeEventListener))
        if not nodeEventListener then
            nodeEventListener = uiNode.gameObject:AddComponent(typeof(CS.NodeEventListener))
            bindInfo.nodeEventHandle = function()
                self:unBindKey(target, bindInfo)
            end
            if nodeEventListener.destroyCallback then
                nodeEventListener.destroyCallback = nodeEventListener.destroyCallback + bindInfo.nodeEventHandle
            else
                nodeEventListener.destroyCallback = bindInfo.nodeEventHandle
            end
        end
    end
    table.insert(bindData, bindInfo)
end

---@param target any
---@param bindInfo dataBindInfo
function DataBindModel:unBindKey(target, bindInfo)
    if (not target.dataBindvars) then
        return
    end
    local bindInfo__ = target.bindInfo__
    local bindData = bindInfo__[bindInfo.key]
    if (bindData) then
        local index = table.indexof(bindData, bindInfo)
        if (index) then

            table.remove(bindData, index)
            local uiNode = bindInfo.uiNode
            if (uiNode and not tolua.isnull(uiNode)) then
                local nodeEventHandle = uiNode:GetComponent(typeof(CS.NodeEventListener))
                if nodeEventHandle then
                    nodeEventHandle.destroyCallback = nodeEventHandle.destroyCallback - bindInfo.nodeEventHandle
                end
            end
        end
        if (#bindData == 0) then
            bindInfo__[bindInfo.key] = nil
        end
    end
    local count = 0;
    for k, v in pairs(bindInfo__) do
        count = count + 1;
        break ;
    end
    if (count <= 0) then
        self:unBindIns(target)
    end
end

---@param bindDataInfos dataBindInfo
function DataBindModel:bindKeys(target, bindDataInfos)
    for i, data in ipairs(bindDataInfos) do
        self:bindKey(target, data)
    end
end

---@param bindDataInfos dataBindInfo
function DataBindModel:unBindKeys(target, bindDataInfos)
    for i, data in ipairs(bindDataInfos) do
        self:unBindKey(target, data)
    end
end

return DataBindModel

调用

注:DataBindModel 是一个全局table

local heroModel = {
         id = 1001, star = 1, level=1
     }
local bindDatas = {
	key = "level", 
	callBack = function(value, bindInfo, model)
		-- 执行刷新逻辑
		self:checkRed()
	end
}
DataBindModel:bindKeys(heroModel, bindDatas)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2308144.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu20.04安装Redis

目录 切换到root用户 使用 apt install redis 安装redis 修改配置文件 ​编辑 重新启动服务器 使用Redis客户端连接服务器 切换到root用户 如果没有切换到root用户的&#xff0c;切换到root用户。 使用 apt install redis 安装redis 遇到y/n直接y即可。 redis安装好之…

OSPF BIT 类型说明

注&#xff1a;本文为 “OSPF BIT 类型 | LSA 类型 ” 相关文章合辑。 机翻&#xff0c;未校。 15 OSPF BIT Types Explained 15 种 OSPF BIT 类型说明 Rashmi Bhardwaj Distribution of routing information within a single autonomous system in larger networks is per…

【深度学习】强化学习(RL)-A3C(Asynchronous Advantage Actor-Critic)

A3C&#xff08;Asynchronous Advantage Actor-Critic&#xff09;详解 A3C&#xff08;Asynchronous Advantage Actor-Critic&#xff09; 是 深度强化学习&#xff08;Deep Reinforcement Learning, DRL&#xff09; 领域的重要算法&#xff0c;由 DeepMind 在 2016 年提出。…

在 Mac mini M2 上本地部署 DeepSeek-R1:14B:使用 Ollama 和 Chatbox 的完整指南

随着人工智能技术的飞速发展&#xff0c;本地部署大型语言模型&#xff08;LLM&#xff09;已成为许多技术爱好者的热门选择。本地部署不仅能够保护隐私&#xff0c;还能提供更灵活的使用体验。本文将详细介绍如何在 Mac mini M2&#xff08;24GB 内存&#xff09;上部署 DeepS…

docker-compose部署onlyoffice8.3.0并支持ssl,且支持通过nginx代理,关闭JWT配置

编写docker-compose文件 mkdir -p /data/onlyoffice && echo "version: 3services:onlyoffice:container_name: OnlyOfficeimage: onlyoffice/documentserver:8.3.0restart: alwaysports:- 8088:80- 64431:443environment:TZ: Asia/ShanghaiJWT_ENABLED: falsevol…

【tplink】校园网接路由器如何单独登录自己的账号,wan-lan和lan-lan区别

老式路由器TPLINK&#xff0c;接入校园网后一人登录&#xff0c;所有人都能通过连接此路由器上网&#xff0c;无法解决遂上网搜索&#xff0c;无果&#xff0c;幸而偶然看到一个帖子说要把信号源网线接入路由器lan口&#xff0c;开启新世界。 一、wan-lan&#xff0c;lan-lan区…

DeepSeek开源周Day5压轴登场:3FS与Smallpond,能否终结AI数据瓶颈之争?

2025年2月28日&#xff0c;DeepSeek开源周迎来了第五天&#xff0c;也是本次活动的收官之日。自2月24日启动以来&#xff0c;DeepSeek团队以每天一个开源项目的节奏&#xff0c;陆续向全球开发者展示了他们在人工智能基础设施领域的最新成果。今天&#xff0c;他们发布了Fire-F…

[密码学实战]Java实现SM2数字信封(结合SM4对称加密)生成与解析

一、代码运行结果 二、什么是数字信封 2.1 基本概念 数字信封(Digital Envelope) 是一种结合对称加密与非对称加密的混合加密技术,通过以下步骤实现高效安全的数据传输: 对称加密:使用SM4算法加密原始数据,处理速度快,适合大数据量。非对称加密:使用SM2公钥加密SM4密…

Oracle 查询表空间使用情况及收缩数据文件

本文介绍Oracle收缩数据文件的相关操作&#xff0c;运维工作中有时会需要通过收缩数据文件来释放磁盘空间。 数据文件初始化方式&#xff1a; 1.我们创建表空间一般有两种方式初始化其数据文件&#xff0c;即指定初始大小为32G&#xff08;很大的值&#xff09;或指定初始大小为…

Grafana接入Zabbix数据源

1. 对接 Zabbix 1.1 安装 Zabbix 插件 在线安装&#xff1a; 1.2 配置 Zabbix 数据源 点击 Configuration > Data Sources > Add data source。选择 Zabbix&#xff0c;填写&#xff1a; URL&#xff1a;http://<zabbix-server>/api_jsonrpc.phpUsername&#x…

华为在不同发展时期的战略选择(节选)

华为在不同发展时期的战略选择&#xff08;节选&#xff09; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 来源&#xff1a;谢宁专著《华为战略管理法&#xff1a;DSTE实战体系》。本文有节选修改。 导言 从目前所取得的成就往回看&#xff0c;华为…

lua基础语法学习

lua基础语法学习 文章目录 lua基础语法学习1. 基础2. 输入输出3. 分支结构与循环结构4. 函数5. 元表与元方法6. 面向对象 1. 基础 注释 --单行注释--[[ 多行注释 --]]标识符 标识符以一个字母 A 到 Z 或 a 到 z 或下划线 _ 开头后加上 0 个或多个字母&#xff0c;下划线&…

【个人开发】deepspeed+Llama-factory 本地数据多卡Lora微调【完整教程】

文章目录 1.背景2.微调方式2.1 关键环境版本信息2.2 步骤2.2.1 下载llama-factory2.2.2 准备数据集2.2.3 微调模式2.2.3.1 zero-1微调2.2.3.2 zero-2微调2.2.3.3 zero-3微调2.2.3.4 单卡Lora微调 2.2.4 实验2.2.4.1 实验1&#xff1a;多GPU微调-zero12.2.4.2 实验2&#xff1a;…

【SpringBoot】数据访问技术spring Data、 JDBC、MyBatis、JSR-303校验

Spring Boot 数据访问技术及特性 目录标题 Spring Boot 数据访问技术及特性摘要1. 引言2. Spring Data架构与原理2.1 Spring Data概述2.2 Spring Data核心组件2.3 Spring Boot与Spring Data的集成机制 3. Spring Boot与JDBC的整合3.1 JDBC整合流程3.2 数据源自动配置3.3 JdbcTe…

手机放兜里,支付宝“碰一下”被盗刷?

大家好&#xff0c;我是小悟。 近期&#xff0c;网络上关于“支付宝‘碰一下’支付易被盗刷”的传言甚嚣尘上&#xff0c;不少用户对此心生疑虑。 首先&#xff0c;要明确一点&#xff1a;“碰一下”支付并不会像某些传言中所描述的那样容易被隔空盗刷。这一观点已经得到了支付…

vue框架后遗症∶被遗忘的dom操作

用多了vue、react等前端框架&#xff0c;不得不说用数据驱动视图来开发真的很香&#xff0c;但是也免不了会有不用这些框架的项目&#xff0c;dom操作还是很有必要的&#xff0c;一开始学习网页设计的时候就教过&#xff0c;后面一直开发项目基本上用框架。虽然有些想不起来了&…

基于深度学习+NLP豆瓣电影数据爬虫可视化推荐系统

博主介绍&#xff1a;资深开发工程师&#xff0c;从事互联网行业多年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了多年的设计程序开发&#xff0c;开发过上千套设计程序&#xff0c;没有什么华丽的语言&#xff0c;只有…

快速列出MS Word中所有可用字体

Word中有很多字体&#xff0c;虽然在字体下拉列表中提供了字体的样例&#xff0c;但是并不全面&#xff0c;例如使用Batang字体的话&#xff0c;数字会显示成什么效果&#xff0c;就无法直观的看到。 打开Word应用程序&#xff0c;新建一个空白文档&#xff0c;按AltF11打开VBE…

【密码学实战】Java 实现 SM2 国密算法(签名带id、验签及 C1C3C2 加密解密)

前言 SM2是中国国家密码管理局发布的椭圆曲线公钥密码算法标准&#xff08;GB/T 32918&#xff09;&#xff0c;属于国密算法体系。与RSA和ECDSA相比&#xff0c;SM2在相同安全强度下密钥更短、计算效率更高。本文将介绍如何在Java中实现SM2的密钥生成、数字签名、验签、加密及…

flex布局自定义一行几栏,靠左对齐===grid布局

模板 <div class"content"><div class"item">1222</div><div class"item">1222</div><div class"item">1222</div><div class"item">1222</div><div class"…