Developer

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

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

今回の内容

今回から3回に分けて、ギミック(ドラゴン)の作成を進めます。
まずはドラゴンの見た目の作成から、炎を吐くところまでを作成していきます。

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

シーンの追加

新たにシーンを追加します。
GameScene1 を複製して、GameScene3 を作成しましょう。
(プロジェクトビューで GameScene1 を選択して Ctrl + D で複製できます。)

忘れないうちに、Build Setting からシーンを追加しておきましょう。
前回も GameScene1, 2 を追加しましたが、ここに追加しておかないとシーンの切り替えに失敗します。

中段の床および箱の大きさと位置を以下に設定してください。


以下のようなステージになっていればOKです。

ドラゴンの追加

ドラゴンを追加していきますが、まだアセットは使わないので、Cube と Sphere で以下のようなオブジェクトを作ります。
Cube だけだとどちらが正面かわからないので、Sphere を置いて正面がわかるようにします。

作成手順は以下です。

① Create Empty で空オブジェクトを配置して、名前を Dragon にする
② Cube を ①の Dragon の子オブジェクトにする
③ Sphere を ①の Dragon の子オブジェクトにする
④ Dragon, Cube, Sphere の Transform を調整する
⑤ Sphere に Red_Material を設定する

③までで以下の構成になります。

④に関しては、以下の通り設定します。

やってみると気が付くかもしれませんが、ここで大事なことが一点あり、
ドラゴンの正面をローカル座標のZ軸方向としていることに注意してください。

この理由ですが、
Unity では「tranform.forward」でオブジェクトの正面方向のベクトルを取得できるのですが、
その正面と言うのはオブジェクトのZ軸方向と対応しています。
後にスクリプトを書く際に扱いやすいように、この向きを意識してオブジェクトを構成しています。
ほとんどのストアアセットでもZ軸方向が正面となるようにモデルが作成されているので、覚えておくと良さそうです。

最後に、⑤ですが、わかりやすいように Sphere を赤くします。
以前作成した Red_Material をドラッグして Sphere に設定します。

冒頭の画像の様なオブジェクトができていれば完成です。
ドラゴンと言いつつも、この段階では何だかわからないですが・・気にせず進めましょう。

炎の追加

次にドラゴンが吐き出す炎を追加します。
これは最終的には炎のエフェクトを使用しますが、現段階では Cube を引き延ばして赤くしたもので代用します。

先ほどと同様に、Dragon の子オブジェクトとして Cube を追加し、名前を Fire とします。

Fire の Transform を以下に設定します。

Fire のコライダーはトリガータイプとしておきましょう。

Sphere と同様に、Fire にも Red_Material を適用しましょう。
これで冒頭の画像と同様のデザインとなるはずです。

最後に、Fire は特定の条件の時に表示する形とするので、デフォルトでは非表示としておきます。
インスペクタービューで名前の横のチェックを外せば完了です。

ドラゴンに炎を吐かせる

まずは対象(プレイヤー)を検知するためのコライダーを設定します。
Dragon に BoxCollider を追加して、以下の設定とします。

以下画像のようなコライダー配置となっていて、ドラゴンの視界を表現しているようなイメージです。

※厳密にやるなら半円系にした方が良いですが、ここでは簡単のため長方形としました。

このあとはスクリプトを使って、設定したコライダーの中にプレイヤーがいれば炎を吐く処理を作成します。

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

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

public class DragonScript : MonoBehaviour
{
    public GameObject Fire;

    void Start()
    {
        
    }

    void Update()
    {

    }

    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);
    }
}

そんなに長くはないですが、ここまでの連載では見慣れないコードがあるので以下解説します。

21行目
実体をもつ対象のみを検知するようにしたいので、対象のコライダーがトリガーなら無視するようにしています。

26行目
対象オブジェクトの位置を取得しているだけですが、transform.position で取得すると足元の位置を取得してしまったりします。
対象の中心位置を取得したい時は、(Colliderオブジェクト).bounds.centerで取得できます。

29, 33行目
関連しているので2つの行をまとめて説明します。
先に下の33行目ですが、検知した対象(プレイヤー)の位置まで Linecast(光線)を飛ばして、間に障害物が無いかを調べています。

注意する点として、障害物にはプレイヤーは含まれない、と言う点に気を付ける必要があります。
そこででてくるのが29行目の処理で、プレイヤーのレイヤー以外を対象にしたレイヤーマスクを作成し、
これを Linecast の引数に渡すことで、プレイヤー以外を対象にヒットする光線を生成しています。

35-39行目, 44-47行目
炎を吐いたり、吐きやめたりの処理を実装しています。
35-39行目はさきほどの33行目の判定によって実行されるブロックで、
・炎(Fire)を表示する
・1秒後に炎を非表示にする(メソッドを呼び出す)
この2つの処理を行っています。
そして非表示の際に呼び出されるメソッドが、44-47行目になります。
ここはプロトタイプ段階ではちょっと雑な処理となっているので、アセット編で修正予定です。

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

スクリプトの解説はこれくらいにして、続きを実装します。

Dragonオブジェクトに DragonScriptをアタッチしましょう。
続けてヒエラルキービューで、Dragon の DragonScript > Fire に Fireオブジェクトを設定します。

ここまでできたら一度シーンを再生してみましょう。
箱が無くなると、ドラゴンが炎を吐いている事が確認できればOKです。

今回の実装は一旦ここまでとします。

おわりに

次回以降は、
・プレイヤーが炎に触れたらゲームオーバーにする
・ドラゴンをギミックで倒せるように
・プレイヤーがドラゴンに触れたらゲームオーバーにする
・ドラゴンが対象の方向を向くように
これらの処理を実装していきます!

 
 

連載目次リンク

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

関連する連載リンク

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

© Unity Technologies Japan/UCL