【基本操作】タマあんどヒシガタ~1/3 キャラクター作成【パズル】

●タマ作成

最初にプレイヤーとして動かすタマを作成します。
タマの隣にジャンプ台がある時に画面をクリックすると、ジャンプ台に押したように動き出します。
まずは単純に、いきなり進み続けるように作成します。

▷タマ作成

球を作成してTransformをリセットし、青色設定したマテリアルを割り当てます。

タマ作成

・球作成

  1. ヒエラルキー左上の「+」をクリック
  2. 「3Dオブジェクト>スフィア」をクリック
  3. 「Tama」と入力し、ENTERキーを押す

・位置、回転、スケールリセット

  1. インスペクターのTransformにある縦の三点リーダーをクリック
  2. リセットをクリック

・マテリアル作成

  1. プロジェクトの「Assets」を右クリックし、「作成>マテリアル」をクリック
  2. 「matTama」と入力し、ENTERキーを押す

・マテリアル色設定

  1. インスペクターの「Main Maps>アルベド>カラーバー」をクリックし、色ダイアログの16進数を「0000FF」に設定
  2. 色ダイアログの右上にある「×」をクリック

・マテリアル割り当て

  1. プロジェクトの「matTama」をヒエラルキーの「Tama」にドラッグ&ドロップ

▷タマ制御

スクリプトを作成してタマに割り当て、「タマを30フレームに1メートルの速さで動く」ようにスクリプトを記述します。

タマ制御

・スクリプト作成

  1. プロジェクトの「Assets」を右クリックし、「作成>C# スクリプト」をクリック
  2. 「CharCtrl」と入力し、ENTERキーを押す

・スクリプト割り当て

  1. プロジェクトの「Assets>CharCtrl」をヒエラルキーの「Tama」にドラッグ&ドロップ

・スクリプト編集開始

  1. プロジェクトの「Assets>CharCtrl」をダブルクリック

・スクリプト変数定義

  1. クラス定義内の先頭に以下の変数を追加
    float moveFrame = 30;       // 1歩に何フレームかけるか
    float frameCount = 0;       // 経過フレーム数

・スクリプト関数定義

  1. クラス定義内の最後に以下の関数を追加
    // 物理フレーム更新時に処理
    void FixedUpdate()
    {
    }

スクリプト処理

  1. FixedFrameに以下の処理を記述
        // 1歩分のフレームが経過するまで何もしない
        frameCount++;
        if (frameCount < moveFrame) return;

        // 経過フレーム数を0初期化する
        frameCount = 0;

        // 向いている方向に1メートル進む
        transform.position += transform.forward;

・スクリプト保存

  1. CTRLを押しながらSキーを押す

・Unityに戻ってスクリプトをビルド

  1. Unityエディタのタイトルをクリック

▷タマ認識

スクリプトでタマを認識させるため、タグ「Player」をタマに割り当てます。

タマ認識

・タグ割り当て

  1. ヒエラルキーの「Tama」をクリック
  2. インスペクター上部のタグドロップダウンをクリックし、「Player」をクリック

・プロジェクト保存

  1. CTRLを押しながらSキーを押す

▷動作確認

タマが期待通り動くかどうか、プレビューして確認します。

動作確認

・プレビュー開始

  1. エディタ上中央の「▶」をクリック

・動作確認

  1. 奥に向かって1メートルごとに進むことを確認

・プレビュー終了

  1. エディタ上中央の「▶」をクリック

▷スクリプト記述例

「タマを30フレームに1メートルの速さで動く」スクリプトの記述例です。

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

public class CharCtrl : MonoBehaviour
{
    float moveFrame = 30;       // 1歩に何フレームかけるか
    float frameCount = 0;       // 経過フレーム数

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    // 物理フレーム更新時に処理
    void FixedUpdate()
    {
        // 1歩分のフレームが経過するまで何もしない
        frameCount++;
        if (frameCount < moveFrame) return;

        // 経過フレーム数を0初期化する
        frameCount = 0;

        // 向いている方向に1メートル進む
        transform.position += transform.forward;
    }
}

●ヒシガタ作成

次に、同じように動くキャラクター「ヒシガタ」を作成します。
タマと衝突すると両方とも消滅します。

▷ヒシガタ作成

箱を作成してTransformを「位置(0, 0, 0)、回転(0, 45, 0)、スケール(0.7, 1, 0.7)」とし、赤色設定したマテリアルを割り当てます。

ヒシガタ作成

・箱作成

  1. ヒエラルキー左上の「+」をクリック
  2. 「3Dオブジェクト>キューブ」をクリック

・位置、回転、スケール設定

  1. インスペクターのTransformにある位置を(0, 0, 0)とする
  2. インスペクターのTransformにある回転を(0, 45, 0)とする
  3. インスペクターのTransformにあるスケールを(0.7, 1, 0.7)とする

・マテリアル作成

  1. プロジェクトの「Assets」を右クリックし、「作成>マテリアル」をクリック
  2. 「matHisi」と入力し、ENTERキーを押す

・マテリアル色設定

  1. インスペクターの「MainMaps>アルベド>カラーバー」をクリックし、色ダイアログの16進数を「FF0000」に設定
  2. 色ダイアログの右上にある「×」をクリック

・マテリアル割り当て

  1. プロジェクトの「matHisi」をヒエラルキーの「Cube」にドラッグ&ドロップ

▷ヒシガタ階層化

空オブジェクトを作成してTransformを「位置(1, 0, 0)、回転(0, 270, 0)、スケール(1, 1, 1)」とし、赤色の箱を子供とします。

ヒシガタ階層化

・空オブジェクト作成

  1. ヒエラルキー左上の「+」をクリック
  2. 「空のオブジェクトを作成」をクリック
  3. 「Hisi」と入力し、ENTERキーを押す

・階層設定

  1. ヒエラルキーの「Cube」をヒエラルキーの「Hisi」にドラッグ&ドロップ

・位置、回転、スケール設定

  1. ヒエラルキーの「Hisi」をクリック
  2. インスペクターのTransformにある位置を(3, 0, 3)とする
  3. インスペクターのTransformにある回転を(0, 270, 0)とする
  4. インスペクターのTransformにあるスケールを(1, 1, 1)とする

▷ヒシガタ認識

タグ「Enemy」を作成し、ヒシガタに割り当てます。

ヒシガタ認識

・タグ作成

  1. ヒエラルキーの「Hisi」をクリック
  2. インスペクター上部のタグドロップダウンをクリックし、「タグを追加…」をクリック
  3. インスペクター「Tag & Layers」にあるタグ欄右下の「+」をクリック
  4. 「Enemy」と入力してENTERを押す

・タグ割り当て

  1. ヒエラルキーの「Hisi」をクリック
  2. インスペクターのタグドロップダウンをクリックし、「Enemy」をクリック

▷ヒシガタ制御

ヒシガタにCharCtrlを割り当て、CharCtrlを「タマとヒシガタが衝突したら両方削除する」ように修正します。

ヒシガタ制御

・スクリプト割り当て

  1. プロジェクトの「Assets>CharCtrl」をヒエラルキーの「Hisi」にドラッグ&ドロップ

・スクリプト編集開始

  1. プロジェクトの「Assets>CharCtrl」をダブルクリック

・タグでオブジェクトを検索

  1. FixedUpdate関数の処理先頭に「タグ検索でタマとヒシガタの一覧を取得する」処理を追加
        // タグ検索でタマとヒシガタの一覧を取得する
        GameObject[] tamas = GameObject.FindGameObjectsWithTag("Player");
        GameObject[] hisis = GameObject.FindGameObjectsWithTag("Enemy");

・衝突時にオブジェクトを削除

  1. 移動処理の後に「ヒシガタとタマが衝突したら両方削除」する処理を追加
        // ヒシガタとタマが衝突したら両方削除
        if (tamas.Length != 0 && hisis.Length != 0)
        {
            // タマとヒシガタの位置が同じだった場合
            if (tamas[0].transform.position == hisis[0].transform.position)
            {
                // タマとヒシガタを削除
                Destroy(tamas[0]);
                Destroy(hisis[0]);
            }
        }

・スクリプト保存

  1. CTRLを押しながらSキーを押す

・Unityに戻ってスクリプトをビルド

  1. Unityエディタのタイトルをクリック

・プロジェクト保存

  1. CTRLを押しながらSキーを押す

▷動作確認

ヒシガタが期待通り動き、タマと衝突したら両方消えるかどうか、プレビューして確認します。

動作確認

・プレビュー開始

  1. エディタ上中央の「▶」をクリック

・動作確認

  1. ヒシガタが左奥に向かって進むことを確認
  2. タマとヒシガタがぶつかったら両方消えることを確認

・プレビュー終了

  1. エディタ上中央の「▶」をクリック

▷スクリプト記述例

「タマとヒシガタが衝突したら両方削除する」スクリプトの記述例です。

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

public class CharCtrl : MonoBehaviour
{
    float moveFrame = 30;       // 1歩に何フレームかけるか
    float frameCount = 0;       // 経過フレーム数

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    // 物理フレーム更新時に処理
    void FixedUpdate()
    {
        // タグ検索でタマとヒシガタの一覧を取得する
        GameObject[] tamas = GameObject.FindGameObjectsWithTag("Player");
        GameObject[] hisis = GameObject.FindGameObjectsWithTag("Enemy");

        // 1歩分のフレームが経過するまで何もしない
        frameCount++;
        if (frameCount < moveFrame) return;

        // 経過フレーム数を0初期化する
        frameCount = 0;

        // 向いている方向に1メートル進む
        transform.position += transform.forward;

        // ヒシガタとタマが衝突したら両方削除
        if (tamas.Length != 0 && hisis.Length != 0)
        {
            // タマとヒシガタの位置が同じだった場合
            if (tamas[0].transform.position == hisis[0].transform.position)
            {
                // タマとヒシガタを削除
                Destroy(tamas[0]);
                Destroy(hisis[0]);
            }
        }
    }
}

●トゲ作成

動かないヒシガタである「トゲ」を作成します。
タマやヒシガタが衝突するとトゲとともに消滅します。

▷トゲ作成

同じ構成なので、ヒシガタをコピーして利用します。
名前を変更して位置を(1, 0, 3)とし、色を紫に変更します。

トゲ作成

・オブジェクト複製

  1. ヒエラルキーの「Hisi」をクリック
  2. CTRLを押しながらDキーを押す

・オブジェクト名変更

  1. F2キーを押す
  2. 「Toge」と入力し、ENTERキーを押す

・位置設定

  1. インスペクターのTransformにある位置を(1, 0, 3)に設定

・アセット複製

  1. プロジェクトの「Assets>matHisi」をクリック
  2. CTRLを押しながらDキーを押す

アセット名変更

  1. F2キーを押す
  2. 「matToge」を入力し、ENTERキーを押す

・マテリアル色設定

  1. インスペクターの「Main Maps>アルベド>カラーバー」をクリックし、色ダイアログの16進数を「FF00FF」に設定
  2. 色ダイアログの右上にある「×」をクリック

・マテリアル割り当て

  1. ヒエラルキーの「Toge」左にある「▶」をクリック
  2. プロジェクトの「Assets>matToge」をヒエラルキーの「Toge>Cube」にドラッグ&ドロップ

▷トゲ認識

タグ「Toge」を作成し、トゲに割り当てます。

トゲ認識

・タグ作成

  1. ヒエラルキーの「Toge」をクリック
  2. インスペクターのタグドロップダウンをクリックし、「タグを追加…」をクリック
  3. インスペクター「Tag & Layers」にあるタグ欄右下の「+」をクリック
  4. 「Toge」と入力してENTERを押す

・タグ割り当て

  1. ヒエラルキーの「Toge」をクリック
  2. インスペクターのタグドロップダウンをクリックし、「Toge」をクリック

▷トゲ制御

トゲは動かないのでCharCtrlスクリプトを外します。
「自分(タマかヒシガタ)がトゲと衝突した時に両方消える」ようにCharCtrlを修正します。
結果、トゲとタマ、もしくはトゲとヒシガタが衝突した時に両方が消えるようになります。

トゲ制御

・コンポーネント削除

  1. ヒエラルキーの「Toge」をクリック
  2. インスペクターの「Char Ctrl(スクリプト)」にある縦の三点リーダーをクリック
  3. 「コンポーネントを削除」をクリック

・スクリプト編集開始

  1. プロジェクトの「Assets>CharCtrl」をダブルクリック

・スクリプト関数定義

  1. FixedUpdate関数の後に以下の関数を追加
    // 指定位置にあるオブジェクトを取得
    GameObject GetObject(Vector3 pos)
    {
        // 指定位置にオブジェクトが無いのでNULLを返す
        return null;
    }

・スクリプト関数作成

  1. GetObject内の「指定位置にオブジェクトが無いのでNULLを返す」前に以下の処理を追加
        // 小数点誤差を補正
        float posX = Mathf.Floor(pos.x + 0.5f);
        float posZ = Mathf.Floor(pos.z + 0.5f);
        // 処理対象とするタグの一覧を作成
        string[] tags = new string[] { "Toge" };
        // タグを1つ1つ処理
        for (int i = 0; i < tags.Length; i++)
        {
            // 指定タグのオブジェクト一覧を取得
            GameObject[] objs = GameObject.FindGameObjectsWithTag(tags[i]);
            // オブジェクトを1つ1つ処理
            for (int j = 0; j < objs.Length; j++)
            {
                // 指定位置に存在するオブジェクトを返す
                Vector3 objPos = objs[j].transform.position;
                if (objPos.x == posX && objPos.z == posZ) return objs[j];
            }
        }

・スクリプト関数呼び出し

  1. FixedUpdate関数の最後に以下の処理を記述
        // 重なったオブジェクトを取得
        GameObject obj = GetObject(transform.position);
        // トゲと重なったら自分とトゲを削除
        if (obj != null && obj.tag == "Toge")
        {
            Destroy(gameObject);
            Destroy(obj);
        }

・スクリプト保存

  1. CTRLを押しながらSキーを押す

・Unityに戻ってスクリプトをビルド

  1. Unityエディタのタイトルをクリック

・プロジェクト保存

  1. CTRLを押しながらSキーを押す

▷動作確認

ヒシガタがトゲと衝突したら両方消えるかどうか、プレビューして確認します。

動作確認

・プレビュー開始

  1. エディタ上中央の「▶」をクリック

・動作確認

  1. ヒシガタとトゲがぶつかったら両方消えることを確認

・プレビュー終了

  1. エディタ上中央の「▶」をクリック

・プレビュー開始

  1. エディタ上中央の「▶」をクリック

・プレビュー一時停止

  1. エディタ上中央の「||」をクリック

・仮編集

  1. ヒエラルキーの「Toge」をクリック
  2. インスペクターのTransformにある位置を(0, 0, 2)に設定

・プレビュー再開

  1. エディタ上中央の「||」をクリック

・動作確認

  1. タマとトゲがぶつかったら両方消えることを確認

・プレビュー終了

  1. エディタ上中央の「▶」をクリック

▷スクリプト記述例

「トゲと重なったら自分とトゲを削除する」スクリプトの記述例です。

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

public class CharCtrl : MonoBehaviour
{
    float moveFrame = 30;       // 1歩に何フレームかけるか
    float frameCount = 0;       // 経過フレーム数

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    // 物理フレーム更新時に処理
    void FixedUpdate()
    {
        // タグ検索でタマとヒシガタの一覧を取得する
        GameObject[] tamas = GameObject.FindGameObjectsWithTag("Player");
        GameObject[] hisis = GameObject.FindGameObjectsWithTag("Enemy");

        // 1歩分のフレームが経過するまで何もしない
        frameCount++;
        if (frameCount < moveFrame) return;

        // 経過フレーム数を0初期化する
        frameCount = 0;

        // 向いている方向に1メートル進む
        transform.position += transform.forward;

        // ヒシガタとタマが衝突したら両方削除
        if (tamas.Length != 0 && hisis.Length != 0)
        {
            // タマとヒシガタの位置が同じだった場合
            if (tamas[0].transform.position == hisis[0].transform.position)
            {
                // タマとヒシガタを削除
                Destroy(tamas[0]);
                Destroy(hisis[0]);
            }
        }

        // 重なったオブジェクトを取得
        GameObject obj = GetObject(transform.position);
        // トゲと重なったら自分とトゲを削除
        if (obj != null && obj.tag == "Toge")
        {
            Destroy(gameObject);
            Destroy(obj);
        }
    }

    // 指定位置にあるオブジェクトを取得
    GameObject GetObject(Vector3 pos)
    {
        // 小数点誤差を補正
        float posX = Mathf.Floor(pos.x + 0.5f);
        float posZ = Mathf.Floor(pos.z + 0.5f);
        // 処理対象とするタグの一覧を作成
        string[] tags = new string[] { "Toge" };
        // タグを1つ1つ処理
        for (int i = 0; i < tags.Length; i++)
        {
            // 指定タグのオブジェクト一覧を取得
            GameObject[] objs = GameObject.FindGameObjectsWithTag(tags[i]);
            // オブジェクトを1つ1つ処理
            for (int j = 0; j < objs.Length; j++)
            {
                // 指定位置に存在するオブジェクトを返す
                Vector3 objPos = objs[j].transform.position;
                if (objPos.x == posX && objPos.z == posZ) return objs[j];
            }
        }

        // 指定位置にオブジェクトが無いのでNULLを返す
        return null;
    }
}

作成手順を書いた記事です。

   →紹介
今▷ →1/3 キャラクター作成
次▷ →2/3 オブジェクト作成
   →3/3 ゲーム仕上げ

完全手順
※紹介と1~3の手順を1ページにまとめています。
 読み込みに時間がかかるかも知れません。

コメント

タイトルとURLをコピーしました