【第16回】Sliderを使ってカメラの拡大率をゲーム画面から操作する
- 2018.04.16
- Unityチュートリアル
- Unity, チュートリアル

前回のチュートリアルでは、ボールの動きに沿ってカメラが移動する処理を実装しました。
カメラが移動することでゲーム画面に描画される範囲が変わるため、より動きを感じられるようになります。
今回は、前回追加したカメラのズームイン・ズームアウト機能について、ゲーム画面から操作できるようにしてみます。
前回のチュートリアルはこちらから。
今回の目的
UIのSliderを使って、ゲーム画面からカメラのズームイン・ズームアウトを操作できるようにします。
プロジェクトの準備
前回のチュートリアルで作成したプロジェクトをそのまま使います。
このページに先にたどり着いた方は、チュートリアルの初回から追っていただけるといいかもしれません。
UIを追加する
現在のゲーム画面には、UIボタンとテキストが表示されています。

今回はここに新たなUIであるSlider(スライダー)を追加してみます。結構Unityでの操作が多くなるので、頑張って一緒にやっていきましょ。
親オブジェクトの作成
まずは『Canvas』オブジェクトを選択した状態で右クリックまたは二本指タップでコンテキストメニューを開きます。メニューから[Create Empty]を選択します。

作成された空のオブジェクトの名前を[ZoomParent]に変更します。今回追加するUIたちはこの子オブジェクトとして作成していきます。

『Slider』オブジェクトの作成
『ZoomParent』オブジェクトを選択した状態で、右クリックまたは二本指タップでコンテキストメニューを開き、[UI] -> [Slider]を選択します。

『Slider』オブジェクトを作成すると、いくつかのパーツが一緒に作成されます。

『Slider』オブジェクトのパーツは以下のようになっています。つまみの部分は『Handle』オブジェクトです。左側の青色になっている部分は『Fill』オブジェクト、右側のグレーの部分は『Background』オブジェクトです。
なお、『Fill』オブジェクトの色はデフォルトだと白色で、今回は分かりやすいように色を着けています。

『Slider』オブジェクトのカスタマイズ
ここからそれぞれのパーツをカスタマイズしていきます。
まずは『Slider』オブジェクトから。Scaleの値をそれぞれ[3]にします。WidthとHeightを直接いじらないのは、パーツの比率を維持したいためです。『Slider』オブジェクトは他のパーツの親オブジェクトなので、Scaleも子オブジェクトに適用され、バランスが崩れないんです。

同じく『Slider』オブジェクトのSliderコンポーネント。ここではMin Valueを[50]に、Max Valueを[150]に設定します。この値は前回のスクリプトの中で、拡大率の最小値と最大値として設定した値です。
Whole Numbersは、値に整数のみを選べるようにするかどうかのチェックボックスです。チェックを入れると、取りうる値が整数のみとなります。スクリプトの中では拡大率をflaotにしていましたが、実際そこまで細かい値は必要ないため、整数にしましょ。スクリプトもあとで改修します。
OnValueChanged()はボタンの時にやったように、値が変わった時にスクリプトのpublicなメソッドを呼ぶことができます。ここもスクリプト改修時に設定を忘れずに。
また、Valueは初期値にもなるので、[100]にしておきます。実はこのValueが曲者で、『Inspector』ウィンドウからValueの値を変えるたびにWarningがコンソールに出るんですよね。

Valueを変えるたびに、
SendMessage cannot be called during Awake, CheckConsistency, or OnValidate
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
というWarningが。

この問題は、Unityで報告された問題やバグを追跡できる『Unity Issue Tracker』でも取り上げられていて、まだ治っていないようです。このチュートリアルと同じように、Sliderを追加してValueをいじったら出る、とコメントしている人もいるので、結構起こってる問題みたい。
幸い、ゲーム画面からSliderを操作し、スクリプトで値を拾う時にはこのWarningが出ません。なので、『Inspector』ウィンドウからValueを変えなければ、ひとまずは問題なさそうかな。Warningならゲーム実行は可能ですからね。
『Background』オブジェクト、『FillArea』オブジェクトは何もせず置いといて、『Fill』オブジェクトを選択して、色を変更します。Imageコンポーネント内にあるColorを選択し、[80C0FFFF](水色)に設定します。

『Handle Slide Area』オブジェクト、『Handle』オブジェクトはそのままで大丈夫です。
拡大率表示用テキストを作成
次は拡大率を画面に表示するUIテキストを作成します。
『ZoomParent』オブジェクトを選択した後、右クリックまたは二本指タップでコンテキストメニューを開き、[UI] -> [Text]を選択します。

作成したオブジェクトを『ZoomText』にリネームし、Widthを[560]、Heightを[100]、Pos Yを[75]に設定。スライダーの少し上に来るようにします。

Textコンポーネントでは、Textフィールドに[Magnification : 100%]、Font Styleを[Bold]、Font Sizeを[48]、Alignmentを中央寄せで中段(両方真ん中を選べばOK)、Colorを[FFFFFFFF](白色)に設定します。
[Add Component] -> [UI] -> [Effects] -> [Outline]からOutlineコンポーネントを作成します。Effect DistanceのXを[2]、Yを[-2]に設定。

ZoomParentの配置
今の状態だと画面中央に表示されているので、これらのパーツを一気に画面左下に持っていきます。親オブジェクトを作っておくと、複数のパーツがあっても一気に移動できるので便利です。
最初にZoomParentのアンカー設定。アンカーを選択し、[shift]キーと[alt(option)]キーを押しながら左下(bottom – left)を選びます。

アンカー設定後は位置を決めます。Pos Xを[250]、Pos Yを[25]にするのがちょうど良さそう。画面の大きさに合わせて適宜調整してくださいな。

設定が終わるとこんな感じになります。画面左下に無事配置できました。

スクリプトの編集
次はスクリプトを編集します。今回の方針は以下の通り。
- Sliderを操作したことを検知するメソッドを作る
- 上記メソッドから拡大率を操作
- Sliderの値をテキストに表示
- 拡大率をfloat型からint型に
これらを盛り込んで編集したのが以下のもの。変更点を紹介・解説します。
まずはusingの追加と、メンバ変数の追加です。『Slider』オブジェクトを操作するためにUnityEngine.UIを追加します。
『Slider』オブジェクトと『ZoomText』オブジェクトへの参照も忘れずに。また、操作したいコンポーネントをキャッシュするための変数も用意しています。
拡大率のテキストでは、数字以外の部分を文字列で宣言しています。拡大率そのものはint型に変更しました。なお、float型からint型に変えるときはおしりのfを忘れずに外します。
続いてStart()の中では、操作したいコンポーネントへの参照をキャッシュしています。『Slider』オブジェクトを操作する時に毎回GetComponentをするのはちょっと重いので、キャッシュして気持ち軽くしています。
次はGetMagnifiedOffset()です。3つ目の、拡大された距離を算出する計算を修正しました。実は前回の状態だと、拡大率150%でボールから遠ざかり、50%でボールに近づく仕様になってました。これは直感的じゃないので修正しましょ。
基準の距離はoffsetDistanceで、ここから拡大率に応じて距離を変えたいのですが、拡大率が大きい時に距離が短くなるように計算します。具体的には、拡大率100%を超えたらカメラの位置をボールの近くに、100%以下ならボールから遠い位置に配置します。

例えば、magnifyが150なら、カメラが基準の距離(赤色の線)から50%分ボールに近づく(青色の線)ことになり、その分カメラに映るボールが大きくなります。逆にmagnifyが50ならカメラが遠ざかる(オレンジ色の線)ためにボールが小さく映ります。

これを式変形したものが、スクリプトの記述です。200fは式変形の過程で出てきた数字なのでご安心ください。
最後にOnChangedMagnifyValue()です。これは『Slider』オブジェクトのValueが変わった時に呼び出されるメソッドです。『Slider』オブジェクトの値を拡大率magnifyにセットし、『ZoomText』オブジェクトにmagnifyの値を表示するようにしています。
これでスクリプトの準備ができました。変更点を記載しましたが、スクリプトの全文は『GitHub Gist』にあります。
オブジェクトのセット
スクリプトを保存してUnityに戻ったら、忘れずにUnity側の設定をしておきます。
まずはオブジェクト参照のセットから。『Main Camera』オブジェクトのCameraControllerを開き、Slider Objectフィールドに『Slider』オブジェクトをセットし、Zoom Text Objectフィールドに『ZoomText』オブジェクトをセットします。
『Hierarchy』ウィンドウからドラッグ&ドロップするか、フィールドの右にある丸ボタンからオブジェクトを選択します。

続いて、『Slider』オブジェクトを選択し、SliderコンポーネントのOnValueChangedの設定を行います。イベントを通知するオブジェクトとして『Main Camera』オブジェクトをセットし、呼び出すメソッドとして[CameraController] -> [OnChangedMagnifyValue()] を選択します。

動作確認
んじゃ確認しましょ。(GIFは2倍速)

ちゃんと拡大率が上がったらボールに近づいていますね。現在の拡大率もテキストとして表示されています。
いやー今回はなかなかのボリュームでした。『Slider』オブジェクト関連で設定項目が多かったので、その分盛りだくさんですしたね。
ズームイン・ズームアウトが実装できたので、次は……ボールに加える力の最大値を決めるために、ボールの飛距離予想を画面に表示するようにしましょうか。
まとめ
今回は『Slider』オブジェクトを使って、カメラのズームイン・ズームアウトを実装しました。
宝箱を開けた時や、ステージのゴールにたどり着いた時など、カメラを近づけてキャラクターを大きく映す演出はよく使われるので、スクリプトから自在にカメラを操れるようになると便利です。
次回はボールの飛距離予想とガイドを表示してみます。カービィボウルでよく見るアレっぽいのです。
ゲーム開発の攻略チャートを作りました!
-
前の記事
【第15回】カメラでPlayerオブジェクトを追いかけるUnityチュートリアル 2018.04.15
-
次の記事
【第17回】斜方投射でボールの予想経路を示す・Material準備編 2018.04.17
コメントを書く