Developer

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

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

今回の内容

今回はドラゴンの作成の第3回目で、完成まで実装を進めます!

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

プレイヤーが倒れたら炎を吐かないようにする

前回までの実装では、プレイヤーが倒れたあともドラゴンが炎を吐き続けていました。

仕様的にはこのままと言う手もありますが、今回は吐きやめる形で進めます。
これは簡単で、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" && !StageControllerScript.isGameOver)
        {
            // ターゲット位置
            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);
    }
}

ゲームオーバー時に再度炎を吐いていなれば成功です。

プレイヤーの方向を向くようにする

ドラゴンがプレイヤーの向きを向くようにします。
ついでに、炎を吐き終えると元の向きに戻るような仕様とします。

DragonScript に追記して、以下の様にしましょう。

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

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

    void Start()
    {
        DefaultRot = transform.rotation;
    }

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

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

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

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

            // プレイヤー以外を対象にLinecastして、ヒットするかチェック
            // ヒットしなければ、炎を吐く
            if (!Physics.Linecast(transform.position, targetPos, layerMask, QueryTriggerInteraction.Ignore))
            {
                if (!Fire.activeSelf)
                {
                    transform.LookAt(other.transform);
                    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);
        transform.rotation = DefaultRot;
    }
}

対象の向きを向く処理
39行目の transform.lookAt で実装しています。
メソッド名の通り、引数の Transform の方向を向いてくれます。

(関連記事)
Transformコンポーネントの便利な関数まとめ

向きを元に戻す処理
DefaultRot に初期状態での向きを保存しておきます。
炎を吐きやめる処理(DisableFire)で、向きを DefaultRot にすることで元に戻しています。

=======================================

記述ができたら、ドラゴンの向きを画面手前に変更しましょう。

シーンを再生して、炎を吐いた後に正面に向き戻れば成功です。

一旦これでプロト段階でのドラゴンは完成となるので、Dragon をプレハブ化しておきましょう。

床にスクリプトを追加

さて、今回のテーマのドラゴンとはズレるのですが、ここで1点問題があり、
現状のステージではプレイヤーが落下した後も直進を続けてしまい、クリアが不可能となっています。

そこで床に適用する新規のスクリプトを作成して、
床ごとにプレイヤーが触れたら「右に向く」、「左に向く」、「そのまま進む」を設定できるようにします。

FloorScript を作成して、以下のコードを記述してください。

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

public class FloorScript : MonoBehaviour
{
    public enum PlayerAction { Default, TurnLeft, TurnRight }

    public PlayerAction playerAction;

    private void OnCollisionEnter(Collision other)
    {
        // defaultなら何もしない
        if (playerAction == PlayerAction.Default) {
            return;
        }

        if (other.transform.tag == "Player") {
            PlayerScript player = other.gameObject.GetComponent<PlayerScript>();

            // プレイヤーの移動を開始する
            switch (playerAction)
            {
                case PlayerAction.TurnLeft:
                    player.TurnLeft();
                    break;
                case PlayerAction.TurnRight:
                    player.TurnRight();
                    break;
            }
        }
    }
}

ソースコードの解説は割愛しますが、BoxScript の時と同様に Enum を用意して、
設定を変更できるようにしています。

これを、プレハブの Floor に適用しましょう。

さらに、GameScene3 の下部の床を選択して、FloorScript の Player Action を「TurnLeft」に設定してください。

これで GameScene3 がクリアできるようになります。

おわりに

今回の内容はちょっと短めですがここまでとなります。
プロトタイプ編についてはここまでで一区切りとして、次回からはアセット適用編へと進む予定です。

アセットを適用することで、ゲームらしさが一気に増してきますのでお楽しみに!

 
 

連載目次リンク

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

関連する連載リンク

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

© Unity Technologies Japan/UCL