1.动态添加的脚本,脚本事件不执行。
写好了脚本XTimer,采用动态addComponent(Xtimer),但是脚本的start update都不执行。
代码如下:
var node = new cc.Node('[XTimer]') //调用新建的node的addComponent函数,会返回一个sprite的对象 node.addComponent(XTimer);
检查发现一切正常,就连输出添加后的alert("BBBBBBBBBBBBB:" + node.active + " " + ttt.enabled); 这两个值都是ture。而且发现将XTimer拖动到场景物体上就正常,只有动态添加的不正常。
后来发现是未给node设置父节点的问题。但我想把node就在场景跟节点中,所以在节点后添加如下代码。
var scene = cc.director.getScene(); node.setParent(scene);
OK,正常运行了。
====================================
2.getChildByName获取不到子物体。
今天发现getChildByName获取不到层次2次以上的子物体。如
var life2 = this.obj.getChildByName("dao/boxlife2");
找了很多资料才知道:
export default class ui_page_battle extends UIBaseWindow { public numid: string = "-1"; public _AwakeImpl() { this.numid = GUtil.GetUUID(); GUtil.BindOnClick(this.txtBtn, this.node, "txtBtnClick", "222"); XObserverCore.RegisterNotification(ConstDefineNotifiStr.note_mainplayerfall,this.OnGameOver); } public txtBtnClick(event, customEventData): void { // 这里 event 是一个 Event 对象,你可以通过 event.target 取到事件的发送节点 var node = event.target; var button: cc.Button = node.getComponent(cc.Button); //// 这里的 customEventData 参数就等于你之前设置的 "foobar" ////alert("btn:" + customEventData); ////button.node.destroy(); //button.node.y += 50; this.CreateNewPlayerToSence(); this.txtBtn.node.active = false; } public OnGameOver(param: EventParam): void { this.Btn_Reset.active = true;//以这种方式注册的订阅者在这里Btn_Reset 始终为undifine,就是根本就未定义。就连此时打印numid都是undefine证明观察者管理器调用的OnGameOver函数并非注册时该函数所在的对象。这里猜测着是js的机制,因为之前绑定按钮事件居然要指定函数所在的脚步名称、节点、以及函数名称。 } }
这里测试了很多总方法,如果是直接
ui_page_battle.Instance.OnGameOver();的话就一切正常,再次证明了上图委托调用的猜想。这里将代码修改为在匿名函数里调用居然正常了。
export default class ui_page_battle extends UIBaseWindow { public numid: string = "-1"; public _AwakeImpl() { this.numid = GUtil.GetUUID(); this.InitUIObject(); GUtil.BindOnClick(this.txtBtn, this.node, "txtBtnClick", "222"); XObserverCore.RegisterNotification(ConstDefineNotifiStr.note_mainplayerfall, (o) => { this.OnGameOver(o);//改成这样就正常了 }); this.txtBtn.node.active = false; } public KeyDebug(o: EventParam): void { //alert("999999999999999999999999:" + this.numid); } public _StartOpenImpl() { //alert("5555555555:"); //this.Btn_Reset.active = false; } public _UpdateImpl(dt) { //alert("333333333333333333333333333333:" + this.node.name + " " + this.Btn_Reset.name + " " + this.numid); } public _DestroyImpl() { } public txtBtnClick(event, customEventData): void { // 这里 event 是一个 Event 对象,你可以通过 event.target 取到事件的发送节点 var node = event.target; var button: cc.Button = node.getComponent(cc.Button); //// 这里的 customEventData 参数就等于你之前设置的 "foobar" ////alert("btn:" + customEventData); ////button.node.destroy(); //button.node.y += 50; this.CreateNewPlayerToSence(); this.txtBtn.node.active = false; } public OnGameOver(param: EventParam): void { this.Btn_Reset.active = true; } }
这里这个得特别注意。
附录:上面服的调用方法也可用下面这样调用:
start() { let self = this;//用self的方式调用就可避免undifine的问题 cc.loader.downloader.loadSubpackage('subpackages', function (err) { if (err) { return console.error(err); } self.LoadInit(); }); } private LoadInit() { this.gameCore = new GameCore(); this.gameCore.Register(); }
3.操作符远近的问题================================
var ui: UIBaseWindow = this.GetGameIngWindow(pageName);UI不为空 if (ui != null) {//为真 alert("2222222222222"); this.RemoveWindow(ui); ui.CloseWindow(() => { if (backcall != null) { backcall(); } }); } if (ui! = null) {!号和=号中建有了空格,此时条件为假 alert("2222222222222"); this.RemoveWindow(ui); ui.CloseWindow(() => { if (backcall != null) { backcall(); } }); }
4.设置局部坐标和世界坐标
item.setPosition(pos);
当item是世界根物体时 设置的坐标就是世界坐标,如果是子物体,就是设置它的局部坐标。
这里要特别注意多个子物体嵌套时,比如A。B。C。A是世界,B是A的自物体同时是C的父物体。且B如果局部坐标不为(0,0),这时如果将C的局部坐标转换为世界坐标是无法正确的。必须一级一级向上层层转换。
5.委托回调时调用this里的属性是undefined的问题。
如:
public useWeaponCtrl: UseWeaponControl; private start(){ let self = this; item.RegisterCollisionCall(self.OnCollisioned); } private OnCollisioned(layer: string, otherCollider: cc.Node) { var other = <cc.Node>otherCollider; switch (layer) { case "monster": var otherCtrl: IPlayerControl = other.getComponent(IPlayerControl); console.log("7777777777777777:", this.strkey); console.log("6666666666666:", layer, " ", this.useWeaponCtrl.node.getComponent(IPlayerControl)); otherCtrl.player.useFight.AcceptAtk(this.useWeaponCtrl.node.getComponent(IPlayerControl)); XAudio.Play("data/audio/audio_hurt", 1, false); break; } }
如果是以item.RegisterCollisionCall(self.OnCollisioned);这种方式回调,受限于js的底层架构问题,回调后再OnCollisioned()函数里这个对象是未定义的。比如
this.useWeaponCtrl就是undefined
解决方法是在注册委托时直接构建一个匿名函数,然后在匿名函数里调用本对象里的方法,就像下面这样。
public useWeaponCtrl: UseWeaponControl; private start(){ let self = this; item.RegisterCollisionCall((layer: string, other: cc.Node) => { self.OnCollisioned(layer, other); }); } private OnCollisioned(layer: string, otherCollider: cc.Node) { var other = <cc.Node>otherCollider; switch (layer) { case "monster": var otherCtrl: IPlayerControl = other.getComponent(IPlayerControl); console.log("7777777777777777:", this.strkey); console.log("6666666666666:", layer, " ", this.useWeaponCtrl.node.getComponent(IPlayerControl)); otherCtrl.player.useFight.AcceptAtk(this.useWeaponCtrl.node.getComponent(IPlayerControl)); XAudio.Play("data/audio/audio_hurt", 1, false); break; } }
这样调用就完全正确。
4.集合第二次判断为空的问题。
private RefreshWeaponList(): void { this.playerslist.Clear(); this.playerslist = XTask.GetAllTaskList(); console.log("7777777777777777777777777:"+this.playerslist.Count.toString()); }
这里this.playerslist.Clear();第一次执行没问题。但第二次执行时,由于playerlist已经等于了XTask.GetAllTaskList();且由于这里的playerlist是引用类型。所以第二次Clear会直接Clear掉
XTask.GetAllTaskList();这里可以去掉Clear。所以在第二行不要直接使用等于,使用AddRange就可以用Clear了。
----------