【Unity】グレネードの爆発で敵を吹き飛ばす【物理】

投稿者: | 2020-08-09

グレネードを投げると数秒後に爆発して、敵やアイテムを吹き飛ばすようにします。

まず敵のスクリプトにパブリックなメソッドを作ります。

public void Explode(Vector3 center)
{

    // 体力を増減してゲージに反映
    HP += -0.8f;
    HP = Mathf.Clamp(HP, 0f, 1f);
    HpImage.fillAmount = HP;


    // 体力が残っているとき
    if (HP > 0f)
    {
        Flinch(); // 怯む

        return;
    }
    else
    {

        Destroy(gameObject); // 敵を破壊

        var r = Instantiate(ragdoll, transform.position, transform.rotation); // ラグドールを生成

            
        //rigidbodyList = new List<Rigidbody>();

        Overlap(ref r); // 敵とラグドールを重ねる

        /*
        if (rigidbodyList.Count != 0)
        {
            foreach (Rigidbody rb in rigidbodyList)
            {
                rb.AddExplosionForce(600f, center, 20f, 4f);
            }
        }
        */
    }

}

void Overlap(ref GameObject r, string s = "")
{
    for (int n = 0; n < r.transform.childCount; n++)
    {
        // 子オブジェクトを探す
        GameObject c = r.transform.GetChild(n).gameObject;


        // Rigidbodyをあればリストに保存
        //Rigidbody rb = c.GetComponent<Rigidbody>();
        //if (rb) rigidbodyList.Add(rb);

        // パスを作る
        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になると敵を破壊して同じ位置にラグドールを作り、ラグドールの各ボーンの位置や回転を敵のものと重ねることで同じ姿勢にします。HPが残れば怯むモーションが再生されます。

そして、グレネードのスクリプトでは、投げられた数秒後にタグから敵を探して、このメソッドを呼びます。

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


public class GrenadeScript : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Invoke("Explode", 3f);
    }

    void Explode()
    {
        GameObject[] enemys = GameObject.FindGameObjectsWithTag("Agent"); // 敵を探す

        Vector3 center = transform.position; // グレネードの位置

        // 敵がいれば
        if (enemys.Length != 0)
        {         
            foreach (GameObject e in enemys)
            {
                AgentAttackTest sc_agent = e.GetComponent<AgentAttackTest>();
                if (sc_agent) sc_agent.Explode(center);
            }
        }

        // アイテムを飛ばす
        GameObject[] items = GameObject.FindGameObjectsWithTag("Item");

        if (items.Length != 0)
        {
            foreach (GameObject i in items)
            {
                Rigidbody r = i.GetComponent<Rigidbody>();
                if(r) r.AddExplosionForce(600f, center, 20f, 4f);
            }
        }

        // ラグドールを飛ばす
        GameObject[] ragdolls = GameObject.FindGameObjectsWithTag("Ragdoll");

        if (ragdolls.Length != 0)
        {
            foreach (GameObject d in ragdolls)
            {
               
                Rigidbody r = d.GetComponent<Rigidbody>();

                if (r) r.AddExplosionForce(600f, center, 20f, 4f);

            }
        }
    }
}

その後、ItemとRagdollタグの付いたオブジェクトを探して、一つずつに爆発の力を加えます。これはRigidbody.AddExplosionForceを使えば簡単です。

RagdollタグはラグドールのRigidbodyの付いたボーン全てに設定されています。これで生成された直後のラグドールと同様に転がっているラグドールも吹っ飛びます。

はじめは、ラグドールと敵のボーンを重ねるときにボーンのRigidbodyをリストにいれて爆発の力を加えていましたが、グレネードのスクリプトでタグで検索して爆発の力を加える処理と重複して力が2度加わるようなのでやめました。

コメントを残す

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