【Unityゲーム作成①】アセット編 ~ 箱の作成 part2 ~


今回の内容


今回も箱のアセット適用、調整を行います。
まずは前回の最後に整理した以下の課題を対応して、箱の完成まで進めます。

課題
・箱をタップしたときに、消えるのではなく壊れるようにする。
・壊れた後の箱にコリジョンがある。(プレイヤーが乗らないようにしたい)

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

★前回までのソースコード
GitHub

タップ時に箱が壊れるようにする


まずは課題の1つ目ですが、現状の動きと理想の動きが以下になります。

↓ 現状の動き

↓ 理想の動き

対応の方針としては以下です。

方針
・BoxUnit に、自分自身を壊すメソッドを用意する(public で、外から呼べるように)
・BoxScript で、Destroy していた場所を変更。各子要素の上記メソッドを呼ぶ。

まずは方針の1つ目、BoxUnit のスクリプトを変更しましょう。
BoxUnit には標準で CrashCrateスクリプトが適用されています。

これを開いて、以下の通り Crashメソッドを追加しましょう。
Crashメソッドの処理内容は、OnTriggerEnterメソッドの4行をコピペしています。
ついでに、OnTriggerEnterメソッドはコメントアウトして無効にしておきます。

namespace ArionDigital
{
    using UnityEngine;

    public class CrashCrate : MonoBehaviour
    {
        [Header("Whole Create")]
        public MeshRenderer wholeCrate;
        public BoxCollider boxCollider;
        [Header("Fractured Create")]
        public GameObject fracturedCrate;
        [Header("Audio")]
        public AudioSource crashAudioClip;

        // コメントアウト
        //private void OnTriggerEnter(Collider other)
        //{
        //    wholeCrate.enabled = false;
        //    boxCollider.enabled = false;
        //    fracturedCrate.SetActive(true);
        //    crashAudioClip.Play();
        //}

        // このメソッドを追加
        public void Crash()
        {
            wholeCrate.enabled = false;
            boxCollider.enabled = false;
            fracturedCrate.SetActive(true);
            crashAudioClip.Play();
        }

        [ContextMenu("Test")]
        public void Test()
        {
            wholeCrate.enabled = false;
            boxCollider.enabled = false;
            fracturedCrate.SetActive(true);
        }
    }
}

次に BoxScript を以下の通り変更します。

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

public class BoxScript : MonoBehaviour
{
    public enum PlayerMove { Default, MoveLeft, MoveRight }

    public PlayerMove playerMove;

    PlayerScript player;

    void Start()
    {
        player = GameObject.Find("Player").GetComponent<PlayerScript>();
    }

    public void onBoxClick()
    {
        // プレイヤーの移動を開始する
        switch (playerMove)
        {
            case PlayerMove.MoveLeft:
                PlayerMoveLeft();
                break;
            case PlayerMove.MoveRight:
                PlayerMoveRight();
                break;
        }

        // 子オブジェクト(箱)を全て破壊
        foreach (Transform unit in transform)
        {
            unit.gameObject.GetComponent<CrashCrate>().Crash();
        }

        // 破片が残るので消滅させる
        Destroy(gameObject, 1.0f);
    }

    // 初期配置で右に移動させる場合に使う
    void PlayerMoveRight()
    {
        if (!player.isMove)
        {
            player.MoveRight();
        }
    }

    // 初期配置で左に移動させる場合に使う
    void PlayerMoveLeft()
    {
        if (!player.isMove)
        {
            player.MoveLeft();
        }
    }
}

スクリプトで押さえておきたい点としては、33行目の foreach です。
Transformオブジェクト に対して foreach をかけると、子要素の Transformオブジェクトを取得できます。
今回の様に、子要素全てを取得して操作したい時には便利だと思います。

これでシーンを再生すると、以下の通り目的の動作となります。

壊れた後の箱のコリジョンを無くす


前回最初に箱を置いたときにも確認しましたが、以下のような配置で箱を壊すと、
壊れた後の箱とプレイヤーが衝突してしまいます。

これを解決するために、以下の対応を行います。

壊れた後の破片のレイヤーは、破片同士でしか衝突しないようにする。

BoxUnit > Crash_Crate_Fractured_LOD_1 を選択して下さい。

新規レイヤー「Crash_Crate_Piece」を追加して設定します。

同様に、BoxUnit(1)、BoxUnit(2)、BoxUnit(3)の「Crash_Crate_Fractured_LOD_1」のレイヤも、
「Crash_Crate_Piece」としてください。

「Crash_Crate_Piece」レイヤーの衝突判定を、「Crash_Crate_Piece」に限定する設定を行います。
Edit > Project Settings を開いてください。

Physics の項目で、衝突判定を以下画像の通り設定してください。

これで壊れた箱との衝突が無効となります。

Box_Wall に触れると反転するようにする


Box_Wall はプレイヤーが衝突すると反転する必要があります。
プロトタイプの時と同様に Box_Wall に Wallタグを設定しましょう。

さらに、右側の Box の BoxScript で、PlayerMove を 「MoveRight」として確認してみます。

黄色い箱を壊すとプレイヤーが移動を開始しますが、Box_Wall をすり抜けてしまっています・・

初歩的なことで、コライダーの設定を行っていないのが原因です。
今回は、子要素である BoxUnit に沿ったコライダーを取得したいので、以下の設定を行います。

1.BoxUnit の BoxCollider(既存)のIsTriggerを外す
2.Box_Wall に Rigidbody を追加する。


この対応の補足ですが、衝突するだけであれば1.の子要素のコライダー設定だけで済みます。
ただ、Wallタグを親要素の設定しているので、この判定を有効にするためには親要素側で衝突判定を持つ必要があります。
親要素にコライダーを設定する方法もありますが、今回のように子要素の形状に合わせたコライダー設定としたい場合、
親にRigidbodyを設定することで、子オブジェクトの形状に沿ったコライダーを親も持つような状態となります。
これによって、親に付いた Wallタグが有効となります。

再生すると以下の通り、衝突して反転もするようになります。

プレハブ化する


これでおよそ対応は完了となるのでプレハブ化を行いましょう。
プロトタイプの Box_Wall は上書きしてしまって構いません。(不安ならリネームして退避させましょう。)

最後に、水平に置くためのBoxプレハブを作成します。
紛らわしいのでシーンにある既存のBoxは削除します。

↓ 削除後の状態

作成手順ですが、Box_Wall を複製して、名前を Box とします。
タグの Wall は削除(Untagged に設定)して、位置を「0, 0, 0」としておきます。

子要素のBoxUnit(1)、BoxUnit(2)、BoxUnit(3)の位置を、それぞれ以下に設定してください。

親の位置を調整して、PlayerMove は 「Default」としておきましょう。

以下の様に、問題無く再生できていれば成功です。

これで完成となるので、Boxもプレハブ化します。(プロトタイプのBoxを上書きします。)

長かったですがこれで一旦、箱のアセット適用が完了となります。

おわりに


箱の作成はこれで完了となります。
実際のソースではもう少し細かい点も調整していたりするので、一部紹介だけしておきます。

・箱を色分けできるように
・壊れるときの音を、1つのオブジェクトだけ再生するように(今はBoxUnitごとに再生している)

例えばこの辺を調整していたりするので、余裕のある方は練習がてら対応してみて下さい。

次回はゴールやトラップにアセットを適用する予定です!

★今回までのソースコード
GitHub


 

© Unity Technologies Japan/UCL

  • このエントリーをはてなブックマークに追加

PAGE TOP