I'm particularly stuck on this, how do I rotate a object tangent to a incline? I've tried code presented in some answers but I often end up with choppy movement, or incorrect rotation on the z and x axis. Many signs point to starting out from this:
You are more or less on the correct track, but the solution is highly dependent on your use case and your setup. If using a character controller and only aligning on collisions, then the code you posted is one way. Using a raycast is a more general solution.
To align to a surface (or tangent if you like), the starting point would be the normal of the surface to which you wish to align. This would become your up vector if you are aligning to the surface. If you are aligning your up to be tangent to the surface, then you would rotate this normal upon the the binormal axis.
Your choppy movement is likely from suddenly changing the orientation. To smooth your movement/orientation, you could lerp or slerp between the orientations as the case demands. Something like:
var orientationTime : float = 1.0f;
private var surfaceNormal : Vector3 = Vector3.up;
private var surfaceOrientation : Quaternion = Quaternion.identity;
private var oldOrientation : Quaternion = Quaternion.identity;
private orientationStep : float = 1.0f;
function Start() {
surfaceNormal = transform.up;
surfaceOrientation = transform.rotation;
//Or raycast and calculate
}
//Wherever you get your surface normal
var oldSurfaceNormal : Vector3 = surfaceNormal;
surfaceNormal = //Get your surfaceNormal
if(oldSurfaceNormal != surfaceNormal) {
oldOrientation = transform.rotation;
var forward = Vector3.OrthoNormalize(surfaceNormal,transform.forward);
surfaceOrientation = Quaternion.LookRotation(forward,surfaceNormal);
orientationStep = 0.0f;
}
function Update() {
//Every frame, gradually move towards that orientation
if(orientationStep < 1.0f) {
orientationStep += Time.deltaTime/orientationTime;
transform.rotation = Quaternion.Slerp(oldOrientation,
surfaceOrientation,
orientationStep);
}
}
If you wanted to ease in and out, you could use Mathf.SmoothStep(orientationStep), but that would require some catches if you are already part way through a rotation when you decide to reorient. If you only wanted to ease out, you could rotate by a fixed amount from transform.rotation in stead of storing an oldOrientation (but you will never reach the orientation exactly this way). If you wanted to fix rotation speed/duration, you could use RotateTowards.