It is sometimes beneficial to change the motiontype of a Havok-simulated object to Motion_Keyframed. This allows you to perform translations on the object while ignoring the physics engine and is all very fine and splendid, right up until one of two points:
- You want to change the object back to Motion_Dynamic to "release" it back to Havok.
- You want to delete the object.
Here's a simple example of 1:
Rock.SetMotionType(Rock.Motion_Keyframed)Rock.TranslateToRef(PlayerREF,100)Rock.SetMotionType(Rock.Motion_Dynamic) ;//This line will almost certainly crash
Avoiding a crash on changing the motiontype is pretty simple: Call StopTranslation on the object immediately before changing its motiontype away from Motion_Keyframed, and make sure nothing in your script is likely to restart the translation before the SetMotionType function is executed:
Rock.SetMotionType(Rock.Motion_Keyframed)Rock.TranslateToRef(PlayerREF,100)Rock.StopTranslation() ;//Make sure the rock stops movingRock.SetMotionType(Rock.Motion_Dynamic) ;//This line should be safe now
Avoiding a crash while deleting an object after you have played with its motiontype is a bit trickier. The odds on a crash occurring on deletion go up if...
- The object is deleting itself from a script attached to it.
- The object is in mid-translation.
- The object has traveled out of the current cell.
Self.SetMotionType(Self.Motion_Keyframed)Self.TranslateToRef(PlayerREF,100)Utility.Wait(1)Self.StopTranslation()Self.Delete() ;//This line has a very high chance of crashing
If you want to see this crash for yourself, duplicate one of the physics trap rock Activators and add a script to it that changes its motiontype to
Motion_Keyframed, translates it a short distance, then deletes it. Place your new Activator at your location in-game and you'll probably see the crash as soon as the Delete function is called. If not, try again. It shouldn't take more than 2-3 of these to crash you good.
The CTD-on-Delete bug is very peculiar and hard to pin down, particularly since it only crashes about 60% of the time (without any of the exacerbating effects mentioned above). Using StopTranslation and even setting the motiontype back to Dynamic does not help. However, the following practices do:
- Deleting the object from another script seems to drastically reduce but not eliminate the chance of a crash.
- Use StopTranslation to make sure this object is not translating when it gets deleted reduces the chance of a crash.
- Avoid a lot of (any?) code in the object's onUnload event, as this seems to increase the chance of a crash.
- THIS IS THE IMPORTANT ONE: At the point in the script when the object would normally be deleted, Disable it instead and use http://www.creationkit.com/DeleteWhenAble_-_ObjectReference. Bear in mind that DeleteWhenAble halts the current thread's execution until deletion actually occurs, so make sure it's the last command called in your Event or Function.
- If your situation allows for it, make sure the object doesn't persist outside the player's cell by attaching the Disable/DeleteWhenAble combo to the object's OnCellDetach event.
Hope this helps anyone who has run into this (admittedly obscure) bug! It's been interfering with my work for some time now and I am very glad to have it (hopefully) squashed!