tl;dr:
How can I get the collision angle?
use Dot Product → ACOSd. It’d be something along the lines of:
ACOSd (hit SurfaceNormal DOT NormalisedVelocity) * 2
This should give you a 0-180 range in degrees.
Is there a reason why you’re doing all this rather than use actual physics?
I have a sphere in the world. I want the sphere to move at a constant speed. I want the sphere to change direction when it collides.
IF that’s what’s needed, the above seems overengineered. Since you want to take advantage of physics, rely on physics then. Full energy conservation can be achieved by configuring a physical material, overriding restitution and friction. Also, removing mass from a physically simulated body is asking for trouble, imho.
You’d need no script for the above and no special settings apart from removing drag (you’ve done this already) and creating a physical material.
If you absolutely must override physics (which can manifest as a bunch of odd issues further down the line), consider working with direction, not angle:
Alternatively, you could use mirrored velocity from the frame before the hit and skip Direction * Magnitude.
Converting to angles often leads to pigeonholing oneself into a corner, especially in 3D. On top of that, relying on generated physical hits will be awkward, as above. You might be better off using a floating movement component and emulate it instead with movement direction. Setting linear velocity per frame seems wasteful and defeats the purpose using physics in the first place.
Not sure what the real end goal is so I might be off my mark here.