关于unity:黑魂复刻游戏的控制器盾牌防御的IK方案以及动画状态方案Unity随手记

43次阅读

共计 1945 个字符,预计需要花费 5 分钟才能阅读完成。

明天实现的内容:
增加 shieldHandle
在人物模型适合的地位增加 shieldHandle 作为盾牌的地位,如图所示。


进攻的 IK 计划
因为本来的 Idle 动画在装上盾牌当前看上去就像举着盾牌,这里咱们能够通过 OnAnimatorIK 办法调整手臂地位(旋转)将盾牌放下来。

在应用 OnAnimatorIK 之前,咱们须要在动画层设置中关上 IK Pass,只有关上 IK Pass,OnAnimatorIK 才会被零碎调用。IK Pass(IK 通道?)能够当成动画机会不会真的去计算 IK 的开关,咱们对骨骼地位的批改也要通过 IK Pass 才行。

接下来,在模型游戏对象上挂载脚本,代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 用于调整模型骨骼左手臂的地位
public class LeftArmIK : MonoBehaviour
{
    // 存储要调整的量
    public Vector3 a;

    private Animator m_anim;

    private void Awake()
    {m_anim = GetComponent<Animator>();
    }

    private void OnAnimatorIK(int layerIndex)
    {
        // 获取要操作的具体骨骼的 Transform 在这里是左手小臂
        Transform leftLowerArm = m_anim.GetBoneTransform(HumanBodyBones.LeftLowerArm);
        // 将要调整的量加上去 加到 local 坐标
        leftLowerArm.localEulerAngles += a;
        // 通过 IK Pass 设置骨骼旋转
        m_anim.SetBoneLocalRotation(HumanBodyBones.LeftLowerArm, Quaternion.Euler(leftLowerArm.localEulerAngles));

    }
}

咱们将 a 调整到适合值,就能实现将手臂骨骼放下来。


站着不动时看着还不错,游戏角色跑起来看着就很生硬了。然而这样做当前,咱们甚至能够利用代码将手臂 IK 调整值清零来实现举盾,这也算是一种计划了。当然咱们还是要用 Avator Mask 和现成的动画来实现。

进攻的动画状态计划
假如咱们没有应用下面的 IK 计划,而是增加新的动画进去。咱们将退出新的动画层 Defense,设置 Weigh 和 Avatar Mask,增加 idle 和 defense_oneHand 动画节点,其中 idle 是放下盾的动画而 defense_oneHand 是举起盾的动画,增加新的 Bool 参数 defense 作为转换条件。

Avator Mask 设置如图,让 Defense 层只影响左手,咱们的我的项目目前还没有辨别配备左右手。

进攻状态代码
这个就很简略了,仍旧是依据是否输出来设置一个 defense 信号,defense 信号是按压信号。而后咱们能够通过 defense 信号进一步设置动画机参数 defense。动画状态计划间接 SetBool 就行了。

        // 触发 defense
        anim.SetBool("defense", current_pi.defense);

不论应用何种计划,设置动画机参数 defense 都很有用,上面是我的 IK 计划的代码。当动画机参数 defense 为 true 时将手臂旋转调整量设置为举盾时的量(在这里 Vector3.zero 刚刚好),为 false 设置为放下时的量。采纳 Lerp 做个突变也行。

    private void OnAnimatorIK(int layerIndex)
    {
        // 设置手臂的旋转最终目标
        tmp_target = m_anim.GetBool("defense") ? Vector3.zero : a;
        // 突变 tmp_currentEulerAngle
        tmp_currentEulerAngle = Vector3.Lerp(tmp_currentEulerAngle, tmp_target, 0.3f);
        // 获取要操作的具体骨骼的 Transform 在这里是左手小臂
        Transform leftLowerArm = m_anim.GetBoneTransform(HumanBodyBones.LeftLowerArm);
        // 将要调整的量加上去 加到 local 坐标
        leftLowerArm.localEulerAngles += tmp_currentEulerAngle;
        // 通过 IK Pass 设置骨骼旋转
        m_anim.SetBoneLocalRotation(HumanBodyBones.LeftLowerArm, Quaternion.Euler(leftLowerArm.localEulerAngles));
    }

正文完
 0