功能需求
- 根据瞄准仰角改变人物上半身姿势;
- 可以在走路中换弹;
- 枪朝向瞄准的方向;
- 上半身在各方向移动中保持稳定,同时有轻微晃动;
- 据枪时左手跟随枪,且左手位置根据不同枪变化;
- 枪绑定的物体在双手、背之间的切换;
- 约束开启和关闭(如跑步)状态平滑过渡;
1.改变瞄准仰角
这个功能有多种方案实现,总体可以分为几类:
1.改变腰的旋转;
2.改变手臂和头的旋转;
3.腰、双臂、头的旋转都改变;
一类方案:
只要转动腰一个骨骼,比较简单;
使用这种方案的游戏:
尘白禁区


二类方案:
转动3个骨骼,比较复杂(因为改变仰角时双臂的旋转是一个极不规则的旋转,写代码使用正向动力学控制基本不可能,要么用IK,要么动画混合);
使用这种方案的游戏:
原神

武装突袭1


因为枪相对头和第一人称相机的位置不固定,第一人称看到的枪的位置和远近也不固定,仰视时枪可能和头、第一人称相机穿模。
三类方案:
基本上只能用动画混合树。
例子:绝地求生、和平精英、荒野行动。仰角比较小时转动手腕,达到一个仰角后转动胳膊和腰。




animator.SetBoneLocalRotation()转动Spine(简单但是僵硬)
需要把相应层打开IK Pass,在OnAnimatorIK()里执行animator.SetBoneLocalRotation(),可以直接改变某个骨骼的旋转。这似乎是官方推荐的方法:

Quaternion.AngleAxis()输入的轴是物体的局部坐标系的,所以要获得Spine坐标系下人物x轴的向量。Quaternion.AngleAxis()返回一个旋转变化,它乘给spine.localRotation。这里angleX是仰角,是个会变大变小的值,怎么能做变化量?
public Animator animator;
HumanBodyBones boneToLookUpDown=HumanBodyBones.Spine;
Transform spine;
[Range(-90,90)]
public float angleX=0;
void Start(){
animator = GetComponent<Animator>();
spine=animator.GetBoneTransform(boneToLookUpDown);
}
void OnAnimatorIK(){
Quaternion spineRot=Quaternion.AngleAxis(angleX,spine.InverseTransformDirection(transform.right));
animator.SetBoneLocalRotation(boneToLookUpDown,spine.localRotation*spineRot);
}
这里animator.SetBoneLocalRotation()之前我打印了一下spine.localEulerAngles,结果是:

animator.SetBoneLocalRotation()之前spine的旋转一直不变,会被动画系统掰回原来的旋转,所以animator.SetBoneLocalRotation(xxx,spine.localRotation*deltaRot);里面虽然有spine的当前旋转,但这个旋转一直是人物姿势被改变前的旋转,这句其实是设置spine的局部绝对旋转。
如果不运行,只在编辑模式看一下效果,可以把人物的旋转归零,选Global,Rotate Tool,直接旋转Spine骨骼。

效果


约束:RotationConstraint(或AimConstraint)
在Spine添加旋转约束,Source是控制仰角的物体。

预览人物端枪的动画。

在旋转约束点Is Activate,组件会计算出Spine当前的旋转偏移。点Lock。

在端枪状态的动画里加上开启旋转约束的关键帧,其他状态不开启。
这个方案也满足了需求3。
在LateUpdate()里修改Spine的旋转
动画系统是在Update()和LateUpdate()之间生效的,在LateUpdate()里直接用transform的API也可以修改骨骼的变换。
AvatarMask+一维混合树(双臂和腰都可以转动)
在3d动画软件里做出人物仰视俯视的动画,然后用一维混合树。


如果不会自己做,Mixamo有一个叫Rifle Aiming Idle的动画,里面有Aim Height参数,可以调出仰视俯视瞄准的动画。

持枪状态在body层是一个移动的二维混合树,arm层是控制仰角的一维混合树。

注意:如果不同方向移动的动画Hips的旋转不一样,此时只用AvatarMask会让不同方向移动

最低0.47元/天 解锁文章
1551






