pixi-spine 动画元素在自定义事件的回调用去删除另外一个不相关的界面动画元素报错

439 阅读2分钟

原因

pixi-spine的更新方法是同步调用pixi-js的更新方法的,并且把当前动画对象传给了pixi-js进行更新,双方都没有做任何限制处理,因为pixi-js这边删除了元素,但是pixi-spine没有,还把这个动画对象传给pixi-js,就直接报错

报错信息

Uncaught TypeError: Cannot read properties of undefined (reading 'visible')

心路历程

报错的第一反应,我以为是调用destroy方法删除元素导致其他哪里没关停,还在一直调用导致的,但,很可惜我把所有监听都关了,直接删也是报错,只要是在pixi-spine的事件中删除的,都会这样,然后我就去github上找,结果官方的问题库里面19年就有人提过,因为用不到后续版本的,所以不知道后续有没有修复这个问题

官方问题地址

源码信息

// pixi-spine
PIXI.spine.Spine.prototype.autoUpdateTransform = function () {
  if (PIXI.spine.Spine.globalAutoUpdate) {
    this.lastTime = this.lastTime || Date.now();
    var timeDelta = (Date.now() - this.lastTime) * 0.001;
    this.lastTime = Date.now();
    this.update(timeDelta);
  }
  else {
    this.lastTime = 0;
  }
  // 这句是重点,同步调用,并且把当前动画对象this绑定了过去
  PIXI.Container.prototype.updateTransform.call(this);
};
// pixi-js
PIXI.Container.prototype.updateTransform = function updateTransform() {
  this._boundsID++;
  this.transform.updateTransform(this.parent.transform);
  this.worldAlpha = this.alpha * this.parent.worldAlpha;
  for (var i = 0, j = this.children.length; i < j; ++i) {
    var child = this.children[i];
    //这里没有判断一下child是否还存在,就导致了报错
    if (child.visible) {
      child.updateTransform();
    }
    // 改,加个判断即可
     if (child&&child.visible) {
      child.updateTransform();
    }
  }
};

解决方法

  1. 可以在删除动画元素的外面套一层延时,setTimeout,但是github上有大佬说,这样的解决方法是丑陋的
  2. 就像我上边这样,直接改覆盖源码,不过大佬是改的pixi-spine的源码,就是 PIXI.Container.prototype.updateTransform.call(this) 这句加判断,不过我没成功,我在这个里面打印 this._destroyed一直是false,只有用到控制台,我手动把这个this对象展开,才可以看到 _destroyed属性变了,可能也是同步的原因,我没深挖,因为苦逼的我还要改bug
if (!this._destroyed) {
    Container.prototype.updateTransform.call(this);
}

总结

我这个是pixi@4.8的版本,pixi-spine@1.6.2的版本,因为公司需求不需要太高的版本,求稳,并且高版本的pixi-spine还要跟pixi-js的版本要匹配,很麻烦,不匹配的话动不动就报错的,因为pixi引擎和pixi-spine第三方库社区不是很活跃,所以百度什么的,具体问题很难搜索到答案,这里也是遇到了,记录一下