【初めてのゲーム制作】#4日目 シーン切り替えの実装

創作活動

みそ味です。初めてのゲーム制作4日目です。
最近あまり時間が取れなくて少しずつしか進められていませんがボチボチやっていきます。

3日目は下記の記事から。

本日もタイトル画面の作業です。

タイトル画面で実装したいことについて以下の3つを挙げていました。

  • 大きいピザが常時クルクル回るようにする
  • 左右キーでボタン3種を選択できるようにする
  • スペースキーを押すと選択しているボタンに対応するシーンor画面に移動する

上の2つは前回実装したので、今回は下の「スペースキーを押すと選択しているボタンに対応するシーンor画面に移動する」です。

今回も基本的にはれー@DKRevel様のサイトのUnity入門で学べるノウハウでなんとかなりそうですが、追加で調べた情報があれば備忘録として書き記していこうと思います。

画面のフェードアウトを開始するコード

シーンの移行前に画面がフェードアウトし、フェードアウトし終えたらシーンを移行するようにします。

これは先ほど紹介したUnity入門のサイトでやった通りにやればほぼ出来るので特に苦労はしませんでした。

/// <summary>
/// シーン移動
/// </summary>
private void SceneChange()
{
    //スペースかエンターを押したとき
    if(Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.Space))
    {
        Debug.Log(cursorIndex);
        if(!firstSpace)
        {
            firstSpace = true;
            if(cursorIndex == 0 || cursorIndex == 1)
            {
                fade.StartFadeOut();
            }
        }
    }
}

このコードを前回のカーソルを移動させたスクリプトに追加します。

cursorIndex=2の時は設定画面への移行ですが、この時はシーンを移行せずにUIの表示だけで処理したいと考えているので if(cursorIndex == 0 || cursorIndex == 1) としています。

追加した後の全文は以下になります。矢印を動かすコードは前回の記事のものから修正してスッキリさせています。

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

public class yajirushi_yajirushi : MonoBehaviour
{
    [Header("フェード")] public Fade_SpriteMask fade;
    [Header("カーソル位置")] public GameObject[] cursorPositions;

    private Transform tf;
    private int cursorIndex = 0;
    private bool isPushing = false;
    private bool firstSpace = false;
    private bool goNextScene = false;

    // Start is called before the first frame update
    private void Start()
    {
        tf = transform;
    }

    // Update is called once per frame
    private void Update()
    {
        HandleInput();
        SceneChange();

        if(!goNextScene && fade.IsFadeOutComplete())
        {
            SceneManager.LoadScene("scene" + (cursorIndex + 1));
            goNextScene = true;
        }
    }

    /// <summary>
    /// 矢印キー入力の判定
    /// </summary>
    private void HandleInput()
    {
        float horizontalKey = Input.GetAxisRaw("Horizontal");

        //「→」を押したとき
        if ( horizontalKey > 0 && !isPushing && Input.GetKeyDown(KeyCode.RightArrow))
        {
            isPushing = true;       //キーを押している
            MoveToNextCursorPosition();
        }

        //「←」を押したとき
        else if (horizontalKey < 0 && !isPushing && Input.GetKeyDown(KeyCode.LeftArrow) )
        {
            isPushing = true;       //キーを押している
            MoveToPreviousCursorPosition();
        }

        else if(Mathf.Approximately(horizontalKey,0f))
        {
            isPushing = false;      //キーを離した
        }
    }

    /// <summary>
    /// カーソルを右に進める
    /// </summary>
    private void MoveToNextCursorPosition()
    {
        cursorIndex = ( cursorIndex + 1) % cursorPositions.Length;
        tf.position = cursorPositions[cursorIndex].transform.position;
    }

    /// <summary>
    /// カーソルを左に進める
    /// </summary>
    private void MoveToPreviousCursorPosition()
    {
        cursorIndex = (cursorIndex - 1 + cursorPositions.Length) % cursorPositions.Length;
        tf.position = cursorPositions[cursorIndex].transform.position;
    }

    /// <summary>
    /// シーン移動
    /// </summary>
    private void SceneChange()
    {
        //スペースかエンターを押したとき
        if(Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log(cursorIndex);
            if(!firstSpace)
            {
                firstSpace = true;
                if(cursorIndex == 0 || cursorIndex == 1)
                {
                    fade.StartFadeOut();
                }
            }
        }
    }

}

画面のフェードイン・フェードアウトを行うコード

こちらも簡単ではありますが、サイトで学んだそのままでは面白みが無いのでフェードイン・アウトの仕様を少し変えてみます。

↑のようなフェードイン・アウトを実装しました。
なんかいい感じ!

真っ黒な画像を円形に切り抜き、その切り抜く円を大きくしたり小さくすることでシーンを切り替えています。

画像を切り抜く方法は主にUnityユーザーマニュアルを参考にしました。

どうやらスプライトマスクとやらを活用すれば出来そうです。

作成したコードは以下になります。

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

public class Fade_SpriteMask : MonoBehaviour
{
    [Header("最初からフェードインが完了しているかどうか")] public bool firstFadeInComp;
    [Header("フェードする時間")] public float fadeTime;

    private Transform tf;
    private int frameCount = 0;
    private float timer = 0.0f;
    private bool fadeIn = false;
    private bool fadeOut = false;
    private bool compFadeIn = false;
    private bool compFadeOut = false;

    // Start is called before the first frame update
    void Start()
    {
        tf = GetComponent<Transform>();
        if(firstFadeInComp)
        {
            FadeInComplete();
        }
        else
        {
            StartFadeIn();
        }
    }

    // Update is called once per frame
    void Update()
    {
        //シーン移行時の処理の重さでTime.deltaTimeが大きくなってしまうから2フレーム待つ
        if(frameCount > 2)
        {
            if(fadeIn)
            {
                FadeInUpdate();
            }
            else if(fadeOut)
            {
                FadeOutUpdate();
            }
        }
        ++frameCount;
    }

    ///<summary>
    ///フェードインを開始する
    /// </summary>
    public void StartFadeIn()
    {
        if(fadeIn || fadeOut) 
        {
            return;
        }
        fadeIn = true;
        compFadeIn = false;
        timer = 0.0f;
        tf.localScale = new Vector3(0.0f, 0.0f, 0.0f);
    }

    ///<summary>
    ///フェードインが完了したかどうか
    /// </summary>
    public bool IsFadeInComplete()
    {
        return compFadeIn;
    }

    ///<summary>
    ///フェードアウトを開始する
    /// </summary>
    public void StartFadeOut()
    {
        if(fadeIn || fadeOut)
        {
            return;
        }
        fadeOut = true;
        compFadeOut = false;
        timer = 0.0f;
        tf.localScale = new Vector3(2.1f, 2.1f, 2.1f);
    }

    ///<summary>
    ///フェードアウトを完了したかどうか
    /// </summary>
    public bool IsFadeOutComplete()
    {
        return compFadeOut;
    }

    ///<summary>
    ///フェードイン中
    /// </summary>
    private void FadeInUpdate()
    {
        if(timer < fadeTime)
        {
            tf.localScale = new Vector3(2.1f*timer/fadeTime, 2.1f * timer / fadeTime, 2.1f * timer / fadeTime);
        }
        else
        {
            FadeInComplete();

        }
        timer += Time.deltaTime;
    }

    ///<summary>
    ///フェードアウト中
    /// </summary>
    private void FadeOutUpdate()
    {
        if(timer < fadeTime)
        {
            tf.localScale = new Vector3(2.1f * (1-timer / fadeTime), 2.1f * (1 - timer / fadeTime), 2.1f * (1 - timer / fadeTime));
        }
        else
        {
            tf.localScale = new Vector3(0.0f, 0.0f, 0.0f);
            FadeOutComplete();
        }
        timer += Time.deltaTime;
    }

    ///<summary>
    ///フェードイン完了
    /// </summary>
    private void FadeInComplete()
    {
        tf.localScale = new Vector3(2.1f, 2.1f, 2.1f);
        timer = 0.0f;
        fadeIn = false;
        compFadeIn = true;
    }

    ///<summary>
    ///フェードアウト完了
    /// </summary>
    private void FadeOutComplete()
    {
        tf.localScale = new Vector3(0.0f, 0.0f, 0.0f);
        timer = 0.0f;
        fadeOut = false;
        compFadeOut = true;
    }
}

フェードアウトからフェードインまでもう少し時間を空けたいなとか、フェードの時以外は真っ黒な画像を非アクティブにしたいなとか、まだ追加したいことはありますが今回進めたことはここまでです。

次回はついにメインのタイピングゲーム部分を作っていきたいと思います。楽しみです。

次回の記事はこちら↓

コメント

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