この記事は「恋愛ホラーノベルゲーム」の作り方講座の第6回です。
前回はUITransitionのInとOut処理をUniTaskで非同期処理として実行できるように改造を行いました。さらにViewBase、SceneBaseを作成し、クラスの継承を活用し共通コンポーネントとして整理を行いました。
前回の記事:
ここまでの開発により今回から作成するUIアニメーション処理の実装準備が整いました。
いよいよ本格的なノベルゲームとしてのUIアニメーション・複数シーンの遷移処理をDoTweenとUnitaskを併用して完成させていきます。
シーン内のビュー遷移処理を作成
SceneBaseの処理を追加
前回作成した「SceneBase.cs」に、ビューの遷移のための処理を追加していきます。
ベースクラスに処理を追加する、ということは継承されているクラスをアタッチした全てのもので実行できる処理になります。
まずは「Start()」内に処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
・・・ using Cysharp.Threading.Tasks; public class SceneBase : MonoBehaviour { // 初期ビューインデックス. [SerializeField] protected int initialViewIndex = 0; // 初期ビュートランジションフラグ. [SerializeField] protected bool isInitialTransition = true; // Viewリスト. [SerializeField] protected List<ViewBase> viewList = new List<ViewBase>(); // 現在のビュー. protected ViewBase currentView = null; protected virtual void Start() { // 初期Indexがちゃんと設定されていたら。 if( initialViewIndex >= 0 ) { // ビューのリスト全てに. foreach( var view in viewList ) { // シーンを設定. view.Scene = this; // 初期インデックスのビューに対しての処理. if( viewList.IndexOf( view ) == initialViewIndex ) { // トランジションする場合. if( view.Transition != null && isInitialTransition == true ) { view.Transition.Canvas.alpha = 0; view.gameObject.SetActive( true ); view.OnViewOpened(); view.Transition.TransitionIn(); } // トランジションしない場合. else { view.OnViewOpened(); view.gameObject.SetActive( true ); } // 現在のビューを設定. currentView = view; } // 初期ビュー以外に対しての処理. else { view.gameObject.SetActive( false ); } } } } } |
一番上「UniTask」を使用するために「using Cysharp.Threading.Tasks;」を追加します。
中の処理には多めに説明コメントを書いてるので参考にしてください。
先に追加した変数の「initilalViewIndex」は最初にどのビューを表示するか、「isInitialTransition」はその際フェードイン・アウトのトランジションを行うかを表します。
それらを使用して「Start()」ではシーンが始まった最初の状態を設定しています。
「if( initilalViewIndex >= 0 )」で初期インデックスが0を含む正の値の時に「viewList」すべてにforeachで同じ処理を行います。「var view」の「var」は型推論と呼ばれ自動的に型を設定してくれます。
今回の場合はリストが「ViewBase」なので「var」と書いておけば自動で「ViewBase」になります。
foreachの括弧の中をみていきます。まずは「if」文の中身以外を抜き出します。
1 2 3 4 5 6 7 8 9 10 11 12 |
// シーンを設定. view.Scene = this; // 初期インデックスのビューに対しての処理. if( viewList.IndexOf( view ) == initialViewIndex ) { ・・・(この部分は一旦後で) } // 初期ビュー以外に対しての処理. else { view.gameObject.SetActive( false ); } |
「view.Scene = this」の処理で「ViewBase」クラスの変数「Scene」にこのオブジェクト自身を保管しています。
次の部分
この関数を使用します。「インデックス」というのは「0」からは始まるリスト内での番号です。
そしてこのインデックスと変数の「initilalViewIndex」が同じ場合、言い換えると「initilalViewIndex」で指定したインデックスの「View」の場合に「if」内の処理を行います。この処理は後で解説します。
それ以外は「else」の処理である「view.gameObject.SetActive( false );」でビューを非表示にします。
では次にif内の処理を抜き出します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// トランジションする場合. if( view.Transition != null && isInitialTransition == true ) { view.Transition.Canvas.alpha = 0; view.gameObject.SetActive( true ); view.OnViewOpened(); view.Transition.TransitionIn(); } // トランジションしない場合. else { view.OnViewOpened(); view.gameObject.SetActive( true ); } // 現在のビューを設定. currentView = view; |
ここは簡単に解説します。
トランジションするときは最初に「Canvas.alpha」を「0」つまり透明にしてから「SetActive( true )」で表示して「TransitionIn()」で徐々に表示させています。
その間に「ViewBase」の「OnViewOpened()」を実行します。
そしてトランジションしないときは単純に「OnViewOpened()」を実行し「SetActive( true )」で表示するだけです。
最後にcurrentViewに開いたビューを保管して終わりです。
続いて関数を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
・・・ public class SceneBase : MonoBehaviour { ・・・ // ------------------------------------------------ /// View移動処理 // ------------------------------------------------ public virtual async UniTask ChangeView( int index ) { // 現在のビューが設定されている場合Close処理を行う. if( currentView != null ) { currentView.OnViewClosed(); if( currentView.Transition != null ) await currentView.Transition.TransitionOutWait(); } // ビューリストから指定のインデックスビューを検索. foreach( var view in viewList ) { // 該当ビューに. if( viewList.IndexOf( view ) == index ) { // オープン処理を行う. view.gameObject.SetActive( true ); view.OnViewOpened(); if( view.Transition != null ) await view.Transition.TransitionInWait(); currentView = view; } else { view.gameObject.SetActive( false ); } } } } |
関数名部分は「public virtual async UniTask ChangeView( int index )」です。
「public 」にして、継承用の「virtual」、非同期用の「async」、そして返り値に「UniTask」にして、引数は「int(整数)」でインデックスを指定します。
この関数は「指定インデックスのビューに移動する」関数です。
最初の部分は「currentView」つまり現在のビューがあるときに、そのビューで「OnViewClosed();」を実行し「currentView.Transition.TransitionOutWait();」で徐々に消していきます。
この関数には「await」が付いているので、これが実行されると処理はここで遷移(徐々に消える)が終わるまで待機します。
次に先ほどと同じように「viewList」を「foreach」そして「if( viewList.IndexOf( view ) == index )」を使用して、指定インデックスとそうでない場合に分けて処理を行います。
処理は「Start()」のときとほど同じで、指定ビューではオープン処理を行いそうでないものを非表示にします。
SplashからTitle、TitleからHomeの処理を再度追加
ではここで最初にテスト用に追加しておいた、Splashから数秒でタイトルに、タイトルからボタンを押すとHomeに行く処理を改めて必要な部分に追加していきます。
まずは「SplashView.cs」です。
以前「TitleScene.cs」にコルーチンで待機して移動する処理を作成したかと思います。
前回消して綺麗にしてあるかと思いますので、ここはあえて「UniTask」を使用して「SplashView.cs」に同じ動き作成してみましょう。
using文の呼び出しやメソッドにasyncを付与するのを忘れずに。
次回に向けて
今回までの講座でUnityを用いてUIアニメーションをUniTaskを用いた非同期処理とdotweenの併用で好きなだけ遷移処理を作れるようになりました。
ビューを増やしたり、シーンを増やしたり、それぞれご自身で作成したいようにUIまわりの操作処理を拡張しやすくなったはずです。オリジナルゲームを作る際は作品に合わせて自由にこうしたUIアニメーション処理を拡張してみましょう。
次回からいよいよ背景・人物画像を入れて見た目をノベルゲームらしくしていきます。
次回の記事 :
コメント
SceneBaseの処理を追加した段階で
CS0103: The name ‘initialViewIndex’ does not exist in the current context
ってエラーが出てなんでだろうと思っていたら
5章での説明では
インデックスの設定が「initilaViewIndex」と「l」と「a」が逆記載でした
コメントありがとうございます。
確認しましたがたしかに誤植ありました。修正しておきました。
こちらご指摘ありがとうございました!