Zenject中ITickable绑定为Transient时Tick()不调用的解决方法
Zenject中Transient模式下ITickable实例的Tick方法不执行的解决方案
问题原因
Zenject的ITickable更新机制默认只会自动追踪**单例(Singleton)**实例:容器会持有单例的唯一引用,并自动将其加入Tick循环队列。而当使用AsTransient()绑定ITickable实现类时,每次注入都会创建新实例,容器不会保留这些实例的引用,因此不会自动将它们注册到Tick系统中,导致Tick()方法无法被调用。
解决方案
方案1:在Timer类内部手动注册/注销Tickable
通过在Timer的构造函数中注入ITickableManager,手动将自身注册到Tick队列,同时实现IDisposable来处理注销,避免内存泄漏:
using Zenject; public class Timer : ITickable, IDisposable { private readonly ITickableManager _tickableManager; public Timer(ITickableManager tickableManager) { _tickableManager = tickableManager; // 注册到Tick循环 _tickableManager.AddTickable(this); } public void Tick() { // 编写你的每帧执行逻辑 } public void Dispose() { // 从Tick循环中移除,避免内存泄漏 _tickableManager.RemoveTickable(this); } }
绑定方式保持不变:
Container.BindInterfacesAndSelfTo<Timer>().AsTransient();
注意:当Timer实例不再被使用时,务必调用
Dispose()方法(比如在依赖该Timer的对象销毁时)。
方案2:通过绑定回调自动注册/注销
无需修改Timer类,在绑定配置中通过OnInstantiated和OnDestroyed回调完成Tickable的注册与注销:
using Zenject; Container.BindInterfacesAndSelfTo<Timer>() .AsTransient() .OnInstantiated<Timer>((context, timer) => { // 实例创建后注册到Tick循环 var tickableManager = context.Container.Resolve<ITickableManager>(); tickableManager.AddTickable(timer); }) .OnDestroyed<Timer>((context, timer) => { // 实例销毁时从Tick循环移除 var tickableManager = context.Container.Resolve<ITickableManager>(); tickableManager.RemoveTickable(timer); });
这种方式将Tickable的管理逻辑集中在绑定配置中,保持Timer类的职责单一。
内容的提问来源于stack exchange,提问作者Viacheslav M
相关产品推荐
相关产品推荐

