音無サノトの空想録

4コマ漫画と創作日記

【ゲーム制作】Unityを利用した横スクロールゲーム開発 03 制限時間とBGMの追加

どうも音無サノトです。

個人的趣味でやっているゲーム制作メモです。

 

今日の成果

  • 時間制限の追加
  • 土台が落ちるトラップの追加
  • BGMの追加

 

作業ログ

 時間制限の追加

ゲームに緊張感を持たせるため時間制限の処理を追加します。

まずゲームの様々な要素を管理するために「GameController」という空のオブジェクトを用意します。

f:id:otonasisanoto:20200913120118p:plain

 

次に時間を表示するテキストとタイムオーバーになった時のテキストをCanvasプレハブ内に用意します。

f:id:otonasisanoto:20200913120630p:plain

 

先ほど作ったGameControllerに次の処理を追加します。

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

public class GameController : MonoBehaviour
{
    public float countTime; // カウントの時間
    public Text countText;  // 時間の表示
    public Text timeoverText;   // タイムオーバーの表示

    
    void Start()
    {
        timeoverText.gameObject.SetActive(false); // タイムオーバーの表示をオフに
    }

    void Update()
    {
        // 残り時間の計算
        countTime -= Time.deltaTime;

        // 残り時間を表示する
        countText.text = "残り" + countTime.ToString("f1") + "秒";

        // 残り時間が0になったら
        if(countTime < 0)
        {
            timeoverText.gameObject.SetActive(true); // タイムオーバーの表示をオンに
            Time.timeScale = 0; // ゲーム停止
        }
    }
}

UnityではTime.deltaTimeで1フレームの時間を取得できるので、制限時間として設けた数値から引くことでカウントダウンを実装しています。

 

実装するとこんな感じ。

 

土台が落ちるトラップの追加

プレイヤーがその土台に触れたら落下するトラップを作ります。

プレイヤーが土台に触れた瞬間、オブジェクトの色を変えて危険だということを知らせます。

その後に土台が落下するという流れの処理を実装します。

 

これは全部スクリプトでやってしまいます。

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

public class FallBlock : MonoBehaviour
{
    private bool isFall = false;    // トラップのフラグ
    public int count;   // ループさせる回数
    private Vector3 temPosition;

    void Update()
    {
        if(isFall)
        {
            // オブジェクトを落下させる処理
            temPosition = this.transform.position;
            temPosition.y = temPosition.y - 0.05f;
            this.transform.position = temPosition;
        }
    }

    void OnCollisionEnter(Collision collision)
    {
        // プレイヤーというタグのオブジェクトに衝突したら
        if(collision.gameObject.tag == "Player")
        {
            StartCoroutine("OnTrap");
        }
    }

    IEnumerator OnTrap()
    {
        // ループさせることでオブジェクトの色をチカチカさせる
        for(int i = 0; i < count ; i++){
            GetComponent<Renderer>().material.color = Color.red;    // 色を赤にする
            yield return new WaitForSeconds(0.5f);  //0.5秒待つ
            GetComponent<Renderer>().material.color = Color.gray;    // 色を灰色にする
            yield return new WaitForSeconds(0.5f);  //0.5秒待つ
        }

        GetComponent<Renderer>().material.color = Color.red;    // 最後は赤にする

        isFall = true; // 落下発動
    }
}

 

これを落下させたいオブジェクトにつけるだけです。

 

BGMの追加

やっぱゲームには音楽付けないとダメですよねー。

ということでBGMを追加します。

使う音源は自分がライブ配信用に作ったテキトーBGMがあるので、とりあえずそれを使います。

 

Unityの音源はAudio Sourceから発生して、それをAudio Listenerでキャッチすることで聞こえるというシステムです。

Audio Listenerはデフォルトでカメラについているので、今回はそのままAudio Sourceをカメラに追加してBGMを実装します。

個人的にはこれが一番簡単。

Audio Sourceを追加したら音源を設定、ループにチェックを入れてボリュームを調整したら完了です。

f:id:otonasisanoto:20200913140402p:plain

 

これで終わり。作業時間3分。いいね。

 

とりあえず今日はここまで。

プロトタイプとしてはだいぶ形になってきたし、ゲーム制作にも慣れてきました。

来週は続きをやるか、新しいゲームに入るかちょっと考えます。

 

本日は以上です。最後まで読んでいただきありがとうございました!

【ゲーム制作】Unityを利用した横スクロールゲーム開発 02 ゲームオーバー/クリアの実装と1stステージ土台作り

どうも音無サノトです。

毎週制作しているゲームのメモになります。

 

作業ログ

今日やることは以下の通り。

  • スポットライトの設置
  • ゲームオーバーの実装
  • ゴールの実装
  • ステージの土台を作成

スポットライトの設置

キャラクターの顔が暗かったのでスポットライトを追加して調整します。

f:id:otonasisanoto:20200906120611p:plain

 

やり方はHierarchyビューからpoint lightを追加してposition(場所)とinsensity(強度)を調整。

f:id:otonasisanoto:20200906121406p:plain

これでOK。 

 

今後、ステージを作成する際に今までのオブジェクトをいちいち作成するのは面倒なので、空のオブジェクトを作成し、キャラクター、ライト、カメラをまとめてプレハブ化しておきます。

f:id:otonasisanoto:20200906121911p:plain

 

ゲームオーバーの実装

プレイヤーがステージから落ちた場合、ゲームオーバーとなるようにします。

こちらも過去に作ったことがあるのでそれを参考にささっと実装します。

 

まずは空のオブジェクトにBox Colliderを追加してステージの下の方に設置し、大きさも変更します。

値は画像の赤枠通り。Is Triggerにチェックを入れておきます。

f:id:otonasisanoto:20200906123236p:plain

 

次にテキストの表示。

テキストを追加して表示範囲、表示テキスト、フォントサイズなどを調整して、画面の中央に「ゲームオーバー」と表示されるようにします。

f:id:otonasisanoto:20200906124108p:plain

 

ゲームオーバーの当たり判定時に実行されるスクリプトを作成してキャラクターにアタッチします。

※この時の注意点なのですが、プレハブ化しているので、元のプレハブの方にアタッチしておきます。そうしないと流用した際に、スクリプトが追加されてないものが使用されてしまいます。

 

コードは下記のようにしました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;  // UIを使う際は追加

public class PlayerSetting : MonoBehaviour
{
    public Text gameoverText; // ゲームオーバーと表示されるテキストをいれる

    void Start()
    {
        // ゲームスタート時はゲームオーバーを非表示
        gameoverText.gameObject.SetActive(false);
    }

    // 衝突判定
    void OnTriggerEnter(Collider other)
    {
        // GameoverLineというオブジェクトに衝突したら
        if(other.gameObject.name == "GameoverLine")
        {
            gameoverText.gameObject.SetActive(true); // テキストを表示
            Time.timeScale = 0; // ゲームを停止する
        }

    }
}

 

これで落下時にゲームオーバーと表示されるようになりました。

 

ゴールの実装

次にキャラクターがゴールにたどり着いた時の処理を制作します。

ゴールにはパーティクルを使用します。

パーティクルというのは粒子が舞ってキラキラする感じのやつです。

f:id:otonasisanoto:20200906140825p:plain

これのPosition、Scale、そして色を変更してBox Colliderを追加。

あとはゲームオーバーの時と同じようにテキストを用意して処理を追加します。

public class PlayerSetting : MonoBehaviour
{
    public Text gameoverText; 
    public Text goalText;   // ゴールを表示されるテキストをいれる

    void Start()
    {
        gameoverText.gameObject.SetActive(false);
        goalText.gameObject.SetActive(false); // スタート時はテキスト非表示
    }

    void OnTriggerEnter(Collider other)
    {
        if(other.gameObject.name == "GameoverLine")
        {
            gameoverText.gameObject.SetActive(true);
            Time.timeScale = 0;
        }

        // GaolPointというオブジェクトに衝突したら
        if(other.gameObject.name == "GoalPoint")
        {
            goalText.gameObject.SetActive(true); // テキストを表示
            Time.timeScale = 0; // ゲームを停止する
        }

    }
}

 

これでゴールの処理も実装しました!

 

今まで制作した、ゲームオーバーやゴールのオブジェクトなどはプレハブ化して、どのステージでも使えるようにしておきます。

 

ステージの土台を作成

ステージをいくつ作るかは未定ですが、最初のステージの土台を作成していきます。

なるべくカメラ切り替えの要素を使わないと進みづらいステージを設計したいですが、そこら辺はやりながら考えていきます。

ビジュアルから作れるのがUnityのいいところですね。

 

ということで色々と試行錯誤して、こんな感じのステージにしてみました。

f:id:otonasisanoto:20200906164831p:plain

 

シンプルだけど割と疲れました。。。

 

プレイ動画は下のような感じ。

 

動画を撮っているとプレイ時間を把握できるからいいですね。

今の動画で1分くらい。

1ステージで1分から5分くらいでサクサク進めるといいんじゃないか、という感覚です。

 

次回はこのステージに面白い仕掛けでも入れられたらなと思っています。

【ゲーム制作】Unityを利用した横スクロールゲーム開発 01 カメラの視点移動

どうも音無サノトです。 

ちょっと工夫した簡単な横スクロールゲームのプロトタイプを今回から開発してみようかなと思います。

 

今日の成果

  • コンセプトは「カメラ切り替えをして進むゲーム」
  • キャラとカメラの動作を実装

 

作業ログ 

まずイメージとしては「横スクロールのゲームなんだけど、3D視点を利用してカメラの位置を変更することで進むことができるゲーム」というコンセプトで進めて行こうと思います。

 

そこで、ゲームの核となるキャラクターの動きとカメラの視点移動から作成。

 

Unityで新規プロジェクトを作成して、使えそうなアセットをインポートします。

f:id:otonasisanoto:20200830134343p:plain

今回はこのアセットを使用。

余裕があればオリジナルのキャラクターを作成したいところですが、それは出来そうならで。。。

 

テストでキャラクターを動かした様子が以下の通りです。

 

もうすでに動作などは実装されているから、ただゲームシーンにキャラクターを置いただけ。

こんな簡単にできるのだから素晴らしいですな。

 

次にカメラの視点移動を実装していきます。

前回のボール転がしゲームのカメラ移動を流用。

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

public class CameraController : MonoBehaviour
{
    
    public GameObject player;
    private Vector3 offset;

    void Start()
    {
        // メインカメラとPlayerの相対距離を算出
        offset = transform.position - player.transform.position;
    }

    void Update()
    {
        transform.position = player.transform.position + offset;
    }
}

 

これでキャラクターの動きに合わせてカメラも移動します。

 

ただ、このままだとキャラクターがそのまま落ちています。

どこかで曲がらないといけないのですが壁が邪魔で見えない。

そのためカメラの視点を切り替える必要があるということです。

それを実装していきます。

 

スクリプトを以下のように変更。

Qキーが押された場合、カメラ視点が切り替わるようになっています。

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

public class CameraController : MonoBehaviour
{
    
    public GameObject player;
    private Vector3 offset;

    Animator anim;

    bool isCameraPotionDefault = true;

    void Start()
    {
        // メインカメラとPlayerの相対距離を算出
        offset = transform.position - player.transform.position;
    }

    void Update()
    {
        transform.position = player.transform.position + offset;

        // Qキーでカメラ視点の切り替え
        if (Input.GetKeyUp(KeyCode.Q)) {
            isCameraPotionDefault = !isCameraPotionDefault;

            if(isCameraPotionDefault){
                offset.x = offset.x + 2.5f;
                offset.z = offset.z + 2.5f;
                transform.eulerAngles = new Vector3(18.5f,-90f,0);
            } else{
                offset.x = offset.x - 2.5f;
                offset.z = offset.z - 2.5f;
                transform.eulerAngles = new Vector3(18.5f,0,0);
            }

        }
    }
}

 

最初はアニメーションでカメラ切り替えをしようと思ったのですが、カメラの位置が変動するため、思うように実装出来ませんでした。

このコードでも動作はできるのですが、自分のイメージではもっと滑らかに動いていく感じだったので改良が必要かもしれないです。

 

まあ、まずは動くものを作るのが大事。

次回からはステージ作りをやって行こうと思います。

【ゲーム制作】2020.06.28 進捗(シーンのリトライと遷移の実装)

どうも音無サノトです。

先週はゲーム制作ができなかったです。今週からまたちゃんとやっていきます。

まあ、この記事は自分用のメモみたいなものですから書かなくてもいいんだけど。。。

 

今日の成果

  • ゲームオーバー時にリトライできるようにした
  • ゲームクリア時に次のステージに行けるようにした
  • 2つ目のステージを作成(動く障害物) 

 

作業ログ

今日やることは以下の通り。

 

まずはボタンの設置。

Hierarchyの+ボタンからUI > Buttonを選択してボタンを追加。

f:id:otonasisanoto:20200628165539p:plain

 

ボタンの表示を変更してゲームーオーバーのテキストの下にボタンを追加します。

f:id:otonasisanoto:20200628170133p:plain

 

新しくスクリプトを作成してボタンに以下の処理を追加します。

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

public class RetryButton : MonoBehaviour
{
    public void OnClick()
    {
        SceneManager.LoadScene (PlayerController.currentStage); // ゲームリスタート
        Time.timeScale = 1;
    }
}

 

これでボタンを押すと現在のシーンがロードされるようになりました。

SceneManager.LoadScene()関数でシーンをロードしております。

引数にはロードするシーンの番号を与えています。

PlayerController.currentStage変数はPlayerControllerスクリプト内で宣言された、シーンをまたいでも保持される変数です。

Unityではpublic staticで変数を宣言しておけば他のスクリプトからもアクセスでき、ゲームが終了するまで保持されるのでこれで現在のシーンが何番目のシーンかを管理します。

 

f:id:otonasisanoto:20200628172306p:plain

こんな感じで宣言しています。

 

これでゲームオーバ時にボタンを押すとゲームをリスタートすることができます。

 

次にゲームクリア時に次のステージへ移動できるようにします。

ゲームオーバーと同じようにゲームクリアの下にボタンを追加して、スクリプトを追加します。

f:id:otonasisanoto:20200628171845p:plain

 

スクリプトでは現在のシーン番号にプラス1することで次のシーンに飛ぶようにしています。

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

public class NextButton : MonoBehaviour
{
    public void OnClick()
    {
PlayerController.currentStage += 1; // 次のシーンにする SceneManager.LoadScene (PlayerController.currentStage); Time.timeScale = 1; } }

 

新しいシーンを作成して、Build Settingsにドラッグ&ドロップしてシーンの連番をつけておきます。

f:id:otonasisanoto:20200628172011p:plain

 

これでゲームクリア時にボタンを押すと次のシーンへと飛びます。

 

それでは次のシーンの中身を作成していこうと思います。

まず、Playerやカメラなど次のシーンでも流用するオブジェクトをひとまとめにしてプレハブ化しておきます。

これでどのシーンでもすぐにオブジェクトを使えるようになります。

f:id:otonasisanoto:20200628173500p:plain

 

第2ステージはUnityのAnimation機能を使用して動く障害物を設置してみました。

 

本日は以上です。

 

【ゲーム制作】2020.06.14 進捗(初期ステージ作成)

どうも音無サノトです。

iPhone向けのゲームアプリ開発を行っております。

今日もちょっとずつ制作です。

 

今日の成果

  • アイテム取得数の表示
  • ゲームオーバー/ゲームクリアの実装
  • ステージ作成

 

作業ログ

 今日はボール転がしのゲームを拡張していこうと思います。

 

まずはアイテムの取得数を表示。

こちらの記事を参考に実装します。

www.otonasisanoto.com

 

こんな感じです。

 

次はボールがステージから落下した際、ゲームオーバーになるという処理を実装します。

 

空のゲームオブジェクトを追加しBox Colliderを追加します。

ステージの下の方に大きめのサイズで調整。

Is Triggerにチェックを入れて、このラインにボールが衝突した際にゲームオーバーになるようにします。

f:id:otonasisanoto:20200614142111p:plain

 

ゲームオーバーを表示するテキストも追加しておきます。

f:id:otonasisanoto:20200614143534p:plain

 

スクリプトの方ではゲームスタート時にはゲームオーバーのテキストを非表示にしておきます。

衝突判定時に表示してゲームシーンをストップさせます。

以下の処理をPlayerに追加。

    // オブジェクト衝突時の処理
    void OnTriggerEnter(Collider other)
    {
        // ポイント獲得時
        if (other.gameObject.CompareTag("Point"))
        {
            other.gameObject.SetActive(false);
            pointCount++;
            SetPointCountText();
        }

        // ゲームオーバー時
        if(other.gameObject.CompareTag("Gameover"))
        {
            gameoverText.gameObject.SetActive(true);
            Time.timeScale = 0; // ゲームの停止(Update関数内など止まらないところもある)
        }
    }

 

次にゲームクリア時の処理を実装します。

ゲームオーバーの時と同じようにテキストを追加しておきます。

ステージ上のポイントを全て取得したらゲームクリアとします。

 

Start関数内でポイントになるアイテム数がいくつあるかを取得しておきます。

void Start()
    {
        rb = GetComponent<Rigidbody>();
        
        pointCount = 0;
        SetPointCountText();

        gameoverText.gameObject.SetActive(false);

        gameclearText.gameObject.SetActive(false);

        pointMax = GameObject.Find("Points").transform.childCount; // アイテム数を取得
    }

 

アイテム取得時のポイント加算処理内に全てのアイテム取得していた場合、ゲームクリアとなる処理を追加します。

        // ポイント獲得時
        if (other.gameObject.CompareTag("Point"))
        {
            other.gameObject.SetActive(false);
            pointCount++;
            SetPointCountText();

            // ゲームクリア時
            if(pointCount >= pointMax)
            {
                gameclearText.gameObject.SetActive(true);
                Time.timeScale = 0; // ゲームの停止(Update関数内など止まらないところもある)
            }
        }

 

実行するとこんな感じ。

 

次に簡単なステージを制作してゲームぽくしていきます。

 

本日は以上です。最後まで読んでいただきありがとうございました!

【ゲーム制作】2020.06.07 進捗(ボール転がしゲームの土台作り)

どうも音無サノトです。

今日もゲーム制作の続きをやっていきます。

 

今日の成果

  •  Playerをボールに変更
  • カメラ追従処理の追加
  • アイテムを取得できるように変更

 

作業ログ

今日はボールを転がしてアイテムを取得できるようにしていきます。

 

まずはボールを転がす処理。

以前に開発したボール転がしゲームの処理を応用してジョイスティックに対応するようにスクリプトを変更します。

www.otonasisanoto.com

 

Playerの処理を以下のように変更。 

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

public class PlayreController : MonoBehaviour
{
    public FixedJoystick joystick;
    public float speed;
    private Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    // Update()はフレーム毎の処理
    // FixedUpadete()は一定時間毎の処理
    // 物理挙動を使用する場合はFixedUpadete()を使用
    void FixedUpdate()
    {
        // Playerを物理挙動を使用して動かす
        float moveHorizontal = joystick.Horizontal;
        float moveVertical = joystick.Vertical;

        Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);

        rb.AddForce(movement * speed);
    }
}

 

こんな感じで動きます。

 

次はカメラをPlayerに追従するように処理を追加します。

まずはメインカメラに以下の処理を追加。

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

public class CameraController : MonoBehaviour
{
    
    public GameObject player;
    private Vector3 offset;

    void Start()
    {
        // メインカメラとPlayerの相対距離を算出
        offset = transform.position - player.transform.position;
    }

    void Update()
    {
        transform.position = player.transform.position + offset;
    }
}

 

こんな感じにPlayerの動作に合わせてカメラも動きます。

 

続きましてアイテム取得の処理を追加します。

ここも以前、制作したゲームの処理を流用します。

www.otonasisanoto.com

 

以下の処理をPlayerに追加します。

    // オブジェクト衝突時の処理
    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Point"))
        {
            other.gameObject.SetActive(false);
        }
    }

 

後はPointというタグのプレハブを制作してシーンに追加。

※Is Triggerにチェックを入れることを忘れずに

ついでにボールが落ちないように壁も作っておきました。

 

実行結果はこちら。

 

 

今回はここまでを実機で動作確認して終わりです。

 

本日は以上です。最後まで読んでいただきありがとうございました! 

【ゲーム制作】2020.05.31 進捗(ジョイスティックの実装)

どうも音無サノトです。

毎週日曜日はUnityにてiOSビルド向けのゲーム制作を行っております。

今日はユーザがゲームを操作するためのジョイスティックの実装です。 

 

今日の成果

  • 実機にてジョイスティックを使った動作テストの確認 

 

 

作業ログ

今日はiPhone上で操作をできるようにジョイスティックの動作テストを行います。

 

ジョイスティックの追加

 

 動作テストのコード

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

public class PlayreController : MonoBehaviour
{
    public FixedJoystick joystick;
    public float speed;

    void Update()
    {
        Vector3 pos = this.gameObject.transform.position;
        float x = joystick.Horizontal * speed;
        float y = joystick.Vertical * speed;
        // 現在のpotionに値を加算してオグジェクトを移動
        this.gameObject.transform.position = new Vector3(pos.x + x, pos.y + y, pos.z);
    }
}

 

このコードはシーンに適当に作ったオブジェクトをジョイスティックで操作する処理を記述しています。

これを前回同様、iOS向けにビルドして実機テストを行いました。

※実行結果は今日の成果(上記)に記載

 

本日は以上となります。