比如UI上的组件cc.Label 组件如何和游戏里的数据绑定
比如
cc.Label.string = My.money
这个只是赋值,UI上是变化了1次
但在我脚本里
My.money += 100;
如何使得UI上的 Label也相应变化呢?
有什么好办法吗?
你是想要 mvvm 模式么,论坛搜下有插件的呀
纯手写的话可以这样。
@property(cc.Label)
moneyLabel: cc.Label = null;
_money: number = 0
get money() {
return this._money;
}
set money(val: number) {
this._money = val;
this._moneyLabel.string = `${val}`;
}
这属于静态绑定吧
就是说 组件,数据 同时纯在,
实际的情况 往往是,游戏数据是全局的,而UI是某个场景的!
那,,这个办法似乎不行吧!
而且,一个数据可能在多个场景的多个UI组件上使用啊!
发送一个消息嘛,所有用到这个数据的UI响应这个消息,自己去读取数据来更新。
额我想你是想类似vue的吧,这样是需要你自己去注入变量去拦截修改,也就是对一个变量的属性重写get set方法,在js中你可以
// 使用 Object.defineProperty
Object.defineProperty(obj, attr, {
get: function () {
return val;
},
set: function (newValue) {
// 修改通知
}
});
你可以遍历对象所有属性进行拦截监听,进行封装一下就可以实现你想要的了,这些都是框架级的了,一般你就写get set 然后发游戏通知就可以了,如果要透明这种在代码里面看的干净,那就是我上面说的了,我自己实现了一个http://puremvc.org/框架,就是直接的对model监听指定属性变化就好,不用实现发通知的步骤,框架已经实现了
或者用set get 或者用事件监听,看你习惯哪种了
1.只更新当前ui 直接赋值 省事
2.同时更新当前ui或其他ui 事件派发 无疑
使用set get感觉有些冗余吧
mvvm不知道是否对任意ui生效?需要配置什么 麻烦不?
对我而言 更关心是赋值给哪个ui 而不是数值…
1.用 set get方法就是 如果游戏变量很多 就比较麻烦,而且游戏变量随时增加。。。
2.游戏变量 与 ui 都不是同步出现的,策划随时改变ui,程序也随时增加,或者减少变量,这样的绑定就比较麻烦
3.消息通知,当前我就是这么做的,,想看看是否有更好的机制。。
我的游戏是 MMORPG类
对全局变量,我都是使用自定义消息机制,当变量更新后触发更新消息,需要使用这个变量的地方监听消息即可
我严重怀疑 cc的消息通知机制,似乎 监听多了就有收不到的情况,所以我都不敢用!你确定消息通知机制没问题吗?还是我使用的方式有问题,,我不确定,也就不敢用了,之前收不到消息或者不能100%收到消息,填了很多坑啊!
另外,如果使用自定义消息,那要为 每一个 全局变量 都给出一个 消息名 吧!
如果 游戏系统里有 100个这样的变量,那就要有100个 自定义消息名,这样才好区分 哪个变量变化了!
我这MMORPG 变量不只100个, 估计得几百个
你用的是cc.Node的自定义消息?
试试我这个方案,看是否满足你的需求
/**
- 全局消息管理类(自己实现)
*/
export class MsgManager {
public static on(msgName, callback, thisobj) {
//实现省略
}
public static off(msgName, callback, thisobj) {
//实现省略
}
public static emit(...arg) {
//实现省略
}
}
/**
- 游戏数据管理类
*/
export class GameData {
private static atts = {};
public static setAtt(attName, attValue) {
this.atts[attName] = attValue;
MsgManager.emit(attName, attValue);
}
}
/**
- 要版定属性的lebel节点挂上该脚本
*/
export default class AttBinding extends cc.Component {
onEnable() {
MsgManager.on(this.node.name, this.updateAtt, this);
}
onDisable() {
MsgManager.off(this.node.name, this.updateAtt, this);
}
updateAtt(attName, attValue) {
if (attName === this.node.name) {
this.node.getComponent(cc.Label).string = attValue + ``;
}
}
}
this.node.name
重名会有问题吗?
你的属性的名字肯定是唯一的,所以在属性绑定上肯定不会有冲突,如果你担心属性的Label节点有可能会和非属性的Label节点发生冲突,你可以定个属性节点的命名规则,比如加个前缀att_att;att_blood;att_xxx等,然后在触发的时候,在MsgManager.emit(att_
+attName, attValue);
这样既不会和其他消息冲突,也不会让节点的名字和非属性节点的名字冲突,怎么灵活怎么来,要会变通嘛,我上面的代码只是提供一种思路!
再说,你的非属性节点不挂这个绑定脚本也不会影响非属性节点啊,我都被你带偏了。。。。。。。