第三人称射击游戏人物动作系统笔记

功能需求

  1. 根据瞄准仰角改变人物上半身姿势;
  2. 给枪或者右手添加约束,使枪朝向瞄准的方向;
  3. 上半身在各方向移动中保持稳定,同时有轻微晃动;
  4. 持枪时左手跟随枪,且左手位置根据不同枪变化;
  5. 枪绑定的物体在双手、背之间的切换;
  6. 约束开启和关闭(如跑步)状态平滑过渡;

1.改变瞄准仰角

这个功能有多种方案实现,总体可以分为几类:

1.改变腰的旋转;

2.改变手臂和头的旋转;

3.腰、双臂、头的旋转都改变;

4.只旋转右手腕;

一类方案:

只要转动腰一个骨骼,比较简单;

使用这种方案的游戏:

尘白禁区

二类方案:

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

使用这种方案的游戏:

原神

武装突袭1

因为枪相对头和第一人称相机的位置不固定,第一人称看到的枪的位置和远近也不固定,仰视时枪可能和头、第一人称相机穿模。

三类方案:

基本上只能用动画混合树。

例子:绝地求生、和平精英。仰角比较小时转动双臂,达到一个仰角后转动腰。

吃鸡里俯视是转动手腕,造成枪托不抵肩。

方案4

荒野行动

 

代码转动Spine(简单但是僵硬)

animator.SetBoneLocalRotation()

需要把相应层打开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的旋转

 

AvatarMask+一维混合树实现(双臂和腰都可以转动)

在3d动画软件里做出人物仰视俯视的动画,然后用一维混合树。

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

第一人称效果(枪相对头的位置变化了,所以看到枪的位置不一样):

问题:这个方案必须用AvatarMask覆盖上半身,如果走路动画的Hips的旋转在晃动,那么上半身也会跟着晃动。可以把走路动画改成Hips旋转不晃动的,然后走路时上半身和双臂都一动不动,动作更僵硬。

使用IK(转动双臂和头)

使用IK需要面对的问题是IKGoal的父级Axis绑定在哪里。绑定在根节点,双手就没有走路时的晃动效果;绑定在Chest,位置和旋转都晃动;可以使用位置约束只让Axis的位置跟随Chest。

轴-枪-IK-双手

节点的决定关系是:

人物改变仰角的时候枪是绕右肩旋转的,所以在瞄准姿势在人物根节点下右肩的位置放一个节点作为转轴Axis。

把枪挂载到Axis下,在枪下面建左手右手的IKGoal节点。枪应该使Axis在枪托尾部的位置。IKGoal的位置和旋转需要运行后手调。

Axis前方很远的地方建一个target,作为头看向的目标。

配置双手IK:

public Transform rightHandIK,leftHandIK;
    void HandsIK(){
        animator.SetIKPosition(AvatarIKGoal.RightHand,rightHandIK.position);
        animator.SetIKPositionWeight(AvatarIKGoal.RightHand,1);

        animator.SetIKRotation(AvatarIKGoal.RightHand,rightHandIK.rotation);
        animator.SetIKRotationWeight(AvatarIKGoal.RightHand,1);

        animator.SetIKPosition(AvatarIKGoal.LeftHand,leftHandIK.position);
        animator.SetIKPositionWeight(AvatarIKGoal.LeftHand,1);

        animator.SetIKRotation(AvatarIKGoal.LeftHand,leftHandIK.rotation);
        animator.SetIKRotationWeight(AvatarIKGoal.LeftHand,1);
    }

配置头看向:

public Transform target;
    void HeadLookIK(){
        animator.SetLookAtPosition(target.position);
        animator.SetLookAtWeight(1);
    }

需要手调的变量有:

1.Axis的位置;

2.枪的位置;

3.双手IK的位置和旋转;

效果

第一人称效果:仰视的时候枪穿到了相机的Near clip plane后面,没有显示全。

看上去好像不错。这个方案的问题:

1.仰视的时候枪和头、第一人称相机穿模了。

2.持枪跑步、换弹、收枪、取枪的动画需要给枪的节点K帧;

3.Axis是绑定在根节点的,走路身体晃动的时候枪不会晃动,被枪约束的双手也不会晃动。

轴-IK-双手-枪

这种架构左手和枪没有约束关系,可能出现左手脱离护木的问题。

使用IK方案的问题:

1.换弹动画需要关闭IK,然后无法改变仰角,如果做第一人称,换弹时可能看不到双手的动画

2.保持枪指向瞄准方向

如果把枪绑定在右手,枪的局部旋转极有可能是个不规则的值,且在移动中手部的旋转可能变化。不适合直接由右手控制枪的旋转。可以给枪的容器节点加旋转约束,由指向瞄准方向的物体控制它的旋转。

3.上半身在移动中保持稳定

方法就是给spine或chest加旋转约束。在1.里已经讨论过。

4.左手跟随枪

如果枪绑定在右手上,那么左手就要使用IK跟随枪。否则就要用双手跟随枪的架构。

5.枪跟随的物体在右手、左手、背之间转换

要么使用动画事件,要么给枪的容器节点加Parent Constraint,把上述物体加入Source,由动画剪辑的关键帧控制各Source的权重。这个方法的好处是:

1.代码量减少;

2.预览动画就能看到效果,动画事件则必须运行才能看到。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值