循环引用这个报错太恶心了

千万不要去除这个警告,而且我发觉每个creator的版本的警告还不一样。希望出现完整的循环引用的警告,最好是在每次修改脚本的时候进行循环引用的警告而不是在编译时候出现,引用循环的问题其实比较好解决,说明是代码模块不够清晰,这个警告方便开发人员调整模块

看怎么引用,我这边的循环引用也不影响运行,一样是creator项目,所以嘛,看代码怎么写而已

开发可以,打包运行会有问题

没问题,打包运行都没问题!

这可以避免 90% 循环引用问题:

import type {A} from 'a' 

如果确实要把 A 作为值使用, 那说明应该重构一下.

3赞

就算结构合理也会出现这种情况的使用场景,比如 ui 父类和子类同时引用了 ui 管理器来回收自己或者子节点,不是什么情况都需要重构,重构只适用于结构不合理,结构合理出现循环引用就可以用动态 import 就可以避免

后面的朋友可以参考我这篇帖子

确实是个有效的办法, 除了不能用在 @property(xx).


不过, 这种 Manager / Item 的模式,

通常是 Item 调用 Manager.instance.add / remove(this);

因此 Manager 只用 import type {Item} from 'item';

Item 这边用普通 import {Manager} from 'mgr';

不可能,就比如我的 ui 管理器,就需要使用 getComponent(ui组件类型)

当然, 需求是多变的. 这种情况用 import() 确实最简单直接.

也有些其他办法,

  • getComponent(COMP_NAME). // export const COMP_NAME=xxx … @ccclass(COMP_NAME) …
  • 写个空的 BaseItemComp 然后用 instanceof 在 components 里找.
  • ServiceLocator (引擎里的 legacyCC 差不多就这个作用吧)

不过 90% 的时候, 我更愿意消除循环引用本身, 而不是让它合理化.

那就更说明引擎要解决了,因为如果你遇到了另外的10%怎么办

ts怎么搞?遇到过一次,获取组件 tiemNode.getComponent(XXX); 然后XXX就导致了循环引用。关键Ts没办法用字符串"XXX"去获取组件。最后只能放弃在这里面获取这个组件~循环引用应该是一种比较常见的现象,不单单是什么重构去解决吧。

循环引用实际上就是耦合过紧,代码设计层面的问题,很多设计模式解耦的很大程度解决了这类问题。最简单直接的方法就是全局单例化manager,在manager中去操作其他全局manager和a,b,c,d对象

实在不行自定义全局事件,两边拿到的引用只是GlobalEventManager之类的

let aa=tiemNode.getComponent(“XXX”)
//@ts-ignore
aa.bb()
//如果想要消除循环引用,那就只能通过接口的方式去消除了,目测ts还不大好实现,总之我没试过,试过后再回复

这种方式是我目前在用的,通过事件监听来解耦,但是目测不大舒服

事件推动的后期维护麻烦的很。

1赞

同感~~~

非继承导致的循环引用错误基本都是架构不合理
如果是多个继承类型引用同一模块导致循环引用就用我上面说的动态导入

肯定是继承导致的。
我说的情况属于,A继承R,R继承C,B也继承C,在B里面只是想在碰撞中通过other.getComponent(A)获取一个属性用来判断而已~

?? 显然是你记错了. 而且 import type 解决了类型提示的问题.


// manager.ts

import type {Item} from './item';
export const ITEM_COMP = 'xxx';

@ccclass
export class Manager extends Component
{
  some_method()
  {
     (<Item> this.node.children[0].getComponent(ITEM_COMP)).foo();
  }
}

// item.ts

import {ITEM_COMP, Manager} from './manager';

@ccclass(ITEM_COMP)
export class Item extends Component 
{
    foo() { Manager.instance.bar() } 
}