【Unity】ラグドールに攻撃の力を加える

投稿者: | 2020-08-01

攻撃して敵が倒れた時に、その攻撃の力でラグドールが吹き飛ぶようにします。

敵を複製してラグドールを作ったので、敵とラグドールは全く同じボーンを持っています。敵の攻撃を受けたボーンの名前はわかるので、敵とラグドールの各ボーンの位置を揃えるときにその名前と同じ名前のラグドールのボーンを探します。

// 敵のボーンのスクリプト
// 遠隔攻撃を受けたとき
 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になります。

ボーンが見つからないとき
見つかったボーンにRigidbodyが無いとき

近接攻撃のときは、プレイヤーから敵へのベクトルを使ってボーンに力を加えます。

コメントを残す

メールアドレスが公開されることはありません。