赞
踩
目录
Unity Mecanim动画系统 之 IK(Inverse Kinematics即反向动力学)的相关说明和简单使用
Unity中的一些基础知识点。便于后期开发使用。
Unity动画系统,也称为“Mecanim”,提供了以下功能:
IK可以使人物和场景更加贴合,从而达到更加真实的游戏效果。
IK(Inverse Kinematics)即反向动力学,即可以使用场景中的各种物体来控制和影响角色身体部位的运动,一般来说骨骼动画都是传统的从父节点到子节点的带动方式(即正向动力学),而IK则倒过来,由骨骼子节点带动骨骼父节点,具体情况比如人物走路踩到了石头就需要由脚的子节点来带动全身骨骼做出踩到石头的响应。
Unity中IK能设置的部位就是10个,分别是:头、左右手、左右脚、身体、左右手肘,左右膝盖
1)两个API:Animator.SetLookAtPosition和Animator.SetLookAtWeight
public void SetLookAtPosition(Vector3 lookAtPosition);
这个方法用来设置头部看向的位置,比如看向你左边的窗户,头就会相应的旋转。
2)public void SetLookAtWeight(float weight, float bodyWeight = 0.0f, float headWeight = 1.0f, float eyesWeight = 0.0f, float clampWeight = 0.5f);
这个方法用来设置IK的权重,这个IK会和原来的动画进行混合。如果权重为1,则完全用IK的位置旋转;如果权重为0,则完全用原来动画中的位置和旋转,参数说明:
Weight 全局权重,后面所有参数的系数
1)API:
public void SetIKPosition(AvatarIKGoal goal, Vector3 goalPosition);
public void SetIKRotation(AvatarIKGoal goal, Quaternion goalRotation);
public void SetIKHintPosition(AvatarIKHint hint, Vector3 hintPosition);
手和脚,需要同时设置位置和旋转。
goal AvatarIKGoal枚举类型,包含:
LeftFoot 左脚
RightFoot 右脚
LeftHand 左手
RightHand 右手
hint AvatarIKHint 枚举类型,包含:
LeftKnee 左膝盖
RightKnee 右膝盖
LeftElbow 左手肘
RightElbow 右手肘
goalPosition/goalRotation IK目标位置/旋转
2)同样还有设置权重的API:
public void SetIKPositionWeight(AvatarIKGoal goal, float value);
public void SetIKRotationWeight(AvatarIKGoal goal, float value);
public void SetIKHintPositionWeight(AvatarIKHint hint, float value);
goal AvatarIKGoal / AvatarIKHint 枚举类型
value IK的权重,1代表完全使用IK值,0代表使用原动画的值
0、必须是新动画系统Animator。
1、动画类型必须是Humanoid。
2、需要勾选对应Layer的IK Pass选项(在Layer的设置里)。
3、代码需要写在OnAnimatorIK这个事件方法里面。
简单实现 IK 五个部分的 IK 控制
1、新建工程,导入模型
2、新建一个 Animator Controller 控制器,并添加一个动画
3、 Animator Controller 设置中,勾选 IK Pass ,这样 IK 功能才能生效
4、把模型导入场景中,并添加对应控制球,用来 IK 控制其动画
5、把 Animator Controller 赋值个模型
6、新建一个脚本,控制是否激活 IK,不激活正常状态,激活可以 IK 球控制动画
7、把脚本,挂载到场景中,对并对应赋值
8、运行场景,效果如下
9、后期要做动作模拟,只要把数据动态对应赋值到控制球上即可
-
- using UnityEngine;
-
- /// <summary>
- /// IK 控制
- /// </summary>
- public class IKController : MonoBehaviour
- {
- // 身体
- public Transform bodyObj = null;//与相关球体对应
-
- // 左脚
- public Transform leftFootObj = null; //与相关球体对应
-
- // 右脚
- public Transform rightFootObj = null; //与相关球体对应
-
- // 左手
- public Transform leftHandObj = null; //与相关球体对应
-
- // 右手
- public Transform rightHandObj = null; //与相关球体对应
-
- // 头的观察点
- public Transform lookAtObj = null; //与相关球体对应
-
- // 右手肘
- public Transform rightElbowobj = null; //与相关球体对应
-
- // 左手肘
- public Transform leftElbowobj = null; //与相关球体对应
-
- // 右膝盖
- public Transform rightKneeobj = null; //与相关球体对应
-
- // 左膝盖
- public Transform leftKneeobj = null; //与相关球体对应
-
-
-
-
- // 动画机
- private Animator avatar;
-
- // 是否激活 IK
- private bool ikActive = false;
-
-
-
- void Start()
-
- {
- //获取动画机
- avatar = GetComponent<Animator>();
-
- }
-
-
-
- void Update()
- {
- // 如果 IK 没有激活
- // 把对应的控制部分附上动画自身的值
- if (!ikActive)
- {
-
- if (bodyObj != null)
- {
-
- bodyObj.position = avatar.bodyPosition;
-
- bodyObj.rotation = avatar.bodyRotation;
-
- }
-
-
-
- if (leftFootObj != null)
- {
-
- leftFootObj.position = avatar.GetIKPosition(AvatarIKGoal.LeftFoot);
-
- leftFootObj.rotation = avatar.GetIKRotation(AvatarIKGoal.LeftFoot);
-
- }
-
-
-
- if (rightFootObj != null)
- {
-
- rightFootObj.position = avatar.GetIKPosition(AvatarIKGoal.RightFoot);
-
- rightFootObj.rotation = avatar.GetIKRotation(AvatarIKGoal.RightFoot);
-
- }
-
-
-
- if (leftHandObj != null)
- {
-
- leftHandObj.position = avatar.GetIKPosition(AvatarIKGoal.LeftHand);
-
- leftHandObj.rotation = avatar.GetIKRotation(AvatarIKGoal.LeftHand);
-
- }
-
-
-
- if (rightHandObj != null)
- {
-
- rightHandObj.position = avatar.GetIKPosition(AvatarIKGoal.RightHand);
-
- rightHandObj.rotation = avatar.GetIKRotation(AvatarIKGoal.RightHand);
-
- }
-
-
-
- if (lookAtObj != null)
- {
-
- lookAtObj.position = avatar.bodyPosition + avatar.bodyRotation * new Vector3(0, 0.5f, 1);
-
- }
-
-
-
- if (rightElbowobj != null)
- {
-
- rightElbowobj.position = avatar.GetIKHintPosition(AvatarIKHint.RightElbow);
-
-
- }
-
- if (leftElbowobj != null)
- {
-
- leftElbowobj.position = avatar.GetIKHintPosition(AvatarIKHint.LeftElbow);
-
-
- }
-
- if (rightKneeobj != null)
- {
-
- rightKneeobj.position = avatar.GetIKHintPosition(AvatarIKHint.RightKnee);
-
-
- }
-
- if (leftKneeobj != null)
- {
-
- leftKneeobj.position = avatar.GetIKHintPosition(AvatarIKHint.LeftKnee);
-
-
- }
-
- }
-
-
-
- }
-
-
- /// <summary>
- /// IK 动画的控制专用函数
- /// </summary>
- /// <param name="layerIndex">动画层</param>
- void OnAnimatorIK(int layerIndex)
- {
- // 动画机为空,返回
- if (avatar == null)
-
- return;
-
-
- // 激活 IK
- //1、 各部分权重赋值 1
- //2、 各部分位置赋值
- //3、 部分旋转赋值
- if (ikActive)
- {
-
- avatar.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 1.0f);
-
- avatar.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 1.0f);
-
-
-
- avatar.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1.0f);
-
- avatar.SetIKRotationWeight(AvatarIKGoal.RightFoot, 1.0f);
-
-
-
- avatar.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1.0f);
-
- avatar.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1.0f);
-
-
-
- avatar.SetIKPositionWeight(AvatarIKGoal.RightHand, 1.0f);
-
- avatar.SetIKRotationWeight(AvatarIKGoal.RightHand, 1.0f);
-
-
-
- avatar.SetLookAtWeight(1.0f, 0.3f, 0.6f, 1.0f, 0.5f);
-
-
- avatar.SetIKHintPositionWeight(AvatarIKHint.RightElbow, 1.0f);
- avatar.SetIKHintPositionWeight(AvatarIKHint.LeftElbow, 1.0f);
- avatar.SetIKHintPositionWeight(AvatarIKHint.RightKnee, 1.0f);
- avatar.SetIKHintPositionWeight(AvatarIKHint.LeftKnee, 1.0f);
-
-
- if (bodyObj != null)
- {
-
- avatar.bodyPosition = bodyObj.position;
-
- avatar.bodyRotation = bodyObj.rotation;
-
- }
-
-
-
- if (leftFootObj != null)
- {
-
- avatar.SetIKPosition(AvatarIKGoal.LeftFoot, leftFootObj.position);
-
- avatar.SetIKRotation(AvatarIKGoal.LeftFoot, leftFootObj.rotation);
-
- }
-
-
-
- if (rightFootObj != null)
- {
-
- avatar.SetIKPosition(AvatarIKGoal.RightFoot, rightFootObj.position);
-
- avatar.SetIKRotation(AvatarIKGoal.RightFoot, rightFootObj.rotation);
-
- }
-
-
-
- if (leftHandObj != null)
- {
-
- avatar.SetIKPosition(AvatarIKGoal.LeftHand, leftHandObj.position);
-
- avatar.SetIKRotation(AvatarIKGoal.LeftHand, leftHandObj.rotation);
-
- }
-
-
-
- if (rightHandObj != null)
-
- {
-
- avatar.SetIKPosition(AvatarIKGoal.RightHand, rightHandObj.position);
-
- avatar.SetIKRotation(AvatarIKGoal.RightHand, rightHandObj.rotation);
-
- }
-
-
-
- if (lookAtObj != null)
-
- {
-
- avatar.SetLookAtPosition(lookAtObj.position);
-
- }
-
- if (rightElbowobj != null)
-
- {
-
- avatar.SetIKHintPosition(AvatarIKHint.RightElbow, rightElbowobj.position);
-
-
-
- }
-
- if (leftElbowobj != null)
-
- {
-
- avatar.SetIKHintPosition(AvatarIKHint.LeftElbow, leftElbowobj.position);
-
-
-
- }
-
- if (rightKneeobj != null)
-
- {
-
- avatar.SetIKHintPosition(AvatarIKHint.RightKnee, rightKneeobj.position);
-
-
-
- }
-
- if (leftKneeobj != null)
-
- {
-
- avatar.SetIKHintPosition(AvatarIKHint.LeftKnee, leftKneeobj.position);
-
-
-
- }
-
- }
-
- // 不激活 IK
- //1、 各部分权重赋值 0
- else
- {
-
- avatar.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 0);
-
- avatar.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 0);
-
-
-
- avatar.SetIKPositionWeight(AvatarIKGoal.RightFoot, 0);
-
- avatar.SetIKRotationWeight(AvatarIKGoal.RightFoot, 0);
-
-
-
- avatar.SetIKPositionWeight(AvatarIKGoal.LeftHand, 0);
-
- avatar.SetIKRotationWeight(AvatarIKGoal.LeftHand, 0);
-
-
-
- avatar.SetIKPositionWeight(AvatarIKGoal.RightHand, 0);
-
- avatar.SetIKRotationWeight(AvatarIKGoal.RightHand, 0);
-
-
-
- avatar.SetLookAtWeight(0.0f);
-
-
- avatar.SetIKHintPositionWeight(AvatarIKHint.RightElbow, 0);
- avatar.SetIKHintPositionWeight(AvatarIKHint.LeftElbow, 0);
- avatar.SetIKHintPositionWeight(AvatarIKHint.RightKnee, 0);
- avatar.SetIKHintPositionWeight(AvatarIKHint.LeftKnee, 0);
-
- }
-
- }
-
-
- /// <summary>
- /// UI
- /// </summary>
- void OnGUI()
- {
-
- GUILayout.Label("激活IK然后在场景中移动Effector对象观察效果");
-
- ikActive = GUILayout.Toggle(ikActive, "激活IK");
-
- }
- }
该插件是对Unity本身的IK的优化和增强,可以模拟出更加真实的效果,有兴趣可以看一看。
https://www.assetstore.unity3d.com/cn/#!/content/14290
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。