Решили: владелец пула (CombatVfx) каждый кадр подбирает эффекты, которые выключили чужой рукой, и возвращает их себе (ReclaimOrphans). Сторожит именно он, а не сам эффект.

Почему: страховка по сроку жизни считается в Update эффекта, а выключенный объект не тикает — вместе с тиком замирает и страховка. Эффект остаётся «играющим» навсегда: пул его не получил, показывать некому, а при следующем включении он оживает с прежним состоянием.

Отвергли возврат по OnDisable у самого эффекта. Он короче, но опирается на чужую руку — на того, кто выключил родителя, — и потому непроверяем: в EditMode вне Play Mode Unity не зовёт OnDisable ребёнку при выключении родителя вовсе. Проверено зондом: activeInHierarchy уже false, а счётчик вызовов ноль. Пул живёт всегда, спросить «этот ещё играет?» может только он, и делает он это методом, который тест зовёт напрямую.

Грабли: симптом выглядел как баг самой дуги, а оказался про иерархию. Дуга за клинком переезжает ВНУТРЬ тела бьющего, а вид юнита уходит в свой пул вместе со смертью. Дуга гаснет ребёнком, срок стоит — и застрявший росчерк появляется снова, когда вид переиспользуют под нового бойца. Отсюда обе странности в жалобе: «иногда» (только при смерти в нужный момент) и «не синхронизировано» (смерти и переиспользование видов на машинах разные).

Первая версия починки была неверной и прошла бы ревью: OnDisable в PooledVfx выглядит очевидно правильным и в рантайме сработал бы. Поймал его тест — не логикой, а тем, что отказался зеленеть.

Сказано: «Багается VFX эффект слеша за мечом. Он иногда.. эм… остается просто видеть и не исчезает? При чем это не сихронизировано, что забавно, т.е. у одного из 2 встречается иногда» (08.08.2026, сессия eab27015).

Не проверено глазами: раскадровку снять не удалось — редактор был занят игрой. Правка меняет только момент возврата в пул и не трогает ни один кадр самой дуги, но правило «тронул VFX — посмотри раскадровку» здесь осталось невыполненным.

Владелец правды: CombatVfx.ReclaimOrphans, PooledVfx.IsPlaying, тест PooledVfxReturnTests.