前言

之前我做过一个TPS第三人称射击游戏项目,但是人物瞄准非常生硬:
在这里插入图片描述

我们可以使用Animation Rigging让它更加灵活。Animation Rigging的基础使用参考:【unity组件介绍】创建程序化动画,灵活地调整角色动作——Animation Rigging的使用

显示骨骼

在这里插入图片描述
在这里插入图片描述

实现角色的头部始终注视某个目标

创建一个rig

选中角色,点击菜单的Rig Setup按钮
在这里插入图片描述
这会在角色下新增一个RigBuilder组件,它会和animator组件一起来管理这个角色上的所有Rig,并在角色层下创建一个新子对象,挂载了Rig组件。

添加约束

在Rig下方创建一个新的空对象,并把此对象重命名为HeadAim。我将继续在这里添加一个Multi-Aim Constraint多目标约束组件。

受约束的对象配置为头部,Aim Axis、Up Axis是头部局部位置的前面和上面轴。配置配置Source Objects为我们要瞄准的目标对象
在这里插入图片描述
效果,头就跟着看向目标
在这里插入图片描述

限制头部偏转角度

目前人物头部可以偏转很大的角度
在这里插入图片描述

我们需要限制头部偏转角度,这里我配置为-60~60度
在这里插入图片描述
效果
在这里插入图片描述

右手瞄准目标

添加新的Multi-Aim Constraint多目标约束组件子物体。受约束的对象配置为右手手腕骨骼,其他配置和前面一样。
在这里插入图片描述

效果,右手跟着瞄准目标了
在这里插入图片描述

身体跟随旋转

添加新的Multi-Aim Constraint多目标约束组件子物体,受约束的对象配置为脊椎骨骼,其他配置和前面一样。
在这里插入图片描述

效果
在这里插入图片描述
但是可以发现,这样旋转导致右手的瞄准出现了问题。我们应该先旋转身体,再旋转手,修改排序,身体在前面就可以了。
在这里插入图片描述

效果,现在正常了
在这里插入图片描述
目前我觉得身体旋转过多,我们限制一下,身体权重限制在0.7左右
在这里插入图片描述
现在身体基本上仍然在旋转,但旋转的幅度没有那么大,这让它看起来更自然一些。
在这里插入图片描述

左手握枪

左手应该握住枪,添加一个TwoBoneIKConstraint双骨骼IK约束,这是用于放置手臂或腿部的东西,因此他需要两个骨骼,例如上臂和下臂,然后为尖端选择一个目标,也就是手掌。它可以用于放置手并将上臂的手臂旋转到合理的位置
在这里插入图片描述
我们先放入左手顶点骨骼
在这里插入图片描述

右键,点击Auto Setup from Tip Transform按钮
在这里插入图片描述
unity会自动帮我们自动选择肩膀中的肘部,并会自动创建两个对象
在这里插入图片描述
将这两个对象移动到右手手掌骨骼下,作为他的子物体
在这里插入图片描述
这里分享一个简单的快捷的方式

我们先关闭所有的骨骼IK重定向效果
在这里插入图片描述
运行游戏状态下,播放瞄准动画,先选中LeftHandAim_target,再选中左手手掌节点(注意选择顺序不要错),点击Align Transform按钮,同步位置
在这里插入图片描述
然后复制组件值,结束运行再粘贴回组件值
在这里插入图片描述
然后和前面一样,再运行游戏状态下,播放瞄准动画,选中LeftHandAim_hint和左手肘部节点,点击Align Transform按钮,同步位置,然后复制粘贴组件值
在这里插入图片描述
最后再打开Rig
在这里插入图片描述
效果,如果不满意效果可以在运行状态下手动微调,在复制粘贴值
在这里插入图片描述

更精细的限制角度

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
如果发现角度偏移没有达到自己设定的角度怎么办?可以配置Avatar骨骼角度限制,具体可以参考:【零基础入门unity游戏开发——unity3D篇】3D模型 —— Rig操纵页签和Avatar化身系统
在这里插入图片描述

代码控制

瞄准和非瞄准状态切换,默认状态不启动瞄准骨骼

[SerializeField] private Rig aimRig;//瞄准骨骼
private float aimRigWeight;//瞄准骨骼权重

//瞄准
if (inputController.isAim && isWeapon)
{
    animator.SetBool(IsAiming, true);
    aimRigWeight = 1f;
}
else
{
    animator.SetBool(IsAiming, false);
    aimRigWeight = 0f;
}

进行鼠标检测,将目标对象投射到碰撞的点上

//剔除层级
public LayerMask cullLayerMask;

//射线检测
void SetAimTarget()
{
    TryGetMouseHitInfo(out var hitInfo, ~cullLayerMask);
    aimTarget.position = hitInfo.point;
}

/// <summary>
/// 获取鼠标在3D世界中的命中信息
/// </summary>
/// <param name="hitInfo">射线命中信息</param>
/// <param name="layerMask">层级掩码(默认为所有层)</param>
/// <param name="maxDistance">最大检测距离</param>
/// <returns>是否命中物体</returns>
bool TryGetMouseHitInfo(out RaycastHit hitInfo, LayerMask? layerMask = null, float maxDistance = Mathf.Infinity)
{
    hitInfo = default;
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    return Physics.Raycast(ray, out hitInfo, maxDistance, layerMask ?? ~0);
}

效果
在这里插入图片描述
最后隐藏目标球体的渲染即可
在这里插入图片描述


专栏推荐

地址
【unity游戏开发入门到精通——C#篇】
【unity游戏开发入门到精通——unity通用篇】
【unity游戏开发入门到精通——unity3D篇】
【unity游戏开发入门到精通——unity2D篇】
【unity实战】
【制作100个Unity游戏】
【推荐100个unity插件】
【实现100个unity特效】
【unity框架/工具集开发】
【unity游戏开发——模型篇】
【unity游戏开发——InputSystem】
【unity游戏开发——Animator动画】
【unity游戏开发——UGUI】
【unity游戏开发——联网篇】
【unity游戏开发——优化篇】
【unity游戏开发——shader篇】
【unity游戏开发——编辑器扩展】
【unity游戏开发——热更新】
【unity游戏开发——网络】

完结

好了,我是向宇,博客地址:https://xiangyu.blog.csdn.net,如果学习过程中遇到任何问题,也欢迎你评论私信找我。

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!
在这里插入图片描述

Logo

分享最新的 NVIDIA AI Software 资源以及活动/会议信息,精选收录AI相关技术内容,欢迎大家加入社区并参与讨论。

更多推荐