この講座ではUnityでの基本的なUIの作成方法マスターしながら「恋愛・ホラー風ノベルゲーム」を開発していきます。今回は第4回目です。
前回はスプラッシュ画面からタイトルへのシーン遷移処理を通して、基本的なUnity C#コードの書き方を解説しました。
前回の記事:
今回はさらに多くのシーン移動処理を実装し、DoTweenを用いたアニメーション処理や画面遷移ユーティリティを作成し、Unity開発テクニックを習得していきます。
ノベルゲームにおけるシーンの遷移処理を追加する
では最初に前回の状態からシーンの遷移を作成します。
Title→Home
まずは既に配置されているボタンをクリックしたらシーンが変わる処理を書いていきましょう。編集するのはボタンの処理が書いてある「TitleView.cs」です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class TitleView : MonoBehaviour { void Start() { } void Update() { } public void OnScreenButtonClicked() { SceneManager.LoadScene( "01_Home" ); } } |
追加しているのはまずシーン遷移を使用するために上部「using」に「UnityEngine.SceneManagement」を追加します。
そして既に作成してある「OnScreenButtonClicked」の関数の中身に追記します。
元々ログが書いてあるかと思いますが消してしまって大丈夫です。そして「SceneManager.LoadScene( “01_Home” );」を追加します。
これがUnityに用意されているシーン移動の関数です。
では、Unityに戻って再生してタイトルでボタンを押してみましょう。
すると移動できないと思います。そのときコンソールウインドウにエラーが出ているかと思います。
Unityで開発を進めていると、このようなエラーが出て実行できない・・・なんて事態はどうしても起こります。こんなときはエラー文をそのままコピペして検索したりして自分で解決することもゲーム開発において重要な作業になってきます。
今回はビルドセッティングにシーンを追加してね、というエラーなのでそれをやっていきましょう。
BuildSetting
まずUnity上部のメニューから「File→BuildSetting」を押してウインドウを開きます。
開くと下記のようなウインドウが表示されると思います。
この上部「SceneInBuild」がシーンを追加する場所です。右下の「AddOpenScennes」を押すと今開いているシーンを追加でき、プロジェクトウインドウからシーンファイルをこの中にドラック&ドロップすることでも追加できます。
「00_TitleScene」「01_HomeScene」を追加してみましょう。追加すると下記のようになります。
追加順によっては右にある数字「0、1」が画像と違うかもしれません。この「0」のシーンが実機で再生したときに一番最初に開くシーンになりますので「00_Title」を「0」にしておきましょう。
名前をドラックすると順番を入れ替えることができます。
ついでにもう一つ設定しておきましょう。上記画像の左下にある「Platform」と言う項目です。
これは文字通りビルドするプラットフォームを差しています。今回はスマホで遊べるゲームを作るのでご自身で使用するOS「Android」もしくは「iOS」を選択しておきましょう。PC版で実行ファイルを作成したい場合は変更しなくても大丈夫です。
ではUnityに戻ってもう一度再生してタイトルのボタンを押してみましょう。Homeシーンに移動できたかと思います。
これが基本的なUnityのシーン移動の実装の流れになります。
DOTweenを使ってノベルゲームにアニメーションを導入しよう
この辺りで少し見た目を調整していきましょう。
今回はアセットストアから使用できるDoTweenというライブラリを使用していきます。とてもよく使われるライブラリなので使い方を知っておくと役に立ちます。無料で利用可能です。
DOTweenのインポート
まずはアセットストアをブラウザで開きます。Unity上部メニュー「Window/AssetStore」のウインドウ「SeachOnline」から開くこともできます。(サインインしておきましょう)
DOTweenと検索すると。「DOTweenPro」という有料アセットも出てきますが、無料の方で問題ありません。
あとは今までと同じように「Unityで開く」からUnityのPackageManagerを開きインポートします。
インポートすると下記のようなウインドウがでるので、特に気にせず「OpenDOTweenUtuilityPanel」「SetupDOTween」を押しておきましょう。
DOTweenでは色々なことができるので一言で説明できないですが、簡単に言うと「値を〇〇秒で〇〇の値にする」と言った値の変化を簡単に扱うことができます。
これによりゲームオブジェクトの移動や回転、色など見た目の変化を簡単に実現できます。そしてこうした処理はそのままアニメーションの実装にも使えます。
今回は2Dアプリなので主にUIを使用しているので、DoTweenを使ってUIの変化を実現する便利なスクリプトを作ってみましょう。
DOTWeenの基本的な使用方法をマスターしよう
では作成していきます。「Assets/AppMain/99_Common/Script」に「UITransition.cs」というC#スクリプトを新しく作成しましょう。
「Transition」とは「遷移」と言う意味でUIを遷移(変化)させるユーティリティなスクリプトを作成していきます。
ユーティリティとは小規模で補助的な機能を持つプログラムのことです。今回のノベルゲーム開発を楽にするために先に補助機能プログラムを組み上げます。
ひとまず動きを確認するために、下記のようにします。
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; public class UITransition : MonoBehaviour { // レクトトランスフォーム取得用. public RectTransform Rect { get { if( rect == null ) rect = GetComponent<RectTransform>(); return rect; } } // レクトトランスフォーム保管用. RectTransform rect = null; void Start() { TransitionOut(); } public void TransitionOut() { Rect.DOLocalMove( new Vector3( 1000f, 0, 0 ), 3f ); } } |
まずは一番上に「using DG.Tweening;」を追加しておきましょう。これが「DOTween」を使用するための命令です。
RectTransform Rectの定義内に人によってはあまり見慣れない記載が出てきます。get{~}の部分です。これは「DOTween」とは関係ありません。
よく使用される方法で「プロパティ」と呼ばれています。プロパティは「get」、「set」というアクセッサを持っており、これらは値の取得時と代入時にそれぞれのアクセッサで定義された内容の処理を自動的に実行します。今回は「get」のみを使用しています。
このプロパティを取得するときは「get」。代入するときは「set」が呼び出されます。
「set」を記載しないことで、「Rect」という変数には値を代入できず、取得のみできる変数として扱うことができます
詳しくはUnity C#プログラミング講座の「UnityC#のフィールド・プロパティ・アクセス修飾子の使い方 スコープの概念を理解する」で解説しています。
今回は「RectTrasnform」を関数で取得する代わりにプロパティを使用しています。
1 2 3 4 5 6 7 8 9 10 11 |
// レクトトランスフォーム取得用. public RectTransform Rect { get { if( rect == null ) rect = GetComponent<RectTransform>(); return rect; } } // レクトトランスフォーム保管用. RectTransform rect = null; |
「public」で他からアクセスできる値として「Rect」を定義して、「get」でこの値を取得するときに「rect」という変数を参照しています(return rect;の部分)。
そしてその「rect」が「null」で何もないときには「GetComponent<RectTransform>()」でこのコンポーネントが付与されているゲームオブジェクトから「RectTransform」を取得して「rect」に保管します。
もし次に「Rect」を取得するとすでに「null」でなくなっている「rect」がそのまま返ります。
これは変数の中身を取得するときに「null」なら必ず何かしらの値を代入してから取得する「Nullチェック」を行うための処理です。
関数を使ってもNullチェックを実装できますがこのように記載する場合の意図は、取得のみ公開(get)し代入(set)ができないようにアクセス制限した「Rect」という変数と、値を保管するための「rect」と分けて役割を制限し明確にするため。
また使用するときの記載を減らし意識せず変数「Rect.〇〇」という形で扱えるようにするためです。
(もちろんゲームオブジェクトに「RectTransform」がない場合は「null」になります)
この辺りは好みにもよるのですが、少し分かりにくい部分なのでいくつかパターンをご紹介します。
関数で書いた場合
1 2 3 4 5 6 7 8 |
// レクトトランスフォーム取得用. public RectTransform GetRect() { if( rect == null ) rect = GetComponent<RectTransform>(); return rect; } // レクトトランスフォーム保管用. RectTransform rect = null; |
こうなるので関数の方が短いしよくない?という人もいます。ただしこの場合は使用するときも「GetRect()」を毎回実行します。
また関数の場合は慣例的に取得の場合「Get〇〇」とした方がベターです。もっと短くすると
1 2 3 4 5 |
// レクトトランスフォーム取得を関数にした場合. public RectTransform GetRect() { return GetComponent<RectTransform>(); } |
保管用をなくしても動きます。でもこれは毎回「GetComponent()」を実行してしまうのでやめましょう。他にも例えば
1 2 3 4 5 6 7 |
// アクセスの制限がしたい場合はプロパティで. public RectTransform Rect{ get; private set; } = null; // 必ずRectを使用する前にInit()を実行する。関数にせずそのまま書いてもOK. void Init() { if( Rect == null ) Rect = GetComponent<RectTransform>(); } |
このパターンでは「Rect」を使用する前に取得しておく必要があります。そのために「Init()」などの取得するための関数、または単純に取得処理をどこかに記載しないといけません。
こういったとき「Start()」関数で値を取得する場合がありますが、そのときは「Start()」関数の実行前に別の関数が実行される可能性があるというところに注意しましょう。
そこを踏まえると「Rect」を使用する関数の最初で「Init()」(もしくは取得処理)を実行しておく形になります。
また変数「Rect」が「public」だと外から代入できてしまいます。アクセスの制限をする場合はやはりプロパティを使用して「{ get; private set; }」と記載します。
これにより「get」はそのまま、つまり「public」で取得できます。「set」は「private」なので同じクラスからのみ代入できるようになります。
このようにアクセスの制限のみを省略して記載することもできます。
これらのパターンを使用した場合には、「Rect」を使用する側では下記になります。(下記関数の処理内容に関しては後ほど解説します)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 関数の場合. public void TransitionOut() { GetRect().DOLocalMove( new Vector3( 1000f, 0, 0 ), 3f ); } // 実行の際にチェックする場合. public void TransitionOut() { Init(); // if( Rect == null ) Rect = GetComponent<RectTransfom>(); // 関数にしない場合. Rect.DOLocalMove( new Vector3( 1000f, 0, 0 ), 3f ); } |
色々な書き方があり必ずしもこれがいいというものではありませんが、今回は最初に書いたプロパティを使うnullチェックの形で統一しておきます。
では解説に戻ります。
「Start」関数は作成したものを実行しているだけなので飛ばして呼び出している関数について解説します。
1 2 3 4 |
public void TransitionOut() { Rect.DOLocalMove( new Vector3( 1000f, 0, 0 ), 3f ); } |
この「Rect.DOLocalMove( new Vector3( 1000f, 0, 0 ), 3f );」が「DOTween」を使用しています。
「Rect」は先に定義した「RectTransform」型のプロパティです。「.DOLocalMove( new Vector3( 1000f, 0, 0 ), 3f );」この部分で今回はRectに入っているUIコンポーネントのx座標を1000だけ正方向(つまり右方向)への移動を実現しています。
この1行だけでDoTween処理の呼び出し元ゲームオブジェクトを移動させることができます。他にも回転やフェードなどがあります。
一旦ここまで実装できたらUnityに戻ります。
「00_Title」シーンで「SplashView」に作成した「UITransition」をアタッチしましょう。
再生すると、「SplashView」が右に移動するのがわかると思います。このように簡単に移動処理が作成できました。
では次にちゃんと画面遷移として使えるようにしていきましょう。
画面遷移ユーティリティーの作成
先ほどは練習としてUIの移動処理を実装しましたが今回のノベルゲームではUIの遷移時に移動ではなくフェード(透明度の変化)を使用していきます。そのため移動処理を透明度処理に変更して汎用的に使用できるようにしていきましょう。
(移動部分は今回は消してしまって大丈夫ですが、残したい方は残して両方使えるようにしても構いません)
CanvasGroupのアタッチ
まずはスクリプトを追加するより先に、Hierarchyで現在UITransitionを使用している「SplashView」のInspectorの下の方「AddComponent」というボタンを押して「CanvasGroup」というコンポーネントを付与します。
「CanvasGroup」は、付与したゲームオブジェクト以下の子UIにまとめて値を設定できます。今回は一番上の「Alpha」つまり透明度を操作するために使用します。
フェードイン・フェードアウト処理を作成
続いてスクリプトを追加していきます。
一気に変更していくので、注意してまずはコピペしてください。といっても難しいことは多くないのでゆっくり確認しながら進めてみてください。
先ほど作成した移動処理を削除して「フェード処理に置き換え」て、さらに「TransitionIn」つまり「UIが画面内に入ってくる処理」も追加します。またフェードイン・アウト処理に用いる値を変更できるように設定用の値も作成します。
最後にUnityでエディタを再生して動きを確認しておきましょう。「TransitionIn()」は透明の状態から徐々に表示され、「TransitionOut()」では表示されている状態から徐々に透明になって消えるようになりました。
少し駆け足でDOTweenの解説をしてきました。他の機能はまた必要に応じて解説していきます。次回はUniTaskを使用してこれらの処理の待機ができるようにしていきます。
次回の記事 :
コメント