攻撃して敵が倒れた時に、その攻撃の力でラグドールが吹き飛ぶようにします。
敵を複製してラグドールを作ったので、敵とラグドールは全く同じボーンを持っています。敵の攻撃を受けたボーンの名前はわかるので、敵とラグドールの各ボーンの位置を揃えるときにその名前と同じ名前のラグドールのボーンを探します。
// 敵のボーンのスクリプト
// 遠隔攻撃を受けたとき
sc_agent.SetHP(-d, gameObject.name, collision.relativeVelocity);
// 近接攻撃を受けたとき
sc_agent.SetHP(-damage, gameObject.name);
// 敵のルートのスクリプト
public bool SetHP(float f,string name,Vector3 v = default)
{
// 怯んでいるときは攻撃を受けないようにする
if (animator.GetCurrentAnimatorStateInfo(0).IsName("Flinch")) return false;
// 体力を増減してゲージに反映
HP += f;
HP = Mathf.Clamp(HP,0f,1f);
HpImage.fillAmount = HP;
// 体力が残っているとき
if (HP > 0f)
{
Flinch(); // 怯む
return false;
}
// 体力が0になったとき
else
{
// 衝突の速度
if (v == default)
{
attackVelocity = (transform.position - player.transform.position) * 50f;
}
else
{
attackVelocity = v;
}
attackedBoneName = name; // 攻撃を受けたボーンの名前
Destroy(gameObject); // 敵を破壊
var r = Instantiate(ragdoll, transform.position, transform.rotation); // ラグドールを生成
attackedBoneRigidbody = null;
Overlap(ref r); // 敵とラグドールを重ねる
Debug.Log("attackedBoneRigidbody = " + attackedBoneRigidbody);
// 攻撃を受けたボーンと同じ名前のラグドールのボーンに力を加える
if (attackedBoneRigidbody)
{
attackedBoneRigidbody.AddForce(attackVelocity, ForceMode.Impulse);
}
else {
Debug.Log("attacked bone is not found");
}
AudioSource a = ragdoll.GetComponent<AudioSource>();
a.pitch = picth;
a.clip = audios[3];
a.Play(); // 倒れるときの声を再生
return true;
}
}
// 位置を重ねる
void Overlap(ref GameObject r, string s = "")
{
for (int n = 0; n < r.transform.childCount; n++)
{
// 子オブジェクトを探す
GameObject c = r.transform.GetChild(n).gameObject;
// 名前からボーンを検索
if (c.name == attackedBoneName)
{
attackedBoneRigidbody = c.GetComponent<Rigidbody>();
}
// パスを作る
string t = s == "" ? c.name : s + "/" + c.name;
// 同じ名前のオブジェクトを探す
GameObject d = transform.Find(t).gameObject;
// 位置と回転を合わせる
c.transform.position = d.transform.position;
c.transform.rotation = d.transform.rotation;
Overlap(ref c, t);
}
}
敵の各ボーンに付けたスクリプトで、敵のHPを減らしてゲージに反映するメソッドを呼びます。この時、刀などで攻撃する場合はトリガーを使うので、攻撃の速度は省略します。
敵のHPが0になると、敵と同じ位置にラグドールを生成して、敵のボーンの位置とラグドールのボーンの位置を重ねることでラグドールが敵と同じ姿勢になるようにします。
このときに、ラグドールの子オブジェクトをすべて検索するので、攻撃を受けたボーンと同じ名前のラグドールのボーンがあれば、そのRigidbodyを変数に入れます。
この変数は直前にnullを入れて置いて、検索した後にtrueならAddForceを呼ぶようにしました。ボーンが見つからなかったり、見つかったボーンにRigidbodyがなかったらfalseになります。
近接攻撃のときは、プレイヤーから敵へのベクトルを使ってボーンに力を加えます。