I rarely enter an interactive debugger. I have TONS of logging statements I can toggle. I make program execution as deterministic and reproducible as possible (for example, all random numbers are generated from random number generators that are passed around). When something goes wrong, I turn on (or add) logging and run it again. Look for odd stuff in the log files. If it doesn't make sense, add more logging. Repeat.
I worked on a pretty large videogame in the 90s where /everything/ was reproducible from a "recording" of timestamped input that was automatically generated. The game crashed after half an hour of varied actions? No problem, just play the recording that was automatically saved and attached to the crash report. It was amazing how fast we fixed bugs that might otherwise take weeks to track down.