You're looking for OnEnable for establishing your connection, and OnDisable for cleaning it up.
The issue with OnDestroy (and OnApplicationQuit fwiw) is it won't be called if the script is disabled, which can happen if:
- You call
SetActive(false) on the GameObject or any of its parents.
- You set
enabled = false on the script component.
- You disable the
GameObject or any of its parents in play mode by unchecking the box in the inspector.
- You disable the script component in play mode by unchecking the box in the inspector.
- The editor is about to recompile the scripts while play mode is running (an especially irritating event to miss for certain types of cleanup code [cough lookin' at you, Vuforia]).
The issue with Start is it won't be called if the script is re-enabled after having been disabled (it'll be called the first time, but no more), which happens in all of the cases opposite of the above list (as well as when the editor finishes recompilation of scripts in play mode).
On the other hand:
OnDisable will be called when the script transitions to disabled for any of the above reasons, plus all the stuff that OnDestroy and OnApplicationQuit cover.
OnEnable will be called when the script transitions to enabled for any of the above reasons, plus all the stuff that Start covers.
Additionally, you will have a 1:1 correspondence of OnEnable and OnDisable calls by Unity (of course you can call them yourself whenever you want).
You will only almost have a 1:1 correspondence of Start and OnDestroy: The notable exception is if a script component is initially disabled (i.e. you disabled it in edit mode) but its GameObject is enabled, you'll still get OnDestroy called on the script even if Start wasn't called (which may be a bug now that I think about it). Plus, of course, you will miss all the above cases.
OnEnable + OnDisable, however, handle all that cleanly, and generally do exactly what you hope that they do, in a straightforward manner with (theoretically) no weird quirks or gotchas.
For the question itself, yes, OnDestroy is reliable: It is called as documented when the script is destroyed.
Of course it wouldn't be called if the application crashes, but in general you'd have bigger problems and that's not the kind of thing you normally code around. It also probably wouldn't be called if you exploded a grenade next to the machine running the game but, again, that's all in "undefined behavior" territory.