第三人称射击游戏人物瞄准仰角的控制方案

概述

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

1.改变腰的旋转;

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

其中一类方案:

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

腰以上的部分保持稳定,所以适合在第一人称使用。

使用这种方案的游戏:

尘白禁区

7f96506f922a4ae5bea9fcae93a43ee7.png33e6327473504108a39385a4bd22109b.png

二类方案:

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

使用这种方案的游戏:

原神

81645458793148ef970e71c2f33c22a6.gif

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

其实第一人称射击也存在这两种方案,如果手臂和相机存在父子关系,则相当于一类方案,表现为枪的远近不随仰角变化;如果手臂和相机是平级关系,相当于二类方案,表现为枪的远近随仰角变化。

animator.SetBoneLocalRotation()转动腰(最简单的方案)

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

b3f7156805484dcda305b6d50d197669.png

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,结果是:

3ba60c0f64d3477485b12b2f02641bea.png

animator.SetBoneLocalRotation()之前spine的旋转一直不变,会被动画系统掰回原来的旋转,所以animator.SetBoneLocalRotation(xxx,spine.localRotation*deltaRot);里面虽然有spine的当前旋转,但这个旋转一直是人物姿势被改变前的旋转,这句其实是设置spine的局部绝对旋转。

如果不运行,只在编辑模式看一下效果,可以把人物的旋转归零,选Global,Rotate Tool,直接旋转Spine骨骼。

6faf79048cce49b39d957eeaf2be8072.png

效果

894c7dbef3f34c30b50679e59dfcd530.png766678e95ca049b6a847a55a684d2f57.png

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

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

18e47513cc684a66b5fbb3d30cebcdd3.png01f3a057b87a4878816730a727faa35e.png

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

9c08b6407bc64ee283f519bf766878df.png

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

f94fd8586dc64abf86a5b4e403ed301f.png

Unity使用一维混合树改变人物仰角_单机游戏热门视频 (bilibili.com)

使用IK(转动双臂和头。调整很繁琐)

轴-枪-IK-双手

节点的决定关系是:

0319186fd02e4ea5853fafd2230ec5df.jpeg

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

56e8539377674b62aa8ae732cb79c231.png

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

13fc04ec349745a4abe9a3e3654b9abe.png

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

cbd795a13b2c4398ad780fce34905967.png

配置双手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的位置和旋转;

效果

0c0f18032c83431c91848af5c55cc103.jpeg85ef4cd4dd0743bbb6840b4c36f79361.jpeg

72a99e15ce6d48b8ae7f041f0d022968.gif63eee9aaa626442fbb2632fa4bed2ffb.gif

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

94cccebea05b4776ad773074e60d1974.gif

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

1.仰视的时候枪和头、第一人称相机穿模了。所以这个适用于第三人称,第一人称适合方案1.

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

轴-IK-双手-枪

42f822551d054314a31180de312466c1.jpeg

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

使用IK方案的问题:

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

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值