今日達成したこと:
シールドハンドル
図に示すように、シールドの位置としてキャラクターモデルの適切な位置にshieldHandleを追加します。
防御的なIKスキーム
元のアイドルアニメーションは、シールドを取り付けた後にシールドを保持しているように見えるため、ここでは、OnAnimatorIKメソッドを使用して腕の位置(回転)を調整し、シールドを下げることができます。
OnAnimatorIKを使用する前に、アニメーションレイヤー設定でIKパスを開く必要があります。IKパスが開いている場合にのみ、システムによってOnAnimatorIKが呼び出されます。IKパス(IKチャネル?)はアニメーションの機会として使用でき、実際にはIKスイッチを計算しません。ボーンの位置を変更するには、IKパスを通過する必要があります。
次に、モデルゲームオブジェクトにスクリプトをマウントします。コードは次のとおりです。
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調整値をゼロにクリアし、シールドを実現することもできます。これも解決策です。もちろん、私たちは今でもAvatorMaskと既製のアニメーションを使用して達成しています。
防衛アニメーション状態スキーム
上記のIKスキームを使用せずに、新しいアニメーションを追加するとします。新しいアニメーションレイヤーDefenseを追加し、WeighとAvatar Maskを設定し、idleとdefense_oneHandアニメーションノードを追加します。idleはシールドを下ろすアニメーションで、defense_oneHandはシールドを上げるアニメーションで、新しいBoolパラメーター防御を次のように追加します。遷移条件。
Avator Maskは図のように設定されているため、防御レイヤーは左手にのみ影響します。このプロジェクトでは、左手と右手を区別しません。
防衛ステータスコード
これは非常に簡単です。入力されているかどうかに応じて防御信号を設定する必要があります。防御信号はプレス信号です。次に、防御信号を介してアニメーションマシンのパラメータ防御をさらに設定できます。アニメーションの状態スキームは、直接SetBoolにすることができます。
// 触发defense
anim.SetBool("defense", current_pi.defense);
使用するスキームに関係なく、アニメーションマシンのパラメータ防御を設定すると便利です。以下は私のIKスキームのコードです。アニメーションマシンのパラメータ防御が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));
}
バグと欠陥:
武器や盾が床や壁に衝突する問題については、後の段階で衝突型加速器が必要になるため、予防策を講じる場合は、衝突型加速器を直接削除せず、システムが床との衝突を計算しないようにします。レイヤー。盾と剣のコライダーを行い、ゲームオブジェクトのレイヤーを武器に設定します。次に、[編集]-[プロジェクト設定]-[物理]に移動して、レイヤー衝突マトリックスを設定します。図に示す設定により、Weaponは現在他のレイヤーとの衝突を計算しないようにすることができます。
優れたアニメーションは非常に重要です。mixamoにダウンロードされた無料のアニメーションは非常に醜く、シールドを追加した後は型を着用し、IKを追加した後はさらに剛性が高くなります。
注意する価値がある:
IKに関しては、逆ダイナミクス。簡単に説明すると、最初に骨の末端ノードの位置を決定し、次に、生物学的骨構造のエンジンの理解に従って、それを接続する親の骨ノードの位置を逆に計算します。反対のプロセスはFK、フォワードキネティクスと呼ばれます。
Unityでは、OnAnimatorIKメソッドを使用して、モデルのボーンをリアルタイムで調整できます。アニメーションマシンは、アニメーションノードが満たすボーン位置を計算した後、必要な特定のエンドボーン位置を計算し、IKを介して計算します。の親ボーンは(エンジンが考える)正しい位置に到達します。
私たちのIKスキームでは、IKパスはベースレイヤーでのみ有効になっていますが、他のレイヤーにも影響を与えるようです。