Stopping broken subscriptions on Stop() or re-launching Subscriptions on Play()

When I execute a BehaviorScript and with a timeline subscription or physics subscription as in the class below, and an error occurs, the script execution stops, but the subscriptions remain.
When I then fix the error and on_init() is executed again, new subscriptions are stacked on top.

The cleanest workaround for me is to completely shut down and re-launch the Omniverse app once a while during development.

How can I get rid of this and have a clean subscription management?

import carb.events
import omni.physx as physx
from omni.kit.scripting import BehaviorScript
from omni.timeline import TimelineEventType


class PhysicsBehaviorScript(BehaviorScript):
    def on_init(self):
        self._timeline_sub = self.timeline.get_timeline_event_stream()\
            .create_subscription_to_pop(self.on_timeline_event)
        self._physics_sub = physx.get_physx_interface().subscribe_physics_step_events(self.on_physics_update)
        print("subscriptions initialized")

    def on_timeline_event(self, e: carb.events.IEvent):
        type = TimelineEventType(e.type)
        if type == TimelineEventType.PLAY:
            self.on_play()
        elif type == TimelineEventType.PAUSE:
            self.on_pause()
        elif type == TimelineEventType.STOP:
            self.on_stop()

    def on_update(self, current_time: float, delta_time: float):
        pass

    def on_physics_update(self, delta_time):
        pass

    def on_play(self):
        pass

    def on_pause(self):
        pass

    def on_stop(self):
        pass

    def on_destroy(self):
        self._physics_sub = None
        self._timeline_sub = None

    def __del__(self):
        self.on_destroy()

Hi @MartinBischoff. You’re doing the right thing and unsubscribing in the on_destroy(). This will be called when the script is saved/reloaded. We have seen this issue of zombie subscriptions in extension development and the team is working to address that to make it more pythonic with the subscriptions always being auto-cleaned up. I imagine if you’re running into this it’s infrequent? The class you shared worked fine for me in my short testing.

Btw, I noticed you’re subscribing to timeline events, but the class already has a subscription for that so code inon_play(), on_pause(), and on_stop() is executing twice.

Thank you for this answer @mati-nvidia .

These zombie subscriptions as you call them occur far too frequently (one in ten times would be too much).
Honestly, I got scared of saving code intermediate states in Python before checking twice that I have good chances that my code has good chances to work. Killing and restating an Omniverse App distracts and costs too much time. Thinking about when to save or not distracts me from thinking about my actual developments.

Thanks for the hint on on_play() , on_pause() , and on_stop(). I will adjust the class accordingly. I hadn’t found any documentation on this anywhere before. Instead, I found this code in your livestream here Getting Started: Python Scripting Components | Omniverse Community Stream - YouTube .

You should get a good template when you create a new script from the Content window:

We have an internal issue, OM-73337, that is being worked on to address the zombie subscriptions. I’ve added this forum issue as a story point for that ticket.