Unity3D 实用技巧 - 理解骨骼动画原理 & 在Unity3D中使用

其实我们在游戏中,会常会应用到动画。所以今天小编与大家一起来深入了解“动画”,其实动画主要分为关节动画、骨骼动画、单一网格模型动画(关键帧动画)。
1)关节动画:把角色分成若干独立部分,一个部分对应一个网格模型,部分的动画连接成一个整体的动画,角色比较灵活,Quake2中使用这种动画;
2)骨骼动画:广泛应用的动画方式,集成了以上两个方式的优点,骨骼按角色特点组成一定的层次结构,有关节相连,可做相对运动,皮肤作为单一网格蒙在骨骼之外,决定角色的外观;
3)单一网格模型动画:由一个完整的网格模型构成,在动画序列的关键帧里记录各个顶点的原位置及其改变量,然后插值运算实现动画效果,角色动画较真实。

第一部分:掌握基础概念

  • 骨骼动画原理
骨骼动画的想法来源于人体骨骼。例如说,人的上肢所有肌肉和皮肤都受上肢骨胳的影响,而人的踝关节则分别承受小腿骨胳和脚骨的影响。根据这个我们可以将骨骼动画理解为两个概念: 骨骼:用以控制蒙皮的一种抽象的概念,如人体骨骼控制皮肤。 蒙皮:被骨骼控制、并显示在外的因素,如人体的皮肤被骨骼所影响。
  • 蒙皮
在最终的渲染结果中,蒙皮将完全显示出来,蒙皮实际上就是顶点、法线和纹理坐标等将被渲染的元素。而其中,最关键的当然是顶点,顶点将直接被骨头牵扯运动,因而使得整个模型呈现骨骼所决定的样子。
  • 骨骼
骨骼是一种抽象的概念,在最终的渲染结果中,它不可见。类如人体骨骼、骨骼是若干骨头(Bone)成树状的集合体,而每块骨头又分别与若干数量的蒙皮顶点关联。当骨头运动的时候,与之关联的所有蒙皮顶点也会受骨骼的影响而运动。 骨头与蒙皮顶点的关联需要考虑到每块骨头对蒙皮顶点的影响。 尽管大部分情况下,一个顶点将仅仅被一个骨头的影响,但是关节处的顶点往往被多根骨头影响,例如踝关节,可能会分别受小腿骨50%和脚骨50%的影响,这种影响叫作权重(Weight)。在这种情况下,我们称踝关节的这些顶点,受小腿骨影响的权重是50%,受脚骨影响的权重也是50%。
  • 核心
通过骨骼带动皮肤运动,也就是通过骨骼的移动动态计算Mesh上的点的位置。
  • 骨骼动画转换过程
1)将Mesh上的点转换为骨骼空间上的点。骨骼空间就是以关节为原点确定的空间,并不是一个实体。
2)通过缩放、旋转、平移将骨骼移动到新的位置。
3)根据骨骼的新位置计算Mesh顶点新世界坐标(骨骼移动,但Mesh顶点与骨骼的相对位置不变,所以产生了顶点随骨骼移动的感觉),若一个顶点被多个骨骼影响,则要进行顶点混合计算新世界坐标。
特别普及点:补间与帧动画
骨骼动画的本质,便是在不同的时间点为某节骨骼定义了特定的位置、缩放、旋转。动画的运作便是根据两个时间点之间的骨骼数据做数值变化,这种行为称之为补间(Tweens),同理骨骼动画也就是一种补间动画。与补间动画相对应的概念是帧动画,帧动画只会在特定的时间点发生变化,时间点之间的运动途中是不变的,在许多经典的2D游戏动画便是这种做法。

第二部分:实战应用

1、学习Unity3D人体18节点骨骼动态简单点线模型的建立,我们以火柴人模型为主,这种模型具有结构简单、直观、响应速度快等优点。我们使用LineRendderer,进行绘制,即为物体间增加线条。
  • 第一步,准备核心组件类,绘制火柴人的脚本CreateSkeletonController.cs、JsonJointSerializable.cs 辅助加载类。
JsonJointSerializable.cs核心代码如下:
    
    
using UnityEngine ; using System . IO ; using System . Text ; using System ; using System . Collections . Generic ; [ System . Serializable ] public class ModelData { public float version ; public List < People_sets > people ; } [ System . Serializable ] public class People_sets { public float [ ] pose_keypoints_2d ; // public float[] hand_left_keypoints_2d; // public float[] hand_right_keypoints_2d; } public class JsonJointSerializable : MonoBehaviour { static public float [ ] pose_joint_x = new float [ 20 ] ; static public float [ ] pose_joint_y = new float [ 20 ] ; int num = 0 ; // Use this for initialization void Start ( ) { } // Update is called once per frame void Update ( ) { try { //test:1帧数据 num = 2 ; //get the last file name string numString = Convert . ToString ( num ) ; string zero = "" ; string pathBefore = "/Resources/OpenPose/" ; for ( int j = 0 ; j < ( 12 - numString . Length ) ; j ++ ) { zero = zero + "0" ; } Debug . Log ( pathBefore + zero + numString + "_keypoints.json" ) ; //analysis data from json string jsonTest = File . ReadAllText ( Application . dataPath + pathBefore + zero + numString + "_keypoints.json" , Encoding . UTF8 ) ; Debug . Log ( Application . dataPath + pathBefore + zero + numString + "_keypoints.json" ) ; ModelData obj = JsonUtility . FromJson < ModelData > ( jsonTest ) ; Debug . Log ( obj ) ; //pervent joints return to (0,0,0) for ( int i = 0 ; i < 18 ; I ++ ) { if ( obj . people [ 0 ] . pose_keypoints_2d [ 3 * i ] == 0.0f ) { } else { pose_joint_x [ i ] = obj . people [ 0 ] . pose_keypoints_2d [ 3 * I ] ; } if ( obj . people [ 0 ] . pose_keypoints_2d [ 3 * i + 1 ] == 0.0f ) { } else { pose_joint_y [ i ] = obj . people [ 0 ] . pose_keypoints_2d [ 3 * i + 1 ] ; } } } catch ( ArgumentOutOfRangeException ) { } //stay if file doesn't reach the num catch ( FileNotFoundException ) { num = num - 1 ; } } }
CreateSkeletonController.cs核心代码如下:
    
    
using System . Collections . Generic ; using UnityEngine ; public class CreateSkeletonController : MonoBehaviour { # region definition public float speed = 5f ; /// <summary> /// line renderer*4 。表示MNose0,MMid1,LShoulder2,LElbow3 关键渲染点,对象需要挂上LineRenderer /// </summary> private List < LineRenderer > lineRendererSet = new List < LineRenderer > ( ) ; public int lineLength = 300 ; /// <summary> /// SkeletonPointType:骨骼节点的类型(18节点),GameObject:骨骼点预设对象(18节点) /// </summary> public Dictionary < SkeletonPointType , GameObject > SkeletonPointDict ; [ System . Serializable ] public enum SkeletonPointType { LEar16 , LEye14 , MNose0 , REye15 , REar17 , MMid1 , LShoulder2 , RShoulder5 , LElbow3 , RElbow6 , LWrist4 , RWrist7 , LAss8 , RAss11 , LKnee9 , RKnee12 , LFoot10 , RFoot13 , } [ System . Serializable ] public struct SkeletonPointPrefab { public SkeletonPointType type ; public GameObject prefab ; } public SkeletonPointPrefab [ ] SkeletonPointPrefabs ; # endregion //将场景的物体关联到该脚本中 void InitObject ( ) { // 字典内容 SkeletonPointDict = new Dictionary < SkeletonPointType , GameObject > ( ) ; for ( int i = 0 ; i < SkeletonPointPrefabs . Length ; I ++ ) { if ( ! SkeletonPointDict . ContainsKey ( SkeletonPointPrefabs [ i ] . type ) ) { SkeletonPointDict . Add ( SkeletonPointPrefabs [ i ] . type , SkeletonPointPrefabs [ i ] . prefab ) ; } } lineRendererSet . Add ( ( LineRenderer ) SkeletonPointDict [ SkeletonPointType . MNose0 ] . GetComponent ( "LineRenderer" ) ) ; lineRendererSet . Add ( ( LineRenderer ) SkeletonPointDict [ SkeletonPointType . MMid1 ] . GetComponent ( "LineRenderer" ) ) ; lineRendererSet . Add ( ( LineRenderer ) SkeletonPointDict [ SkeletonPointType . LShoulder2 ] . GetComponent ( "LineRenderer" ) ) ; lineRendererSet . Add ( ( LineRenderer ) SkeletonPointDict [ SkeletonPointType . LElbow3 ] . GetComponent ( "LineRenderer" ) ) ; } // Use this for initialization void Start ( ) { InitObject ( ) ; lineRendererSet [ 0 ] . positionCount = lineLength ; lineRendererSet [ 1 ] . positionCount = lineLength ; lineRendererSet [ 2 ] . positionCount = lineLength ; lineRendererSet [ 3 ] . positionCount = lineLength ; lineRendererSet [ 0 ] . positionCount = 7 ; lineRendererSet [ 1 ] . positionCount = 7 ; lineRendererSet [ 2 ] . positionCount = 4 ; lineRendererSet [ 3 ] . positionCount = 4 ; } // Update is called once per frame void Update ( ) { float step = speed * Time . deltaTime ; //move joints using interpolation method SkeletonPointDict [ SkeletonPointType . LEar16 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LEar16 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 16 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LEar16 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 16 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . MNose0 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . MNose0 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 0 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . MNose0 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 0 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . LEye14 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LEye14 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 14 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LEye14 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 14 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . REye15 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . REye15 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 15 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . REye15 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 15 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . MMid1 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . MMid1 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 1 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . MMid1 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 1 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . LShoulder2 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LShoulder2 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 2 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LShoulder2 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 2 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . RShoulder5 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . RShoulder5 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 5 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . RShoulder5 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 5 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . LElbow3 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LElbow3 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 3 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LElbow3 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 3 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . RElbow6 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . RElbow6 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 6 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . RElbow6 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 6 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . LWrist4 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LWrist4 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 4 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LWrist4 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 4 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . RWrist7 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . RWrist7 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 7 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . RWrist7 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 7 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . LAss8 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LAss8 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 8 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LAss8 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 8 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . RAss11 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . RAss11 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 11 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . RAss11 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 11 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . LKnee9 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LKnee9 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 9 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LKnee9 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 9 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . RKnee12 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . RKnee12 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 12 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . RKnee12 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 12 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . LFoot10 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LFoot10 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 10 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . LFoot10 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 10 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . RFoot13 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . RFoot13 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 13 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . RFoot13 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 13 ] , step ) , 0 ) ; SkeletonPointDict [ SkeletonPointType . REar17 ] . transform . localPosition = new Vector3 ( Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . REar17 ] . transform . localPosition . x , 0.1f * JsonJointSerializable . pose_joint_x [ 17 ] , step ) , Mathf . Lerp ( SkeletonPointDict [ SkeletonPointType . REar17 ] . transform . localPosition . y , - 0.1f * JsonJointSerializable . pose_joint_y [ 17 ] , step ) , 0 ) ; //it requires 4 lines to connect all the joints lineRendererSet [ 0 ] . SetPosition ( 0 , SkeletonPointDict [ SkeletonPointType . LEar16 ] . transform . localPosition ) ; lineRendererSet [ 0 ] . SetPosition ( 1 , SkeletonPointDict [ SkeletonPointType . LEye14 ] . transform . localPosition ) ; lineRendererSet [ 0 ] . SetPosition ( 2 , SkeletonPointDict [ SkeletonPointType . MNose0 ] . transform . localPosition ) ; lineRendererSet [ 0 ] . SetPosition ( 3 , SkeletonPointDict [ SkeletonPointType . MMid1 ] . transform . localPosition ) ; lineRendererSet [ 0 ] . SetPosition ( 4 , SkeletonPointDict [ SkeletonPointType . LShoulder2 ] . transform . localPosition ) ; lineRendererSet [ 0 ] . SetPosition ( 5 , SkeletonPointDict [ SkeletonPointType . LElbow3 ] . transform . localPosition ) ; lineRendererSet [ 0 ] . SetPosition ( 6 , SkeletonPointDict [ SkeletonPointType . LWrist4 ] . transform . localPosition ) ; lineRendererSet [ 1 ] . SetPosition ( 0 , SkeletonPointDict [ SkeletonPointType . REar17 ] . transform . localPosition ) ; lineRendererSet [ 1 ] . SetPosition ( 1 , SkeletonPointDict [ SkeletonPointType . REye15 ] . transform . localPosition ) ; lineRendererSet [ 1 ] . SetPosition ( 2 , SkeletonPointDict [ SkeletonPointType . MNose0 ] . transform . localPosition ) ; lineRendererSet [ 1 ] . SetPosition ( 3 , SkeletonPointDict [ SkeletonPointType . MMid1 ] . transform . localPosition ) ; lineRendererSet [ 1 ] . SetPosition ( 4 , SkeletonPointDict [ SkeletonPointType . RShoulder5 ] . transform . localPosition ) ; lineRendererSet [ 1 ] . SetPosition ( 5 , SkeletonPointDict [ SkeletonPointType . RElbow6 ] . transform . localPosition ) ; lineRendererSet [ 1 ] . SetPosition ( 6 , SkeletonPointDict [ SkeletonPointType . RWrist7 ] . transform . localPosition ) ; lineRendererSet [ 2 ] . SetPosition ( 0 , SkeletonPointDict [ SkeletonPointType . LFoot10 ] . transform . localPosition ) ; lineRendererSet [ 2 ] . SetPosition ( 1 , SkeletonPointDict [ SkeletonPointType . LKnee9 ] . transform . localPosition ) ; lineRendererSet [ 2 ] . SetPosition ( 2 , SkeletonPointDict [ SkeletonPointType . LAss8 ] . transform . localPosition ) ; lineRendererSet [ 2 ] . SetPosition ( 3 , SkeletonPointDict [ SkeletonPointType . MMid1 ] . transform . localPosition ) ; lineRendererSet [ 3 ] . SetPosition ( 0 , SkeletonPointDict [ SkeletonPointType . RFoot13 ] . transform . localPosition ) ; lineRendererSet [ 3 ] . SetPosition ( 1 , SkeletonPointDict [ SkeletonPointType . RKnee12 ] . transform . localPosition ) ; lineRendererSet [ 3 ] . SetPosition ( 2 , SkeletonPointDict [ SkeletonPointType . RAss11 ] . transform . localPosition ) ; lineRendererSet [ 3 ] . SetPosition ( 3 , SkeletonPointDict [ SkeletonPointType . MMid1 ] . transform . localPosition ) ; } }
骨骼数据文件(Json格式),测试使用。文件放置Resources/OpenPose/000000000002_keypoints.json 文件夹下。
    
    
{ "version" : 1.2 , "people" : [ { "pose_keypoints_2d" : [ 273.264 , 38.5963 , 0.869616 , 301.865 , 147.37 , 0.80189 , 219.778 , 147.363 , 0.74485 , 177.866 , 278.962 , 0.660513 , 149.317 , 387.645 , 0.783981 , 389.568 , 145.525 , 0.69237 , 418.295 , 294.246 , 0.581674 , 429.69 , 420.184 , 0.744175 , 225.593 , 439.214 , 0.393213 , 364.144 , 650.645 , 0.848758 , 364.144 , 650.645 , 0.848758 , 357.144 , 450.645 , 0.348758 , 364.144 , 650.645 , 0.848758 , 364.144 , 650.645 , 0.848758 , 252.327 , 21.455 , 0.845018 , 296.116 , 17.6204 , 0.78486 , 236.984 , 38.5901 , 0.239763 , 330.499 , 36.6363 , 0.860353 ] , "face_keypoints_2d" : [ ] , "hand_left_keypoints_2d" : [ 430.255 , 424.202 , 0.255266 , 416.676 , 452.158 , 0.343294 , 421.469 , 486.505 , 0.0764938 , 419.073 , 497.688 , 0.0160631 , 424.664 , 501.682 , 0.00270473 , 414.28 , 496.091 , 0.0290727 , 396.707 , 488.902 , 0.00831178 , 395.11 , 489.7 , 0.00435322 , 413.481 , 540.822 , 0.00356947 , 423.066 , 497.688 , 0.0233392 , 411.884 , 504.078 , 0.00861702 , 422.268 , 503.28 , 0.00597289 , 415.878 , 540.822 , 0.00381597 , 423.865 , 496.091 , 0.0400665 , 412.682 , 504.078 , 0.0124277 , 423.865 , 503.28 , 0.00940899 , 412.682 , 540.023 , 0.00571543 , 424.664 , 486.505 , 0.0412582 , 395.11 , 488.103 , 0.0168368 , 423.865 , 501.682 , 0.00908826 , 424.664 , 505.676 , 0.00689844 ] , "hand_right_keypoints_2d" : [ 159.561 , 374.712 , 0.0309012 , 142.809 , 387.822 , 0.0350077 , 142.809 , 419.14 , 0.0447348 , 163.202 , 436.62 , 0.0462346 , 149.364 , 443.174 , 0.0316575 , 160.289 , 403.845 , 0.064782 , 142.809 , 430.065 , 0.0809698 , 153.734 , 449.001 , 0.128932 , 164.659 , 466.481 , 0.114184 , 160.289 , 406.03 , 0.0501139 , 155.919 , 427.88 , 0.0803895 , 163.202 , 454.828 , 0.162599 , 169.757 , 470.851 , 0.186943 , 161.746 , 405.301 , 0.0399239 , 160.289 , 424.966 , 0.0734568 , 165.387 , 444.631 , 0.164918 , 170.486 , 470.851 , 0.246341 , 166.116 , 404.573 , 0.0298664 , 166.116 , 423.51 , 0.0586659 , 169.757 , 441.718 , 0.0851868 , 174.856 , 465.753 , 0.0832467 ] , "pose_keypoints_3d" : [ ] , "face_keypoints_3d" : [ ] , "hand_left_keypoints_3d" : [ ] , "hand_right_keypoints_3d" : [ ] } ] }
附加说明:然后之前有一个插件专门研究解决多人骨骼和手势、面部识别的问题。上面测试数据也来源于OpenPose。
  • 第二步,在项目中设置预设对象,可以选择Sphere或者Cube对象。并且附加CreateSkeletonController.cs、JsonJointSerializable.cs组件。
  • 第三步,直接运行项目可以看到绘制的火柴人。
后续小编这边会继续分享骨骼动画在Unity3D中的应用。期待关注哈!
Mixamo 动画资源的网站(免费): http://www.360doc.com/content/20/0117/17/21412_886713704.shtml
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值