Developer

【Unity実践】#13 プロトタイプ編 ~ ギミックの作成  part2 ~【Boxゲーム】
2021.03.04
Lv2

【Unity実践】#13 プロトタイプ編 ~ ギミックの作成 part2 ~【Boxゲーム】

今回の内容

今回はドラゴンの作成の第2回目です。
・プレイヤーが炎に触れたらゲームオーバーにする
・ドラゴンをギミックで倒せるように
・プレイヤーがドラゴンに触れたらゲームオーバーにする
これら3点を実装します!

※初めての方はこちらから
【第1回記事】この連載について

炎のスクリプトを追加

プレイヤーが炎に触れるとゲームオーバーになる処理を作成します。
今回は、炎にスクリプトをアタッチして、OnTriggerEnter でプレイヤーにダメージを与えます。

新規スクリプト「FireScript」を作成して以下を記述しましょう。

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

public class FireScript : MonoBehaviour
{
    private void OnTriggerEnter(Collider other)
    {
        if(other.tag == "Player")
        {
            other.GetComponent<PlayerScript>().isDamaged = true;
        }
    }
}

Fire(Dragon の子オブジェクト)にアタッチしたら、シーンを再生しましょう。

これでプレイヤーが炎に触れると、ダメージを受けてゲームオーバーとなります。

トラップでドラゴンを倒せるようにする

以前作成したトラップを使って、ドラゴンを倒す仕組みを実装します。
まずはドラゴンにダメージを受けた際のフラグを追加して、消滅する処理を実装しましょう。
DragonScript に以下を追記してください。

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

public class DragonScript : MonoBehaviour
{
    public GameObject Fire;
    public bool isDamaged;

    void Start()
    {
        
    }

    void Update()
    {
        if (isDamaged) Destroy(gameObject);
    }

    private void OnTriggerStay(Collider other)
    {
        if (other.isTrigger) return;

        if(other.tag == "Player")
        {
            // ターゲット位置
            Vector3 targetPos = other.bounds.center;

            // プレイヤー以外のレイヤマスク
            int layerMask = ~(1 << other.gameObject.layer);

            // プレイヤー以外を対象にLinecastして、ヒットするかチェック
            // ヒットしなければ、炎を吐く
            if (!Physics.Linecast(transform.position, targetPos, layerMask, QueryTriggerInteraction.Ignore))
            {
                if (!Fire.activeSelf)
                {
                    Fire.SetActive(true);
                    Invoke("DisableFire", 1.0f);
                }
            }
        }
    }

    void DisableFire()
    {
        Fire.SetActive(false);
    }
}

次に、TrapScript に以下を追記します。

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

public class TrapScript : MonoBehaviour
{
    private void OnCollisionEnter(Collision other)
    {
        if (other.gameObject.tag == "Player")
        {
            other.gameObject.GetComponent<PlayerScript>().isDamaged = true;
        }

        if (other.gameObject.tag == "Dragon")
        {
            other.gameObject.GetComponent<DragonScript>().isDamaged = true;
        }
    }
}

「Dragon」タグの付いたオブジェクトと衝突するとダメージを与えるようしています。

最後にDragonオブジェクトに「Dragon」タグの設定と、Rigidbodyコンポーネントを追加しましょう。

ここまでで実装は完了です。
シーンにトラップを追加してテストしてみましょう。

ドラゴンがトラップに触れると消滅していれば成功です。

プレイヤーがドラゴンに触れるとゲームオーバーにする

プレイヤーがドラゴンに触れた時にゲームオーバーとする処理を実装します。
DragonScript に以下を追記してください。

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

public class DragonScript : MonoBehaviour
{
    public GameObject Fire;
    public bool isDamaged;

    void Start()
    {
        
    }

    void Update()
    {
        if (isDamaged) Destroy(gameObject);
    }

    private void OnTriggerStay(Collider other)
    {
        if (other.isTrigger) return;

        if(other.tag == "Player")
        {
            // ターゲット位置
            Vector3 targetPos = other.bounds.center;

            // プレイヤー以外のレイヤマスク
            int layerMask = ~(1 << other.gameObject.layer);

            // プレイヤー以外を対象にLinecastして、ヒットするかチェック
            // ヒットしなければ、炎を吐く
            if (!Physics.Linecast(transform.position, targetPos, layerMask, QueryTriggerInteraction.Ignore))
            {
                if (!Fire.activeSelf)
                {
                    Fire.SetActive(true);
                    Invoke("DisableFire", 1.0f);
                }
            }
        }
    }

    private void OnCollisionEnter(Collision collision)
    {
        if(collision.gameObject.tag == "Player")
        {
            collision.gameObject.GetComponent<PlayerScript>().isDamaged = true;
        }
    }

    void DisableFire()
    {
        Fire.SetActive(false);
    }
}

今のシーンの配置だとテストができないので、一時的に以下の様に、
床を伸ばしてドラゴンの向きを変えると、テストができます。

テスト後は、配置は元にもどしておきましょう。

※補足:コライダーが無いのにOnCollisionEnter・・?
Dragonオブジェクトを見てみると、特にコライダーは設定されていないのに、
DragonScript の OnCollisionEnter は実行されているので疑問に思うかもしれません。

なぜコライダーがないのに衝突判定ができているかというと、Dragon の Rigidbodyコンポーネントがカギとなっています。
コライダー関連の特徴として、

Rigidbody が設定されていると、子オブジェクトのコライダーも適用される

と言う特徴があります。
結構大事な特徴なので覚えておきましょう。

おわりに

今回はここまでとなります。
残す実装として、
・ドラゴンが対象の方向を向くように
次回はこの機能の実装と細かい点の修正を行いたいと思います!

 
 

連載目次リンク

実践Unityゲームプログラミング 連載目次
 

関連する連載リンク

「初心者のための」Unityゲーム制作 目次
 

© Unity Technologies Japan/UCL