I try to rotate object according normal rotation of terrain. More over this object should move. And I need to combine z and x from normal of terrain and y which rotates to target. I tried this but result is quiet weird:

function getTerrainRot(myTarget:Vector3,terrPos: Vector3,modelRot:Quaternion){
var terrHit: RaycastHit;
var dirQuat: Quaternion;
var newPos: Vector3;
if(Physics.Raycast (terrPos, -Vector3.up,terrHit, 10.0))
{	
        newPos = getPosAndTerrainY(myTarget) - terrPos;
		normal_q = Quaternion.FromToRotation(Vector3.up, terrHit.normal);
        terr_q = normal_q * Quaternion.AngleAxis(modelRot.eulerAngles.x, terrHit.normal);

		dirQuat = Quaternion.LookRotation(newPos);
		terr_q = Quaternion(terr_q.x,dirQuat.y,terr_q.z,dirQuat.w);

}
return Quaternion.Slerp(modelRot, terr_q, Time.deltaTime);
}

Thanks

You’re having weird results because you’ve messed with the components of a Quaternion - despite their names, they have nothing to do with the axes x, y and z.

If you want the character to keep looking to newPos direction while following the surface normal, you can use LookRotation(newPos, normal) - the second parameter indicates the up direction. About the surface normal: it’s better to keep a curNormal variable and Lerp it to the surface normal (or Vector3.up, if no terrain hit) to smooth the character orientation:

var curNormal = Vector3.up;

function getTerrainRot(myTarget:Vector3,terrPos: Vector3): Quaternion; {
    var terrHit: RaycastHit;
    var newPos: Vector3;
    var normal = Vector3.up;
    if(Physics.Raycast (terrPos, -curNormal, terrHit, 10.0)){
        normal = terrHit.normal;
    }
    curNormal = Vector3.Lerp(curNormal, normal, 2*Time.deltaTime);   
    newPos = getPosAndTerrainY(myTarget) - terrPos;
    return Quaternion.LookRotation(newPos, curNormal);
}

EDITED: You’re right: LookRotation in this case doesn’t work as expected - it prefers to look at the target direction and completely ignores the normal!

Let’s go back to the basics: calculate a rotation from Vector3.up to curNormal (as you already did), than multiply by the horizontal rotation from Vector3.forward to the target direction (multiplication in the Quaternion world actually combines the rotations):

var curNormal = Vector3.up;

function getTerrainRot(myTarget:Vector3,terrPos: Vector3): Quaternion {
    var terrHit: RaycastHit;
    var newPos: Vector3;
    var normal = Vector3.up; // default normal = up
    if (Physics.Raycast (terrPos, -curNormal, terrHit, 10.0)){
        normal = terrHit.normal; // use the surface normal, if any
    } // smoothly follow the surface normal
    curNormal = Vector3.Lerp(curNormal, normal, 2*Time.deltaTime);   
    newPos = myTarget - terrPos; // get the direction to look at
    newPos.y = 0; // zero y to keep only the horizontal direction
    // calculate rotation to normal
    var rot = Quaternion.FromToRotation(Vector3.up, curNormal);
    // combine with the horizontal rotation
    rot = rot * Quaternion.FromToRotation(Vector3.forward, newPos);
    return rot;
}