当前位置: 首页 > news >正文

unity lua属性绑定刷新

我们现在有一个 角色属性类叫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 resendmetaTable.__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 thenlocal callback = metaTable.bindDataList[k]callback()endmetaTable.newInfo[k] = vreturn vend-- 将heroModel中的属性赋值到原表,并清空heroModel,这样操作之后,只要给heroModel进行赋值就会执行它的原方法 __newindexfor k, v in pairs(heroModel) dometaTable.newInfo[k] = vheroModel[k] = nilend-- 设置元表setmetatable(heroModel, metaTable)-- 绑定回调方法metaTable.bindDataList["level"] = function()printError("level 值发生了变化")end--测试printError("----test---")printError("level 初始值 = "..tostring(heroModel.level)) --没有更新赋值时候进行调用heroModel.level = 10 --通过__newindex 刷新属性值,并执行回调heroModel.level = 11local 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) thenreturnendlocal dataBindvars = {}local mateTable = getmetatable(target)setmetatable(dataBindvars, mateTable)for k, v in pairs(target) dodataBindvars[k] = vtarget[k] = nilendtarget.dataBindvars = dataBindvarstarget.bindInfo__ = {}target.isBind = falsetarget.oldMateTable = mateTablelocal settable = { __index = function(t, key)return dataBindvars[key]end }settable.__newindex = DataBindModel.__newindexsetmetatable(target, settable)
endfunction DataBindModel:unBindIns(target)if (not target.dataBindvars) thenreturnendlocal dataBindvars = target.dataBindvarslocal mateTable = target.oldMateTabletarget.oldMateTable = niltarget.bindInfo__ = niltarget.isBind = niltarget.dataBindvars = nilsetmetatable(target, mateTable)for k, v in pairs(dataBindvars) dotarget[k] = vend
endfunction DataBindModel:newIndex(key)return self.dataBindvars[key]
endfunction DataBindModel:__newindex(key, var)local vars = self.dataBindvarslocal oldValue = vars[key]vars[key] = varif (self.isBind) thenif (oldValue ~= var) thenlocal bindInfo__ = self.bindInfo__local bindData = bindInfo__[key]if (bindData) thenlocal tempBindData = {}for i, bdata in ipairs(bindData) dotable.insert(tempBindData, bdata)endfor i, bdata in ipairs(tempBindData) dobdata.callBack(var, bdata, self)endtempBindData = nilendendendend---@param target any @model
---@param bindInfo dataBindInfo
function DataBindModel:bindKey(target, bindInfo)if not target thenprintWarningColor("FFB500FF", "dataModel is nil")returnendif (not target.dataBindvars) thenself:__bindIns(target)endlocal bindInfo__ = target.bindInfo__local bindData = bindInfo__[bindInfo.key]if (not bindData) thenbindData = {}bindInfo__[bindInfo.key] = bindDataendtarget.isBind = truelocal uiNode = bindInfo.uiNodeif (uiNode and not tolua.isnull(uiNode)) then---@type CS.NodeEventListenerlocal nodeEventListener = uiNode:GetComponent(typeof(CS.NodeEventListener))if not nodeEventListener thennodeEventListener = uiNode.gameObject:AddComponent(typeof(CS.NodeEventListener))bindInfo.nodeEventHandle = function()self:unBindKey(target, bindInfo)endif nodeEventListener.destroyCallback thennodeEventListener.destroyCallback = nodeEventListener.destroyCallback + bindInfo.nodeEventHandleelsenodeEventListener.destroyCallback = bindInfo.nodeEventHandleendendendtable.insert(bindData, bindInfo)
end---@param target any
---@param bindInfo dataBindInfo
function DataBindModel:unBindKey(target, bindInfo)if (not target.dataBindvars) thenreturnendlocal bindInfo__ = target.bindInfo__local bindData = bindInfo__[bindInfo.key]if (bindData) thenlocal index = table.indexof(bindData, bindInfo)if (index) thentable.remove(bindData, index)local uiNode = bindInfo.uiNodeif (uiNode and not tolua.isnull(uiNode)) thenlocal nodeEventHandle = uiNode:GetComponent(typeof(CS.NodeEventListener))if nodeEventHandle thennodeEventHandle.destroyCallback = nodeEventHandle.destroyCallback - bindInfo.nodeEventHandleendendendif (#bindData == 0) thenbindInfo__[bindInfo.key] = nilendendlocal count = 0;for k, v in pairs(bindInfo__) docount = count + 1;break ;endif (count <= 0) thenself:unBindIns(target)end
end---@param bindDataInfos dataBindInfo
function DataBindModel:bindKeys(target, bindDataInfos)for i, data in ipairs(bindDataInfos) doself:bindKey(target, data)end
end---@param bindDataInfos dataBindInfo
function DataBindModel:unBindKeys(target, bindDataInfos)for i, data in ipairs(bindDataInfos) doself:unBindKey(target, data)end
endreturn 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)

相关文章:

unity lua属性绑定刷新

我们现在有一个 角色属性类叫heroModel,内容如下,当heroModel中的等级发生变化的时候&#xff0c;我们需要刷新界面显示等级信息&#xff0c;通常我们是在收到等级升级成功的协议的时候&#xff0c;发送一个事件&#xff0c;UI界面接受到这个事件的时候&#xff0c;刷新一下等级…...

Self-Pro: A Self-Prompt and Tuning Framework for Graph Neural Networks

Self-Pro: A Self-Prompt and Tuning Framework for Graph Neural Networks ​#paper/GFM/GNN-BASED#​ #paper/⭐⭐⭐#​ 注意&#xff1a;这篇文章是每个图一个GCN模型&#xff0c;而不是所有图一个GCN 模型 算是最早的涉及异配图的prompt了 贡献和动机&#xff1a; 非对…...

企业级-数据分类分级详细方案

一、方案背景 在数字化时代,数据成为企业和组织的核心资产。随着数据量的快速增长和数据应用场景的不断拓展,如何有效地管理和保护数据,确保数据的安全性、合规性和可用性,成为了亟待解决的问题。数据分类分级作为数据管理的基础工作,能够帮助企业清晰地了解自身的数据资…...

本地部署Qwen2.5-VL-7B-Instruct模型

本地部署Qwen2.5-VL-7B-Instruct模型 本地部署Permalink **创建环境** conda create -n qwenvl python3.11 -y# 报错&#xff1a; Solving environment: failedPackagesNotFoundError: The following packages are not available from current channels:# 处理&#xff1a; c…...

【前端】简单原生实例合集html,css,js

长期补充&#xff0c;建议关注收藏点赞。 目录 a标签设置不一样的花样&#xff08;图片但不用img)侧边固定box分栏input各种类型iframe表单拖拽 a标签设置不一样的花样&#xff08;图片但不用img) a标签里面不用嵌套img&#xff0c;直接设置为其bg-img即可 <!DOCTYPE html…...

【Spring】配置文件的使用

在Spring框架中&#xff0c;application.properties&#xff08;或application.yml&#xff09;文件用于配置Spring应用程序的各种属性。我们可以通过多种方式来使用这些配置&#xff0c;包括使用Value和ConfigurationProperties注解来绑定配置到Java对象。 下面是对不同配置类…...

MOM成功实施分享(七)电力电容制造MOM工艺分析与解决方案(第一部分)

声明&#xff1a;文章仅用于交流学习&#xff0c;不用于商业项目实施&#xff0c;图片来源于网络&#xff0c;如有侵犯权利&#xff0c;请联系作者及时删除。 本方案旨在对电力电容&#xff08;PEC和PQM型号&#xff09;制造工艺深度分析&#xff0c;结合管理要求设计MOM相关功…...

计算机毕业设计SpringBoot+Vue.js航空机票预定系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

Python 爬取唐诗宋词三百首

你可以使用 requests 和 BeautifulSoup 来爬取《唐诗三百首》和《宋词三百首》的数据。以下是一个基本的 Python 爬虫示例&#xff0c;它从 中华诗词网 或类似的网站获取数据并保存为 JSON 文件。 import requests from bs4 import BeautifulSoup import json import time# 爬取…...

【二.提示词工程与实战应用篇】【3.Prompt调优:让AI更懂你的需求】

最近老张在朋友圈秀出用AI生成的国风水墨画,隔壁王姐用AI写了份惊艳全场的年终总结,就连楼下小卖部老板都在用AI生成营销文案。你看着自己跟AI对话时满屏的"我不太明白您的意思",是不是怀疑自己买了台假电脑?别慌,这可能是你的打开方式不对。今天咱们就聊聊这个…...

商城源码的框架

商城源码的框架通常是基于某种Web开发框架或者电子商务平台来构建的。以下是一些常见的商城源码框架&#xff1a; WooCommerce&#xff1a;基于WordPress的电子商务插件&#xff0c;适用于小型到中型的在线商店。 Magento&#xff1a;一个功能强大和灵活的开源电子商务平台&am…...

WordPress如何防Webshell、防篡改、防劫持,提升WP漏洞防护能力

WordPress是一款世界知名的CMS系统&#xff0c;不仅可以创建博客网站&#xff0c;还可以用于建设企业网站、下载网站、商城等各类网站。功能非常强大、结构科学合理&#xff0c;深受广大用户喜欢。 虽然WordPress非常优秀&#xff0c;但是为了保障网站安全&#xff0c;我们还是…...

Android Flow 示例

在Android开发的世界里&#xff0c;处理异步数据流一直是一个挑战。随着Kotlin的流行&#xff0c;Flow作为Kotlin协程库的一部分&#xff0c;为开发者提供了一种全新的方式来处理这些问题。今天&#xff0c;我将深入探讨Flow的设计理念&#xff0c;并通过具体的例子展示如何在实…...

刚安装docker并启动docker服务: systemctl restart docker报错解决

root:/home/lzw# sudo systemctl restart docker Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xeu docker.service" for details. 1、问题描述 启动doc…...

xss笔记与打靶(更新中)

这个文章好 https://blog.csdn.net/huangyongkang666/article/details/123624164?fromshareblogdetail&sharetypeblogdetail&sharerId123624164&sharereferPC&sharesource2401_88818565&sharefromfrom_link 什么是xss XSS&#xff08;跨站脚本攻击&…...

游戏引擎学习第133天

仓库:https://gitee.com/mrxiao_com/2d_game_3 回顾并设定今天的主题 今天的任务是进一步优化背景资源的流式加载&#xff0c;尤其是在内存管理方面。昨天&#xff0c;我们实现了资源流式加载&#xff0c;让游戏在加载时可以动态地加载背景&#xff0c;而不是一开始就把所有资…...

【鸿蒙操作系统】- 1:实习阶段的一些总结

本文目录 1. 序2.鸿蒙与欧拉的概念微内核LiteOS鸿蒙微内核POSIX标准 3.实习干了些什么身份鉴别访问控制恶意代码防范安全审计入侵防范性能压测检查系统版本网络测试常见的linux测试命令 1. 序 之前在某国企实习的时候&#xff0c;有幸参与了鸿蒙系统、鸿蒙欧拉的项目&#xff…...

Qt基础入门-详解

前言 qt之路正式开启 &#x1f493; 个人主页&#xff1a;普通young man-CSDN博客 ⏩ 文章专栏&#xff1a;C_普通young man的博客-CSDN博客 ⏩ 本人giee: 普通小青年 (pu-tong-young-man) - Gitee.com 若有问题 评论区见&#x1f4dd; &#x1f389;欢迎大家点赞&#x1f44…...

【前端】HTML 备忘清单(超级详细!)

文章目录 入门hello.html注释 Comment段落 ParagraphHTML 链接Image 标签文本格式标签标题Section Divisions内部框架HTML 中的 JavaScriptHTML 中的 CSS HTML5 标签页面标题导航HTML5 TagsHTML5 VideoHTML5 AudioHTML5 RubyHTML5 kdiHTML5 progressHTML5 mark HTML 表格Table …...

版图自动化连接算法开发 00004 ------ 给定一个点,添加一个中间点实现 Manhattan 方式连接两个给定的坐标点

版图自动化连接算法开发 00004 ------ 给定一个点,添加一个中间点实现 Manhattan 方式连接两个给定的坐标点 引言正文引言 必读文章 ------ 版图自动化连接算法开发 00001 ------ 直接连接两个给定的坐标点。 此处,我们对给定点的坐标进行一下限制,因为是只添加一个点,因…...

CSS动画+超级千问:打造有呼吸感的语音合成反馈系统(实战教程)

CSS动画超级千问&#xff1a;打造有呼吸感的语音合成反馈系统&#xff08;实战教程&#xff09; 1. 项目介绍与核心价值 1.1 传统TTS工具的痛点 大多数语音合成工具的操作体验是这样的&#xff1a;面对一堆参数滑块&#xff0c;反复调整"语速"、"音高"、…...

深度解析Windows设备指纹伪装技术:EASY-HWID-SPOOFER内核级硬件隐私保护实现

深度解析Windows设备指纹伪装技术&#xff1a;EASY-HWID-SPOOFER内核级硬件隐私保护实现 【免费下载链接】EASY-HWID-SPOOFER 基于内核模式的硬件信息欺骗工具 项目地址: https://gitcode.com/gh_mirrors/ea/EASY-HWID-SPOOFER 在数字化时代&#xff0c;硬件隐私保护已成…...

7个实用技巧:从零开始开发jquery-qrcode自定义二维码生成器

7个实用技巧&#xff1a;从零开始开发jquery-qrcode自定义二维码生成器 【免费下载链接】jquery-qrcode qrcode generation standalone (doesnt depend on external services) 项目地址: https://gitcode.com/gh_mirrors/jq/jquery-qrcode jquery-qrcode是一款轻量级的纯…...

轻量锐驰 x 轻量对象存储:构建个人专属高速云存储方案

1. 为什么你需要自建云存储&#xff1f; 每次用公共网盘传文件都像在参加龟速比赛&#xff1f;分享给朋友时对方总抱怨下载慢如蜗牛&#xff1f;我三年前就开始研究自建云存储方案&#xff0c;实测下来轻量锐驰服务器轻量对象存储的组合&#xff0c;速度能跑满家庭宽带上限&…...

Z-Image-Turbo商业应用探索:稳定可靠的AI绘画方案推荐

Z-Image-Turbo商业应用探索&#xff1a;稳定可靠的AI绘画方案推荐 1. 商业级AI绘画的新选择 在数字内容创作需求爆炸式增长的今天&#xff0c;Z-Image-Turbo作为阿里通义实验室开源的文生图模型&#xff0c;凭借其卓越的稳定性和高效性&#xff0c;正在成为商业应用领域的新宠…...

Step3-VL-10B内网穿透应用:安全远程模型调用方案

Step3-VL-10B内网穿透应用&#xff1a;安全远程模型调用方案 1. 场景需求与痛点分析 很多企业和机构在内部部署了强大的多模态AI模型&#xff0c;比如Step3-VL-10B这样的视觉语言模型&#xff0c;能够处理图像和文本的复杂任务。但这些模型通常运行在内网环境中&#xff0c;外…...

Java学习——String 类的不可变性、底层实现(JDK1.8+)

目录 一、核心定义与设计思想 1. 核心定义 2. 核心设计思想 二、底层实现原理&#xff08;含 JDK 源码分析 / 反编译验证&#xff09; 1. JDK1.8 String 核心源码解析 2. 字符串常量池&#xff08;JDK1.8 底层&#xff09; 3. 反编译验证&#xff08;不可变性 编译器优…...

SPIRAN ART SUMMONER异常处理:常见错误解决方案

SPIRAN ART SUMMONER异常处理&#xff1a;常见错误解决方案 1. 前言 遇到SPIRAN ART SUMMONER运行报错时&#xff0c;别急着放弃。作为一款强大的AI艺术生成工具&#xff0c;它在使用过程中确实会遇到一些典型问题&#xff0c;但大多数都有明确的解决方法。本文汇总了用户反馈…...

IEEE会议论文避雷指南:如何用GSview+Photoshop搞定EPS图片压缩与特殊字符命名

IEEE会议论文图片处理全攻略&#xff1a;从格式转换到命名规范 第一次投稿IEEE会议的新手研究者们&#xff0c;往往会在图片处理环节栽跟头——明明内容扎实、实验充分&#xff0c;却因为技术细节问题被编辑退回修改。这不是学术能力的问题&#xff0c;而是对印刷出版标准的不熟…...

Meta2d.js完整指南:5步掌握专业级2D可视化引擎开发

Meta2d.js完整指南&#xff1a;5步掌握专业级2D可视化引擎开发 【免费下载链接】meta2d.js The meta2d.js is real-time data exchange and interactive web 2D engine. Developers are able to build Web SCADA, IoT, Digital twins and so on. Meta2d.js是一个实时数据响应和…...