您的位置:首页 > 移动开发 > Unity3D

unity, 让主角头顶朝向等于地面法线(character align to surface normal)

2015-03-31 12:48 423 查看
计算过程如下:

1,通过由主角中心raycast一条竖直射线获得主角所在处地面法线,用作主角的newUp。

注:一定要从主角中心raycast,而不要从player.transform.position,因为如果player的模型原点在脚上,则player.transform.position可能就在地面以下了,向下raycast得不到与地面的交点了就。

2,根据主角forward和newUp计算newForward。

3,使用Quaternion.LookRotation (newForward, newUp)获得主角新的rotation。

结果如图:





代码:

     //note, the code here suppose our character use a capsuleCollider and the floors' layerMask is "floor"..

     //..if yours' is not, you should make some change.

RaycastHit hitInfo;
Vector3 capsuleColliderCenterInWorldSpace=GetComponent<CapsuleCollider> ().transform.TransformPoint (GetComponent<CapsuleCollider>().center);
bool isHit=Physics.Raycast (capsuleColliderCenterInWorldSpace,new Vector3(0f,-1f,0f),out hitInfo,100f,LayerMask.GetMask("floor"));

Vector3 forward=GetComponent<Rigidbody>().transform.forward;

Vector3 newUp;
if (isHit) {
newUp = hitInfo.normal;
} else {
newUp = Vector3.up;
}

     //limit lean angle (if do not need to limit lean angle, remove the code block below)

     {

       const float maxDegreeFromWorldUp = 45.0f;//lean angle limited to 45 degree
//clamp newUp to let is not exceed 45 degree from WorldUp(Vector3.up)
newUp=Vector3.RotateTowards (Vector3.up, newUp, maxDegreeFromWorldUp / 180.0f * Mathf.PI, 0.0f);

     }
Vector3 left = Vector3.Cross (forward,newUp);//note: unity use left-hand system, and Vector3.Cross obey left-hand rule.
Vector3 newForward = Vector3.Cross (newUp,left);
Quaternion oldRotation=GetComponent<Rigidbody>().transform.rotation;
Quaternion newRotation = Quaternion.LookRotation (newForward, newUp);

     float kSoftness=0.1f;//if do not want softness, change the value to 1.0f
GetComponent<Rigidbody> ().MoveRotation (Quaternion.Lerp(oldRotation,newRotation,kSoftness));
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: