Start メソッドはコルーチンメソッドになっていますので、yield を利用した中断処理を実装することが出来ます。
この処理と DOTween の Sequence 機能を組み合わせて、
オープニングのアニメの途中でキャラを登場させる、という演出を実装します。
操作したいキャラモデルの情報はスクリプト内にはありませんので、新しく変数を用意して、キャラモデルの制御を行える状態にします。
Sequence 機能を利用して、キャラモデルのサイズを少し大きめに変更し、元に戻すという処理をしてみましょう。
びよーん、という緩い感じでキャラが登場するようになります。
GameManager.cs
<= クリックすると開きます
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
[Header("ゲーム終了判定値")]
public bool isGameUp;
[SerializeField]
private DefenseBase defenseBase;
[SerializeField]
private PlayerController playerController;
[SerializeField]
private EnemyGenerator enemyGenerator;
[SerializeField]
private Transform temporaryObjectContainerTran;
[SerializeField]
private GameObject fireworksPrefab; // 花火のプレファブの情報をインスペクターより事前にアサインし登録する
[SerializeField]
private Transform canvasTran; // 花火の生成する位置の情報をインスペクターより事前にアサインして登録する
////* ここから変数を追加する *////
[SerializeField]
private GameObject charaObj; // キャラモデルのゲームオブジェクトの情報をインスペクターより事前にアサインして登録する
////* ここまで *////
public UIManager uiManager;
public BulletSelectManager bulletSelectManager; // インスペクターより事前にアサインして登録する
public bool isSetUpEnd; // Start メソッド内の処理の準備終了判定用。Start メソッド内の処理がすべて終了したら準備完了となり true
IEnumerator Start()
{
// 準備開始
isSetUpEnd = false;
// ゲーム終了の判定を、「ゲームが終了していない」状態にする
SwitchGameUp(false);
// Main 用の BGM を再生
SoundManager.instance.PlayBGM(SoundDataSO.BgmType.Main);
// DefenseBase スクリプトに用意した、DefenseBase の設定を行うための SetUpDefenseBase メソッドを呼び出す。引数として GameManager の情報を渡す
defenseBase.SetUpDefenseBase(this);
// PlayerController スクリプトに用意した、PlayerController の設定を行うための SetUpPlayer メソッドを呼び出す。引数として GameManager の情報を渡す
playerController.SetUpPlayer(this);
// EnemyGeneratorの初期設定
enemyGenerator.SetUpEnemyGenerator(this);
// TransformHelper スクリプトの temporaryObjectContainerTran 変数に情報を渡す
TransformHelper.SetTemporaryObjectContainerTran(temporaryObjectContainerTran);
// GameClearSet ゲームオブジェクトを見えない状態にする
uiManager.HideGameClearSet();
// GameOverSet ゲームオブジェクトを見えない状態にする
uiManager.HideGameOverSet();
// BossAlertSet を隠す
uiManager.HideBossAlertSet();
////* ここから処理を追加する *////
// キャラの現在のサイズを保持し、一時、見えなくする
float scaleX = charaObj.transform.localScale.x;
charaObj.transform.localScale = Vector3.zero;
////* ここまで *////
// バレット選択用のボタンを生成。この処理が終了するまで、次の処理は動かない
yield return StartCoroutine(bulletSelectManager.GenerateBulletSelectDetail(this));
// ゲームスタート時の演出
yield return StartCoroutine(uiManager.PlayOpening());
////* ここから処理を追加する *////
// キャラ表示(スタート演出の途中でキャラをタイミングよく表示させる)
Sequence sequence = DOTween.Sequence();
// キャラを少し大きめに表示
sequence.Append(charaObj.transform.DOScale(Vector3.one * 1.3f, 0.5f).SetEase(Ease.Linear));
// 上の Append メソッド終了後、元の大きさに戻す
sequence.Append(charaObj.transform.DOScale(Vector3.one * scaleX, 0.05f).SetEase(Ease.Linear));
// スタート演出が終了するまで一時処理を中断して待機(この間にキャラは元の大きさに戻っている)
yield return new WaitForSeconds(1.0f);
// TODO 開始時の Voice など
yield return new WaitForSeconds(0.5f);
////* ここまで *////
// 使用できるバレットの確認と更新
bulletSelectManager.JugdeOpenBullets();
// 準備完了状態にする
isSetUpEnd = true;
}
/// <summary>
/// ゲーム終了状態の切り替え
/// </summary>
/// <param name="isSwitch"></param>
public void SwitchGameUp(bool isSwitch) {
// isGameUp の値を引数の値に切り替える
isGameUp = isSwitch;
// ゲーム終了の状態の場合
if (isGameUp) {
// 画面に残っているエネミーをすべて破壊する
enemyGenerator.ClearEnemiesList();
// 一時オブジェクトを破壊する(子オブジェクトである、ボスのエネミーのバレットやエフェクトなども一緒に破壊される)
enemyGenerator.DestroyTemporaryObjectContainer();
}
}
/// <summary>
/// ゲームクリアの準備
/// </summary>
public void PreparateGameClear() {
// ゲームクリアの表示を行う
uiManager.DisplayGameClearSet();
// 花火の演出
StartCoroutine(GenerateFireWorks());
}
/// <summary>
/// ゲームオーバーの準備
/// </summary>
public void PreparateGameOver() {
// ゲームオーバーの表示を行う
uiManager.DisplayGameOverSet();
}
/// <summary>
/// プレイヤーとエネミーとの位置から方向を判定
/// </summary>
/// <returns></returns>
public Vector3 GetPlayerDirection(Vector3 enemyPos) {
return (playerController.transform.position - enemyPos).normalized;
}
/// <summary>
/// ランダムな数の花火の生成
/// </summary>
private IEnumerator GenerateFireWorks() {
yield return new WaitForSeconds(1.5f);
// ランダムな値を取得し、その回数だけ処理を繰り返す
for (int i = 0; i < Random.Range(5, 8); i++) {
// 花火のゲームオブジェクトの生成
GameObject fireworks = Instantiate(fireworksPrefab, canvasTran, false);
// 花火の色を変更するために、花火のゲームオブジェクトにアタッチされているパーティクルシステムのメインの情報(Duration や StartColor の情報がある部分)を取得
ParticleSystem.MainModule main = fireworks.GetComponent<ParticleSystem>().main;
// パーティクルの色をランダムな2色に変更
main.startColor = GetNewTwoRandomColors();
// 花火の位置をランダムな値を加えて変更
fireworks.transform.localPosition = new Vector3(fireworks.transform.localPosition.x + Random.Range(-500, 500), fireworks.transform.localPosition.y + Random.Range(700, 1000));
// 指定した秒数後に花火のゲームオブジェクトを破壊
Destroy(fireworks, 3f);
// 次の生成まで一時処理を中断(こうすることで、1つの花火のゲームオブジェクトが生成されてから1秒後に次の花火の生成を行うことができる)
yield return new WaitForSeconds(1.0f);
}
}
/// <summary>
/// パーティクルの色をランダムで設定
/// </summary>
/// <returns></returns>
private ParticleSystem.MinMaxGradient GetNewTwoRandomColors() {
// パーティクルシステム用の色の設定を行うためのインスタンスを作成して、コンストラクタを利用して色を2色設定して初期化
return new ParticleSystem.MinMaxGradient(GetRandomColor(), GetRandomColor());
}
/// <summary>
/// ランダムな色を取得
/// </summary>
/// <returns></returns>
private Color GetRandomColor() {
// Color32 は byte 型で色の指定が可能なので、色の各成分用の値を Random.Range メソッドを利用して int 型で取得し、byte 型にキャストして指定
return new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255), (byte)Random.Range(0, 255), 255);
}
}
スクリプトを修正したらセーブします。
GameManager ゲームオブジェクトを選択して GameManager スクリプトを確認します。
インスペクターに新しく宣言した変数が表示されていますので、ヒエラルキーにある Little_Cat_Girl ゲームオブジェクトを
ドラッグアンドドロップしてアサインして登録します。
GameManager ゲームオブジェクト インスペクター画像
以上でスクリプトの修正と設定は完了です。