猫でもわかるUnity入門(第18回 Android用のビルド環境を作ろう)

えにあです。
今まではPC向けアプリとしてビルドしてきましたが、今回はAndroid向けにビルドできるようにしていきます。

NOTE:
自分のスマホをUSBでパソコンとつないで、実機で動作確認できるようにするだけです。 そのうち自分のアプリを作ってPlayストアからダウンロードできるようにする方法も記事にしたいですね。

Android向けにビルドするには、AndroidStudioのインストールと、Unity側の設定が必要です。 これから、順番に手順を記載していきます。 ちなみに、iPhone向けにビルドするにはMacが必要です。私はMaciPhoneも持っていないので、Androidをターゲットにしています。


目次

Android Stuidoのダウンロード

まずは以下のサイトからAndroid Studioをダウンロードしましょう。 インストーラだけで1GBほどのサイズがありますので、空き容量に注意してください。
developer.android.com

Download Android Stuidoをクリックします。 f:id:enia:20210305214623p:plain

利用規約に同意して「ダウンロードする」をクリックします。 f:id:enia:20210305215523p:plain

以上でダウンロードは完了です。

Android Studioのインストール

ダウンロードしたインストーラをクリックして、インストールを開始します。 「Next」を押します。
f:id:enia:20210304094748p:plain

デフォルトの設定のまま「Next」を押します。
f:id:enia:20210304095203p:plain

インストール先を指定して「Next」を押します。
私はデフォルトのパスのままにしました。
f:id:enia:20210304095427p:plain

「Install」をクリックします。
f:id:enia:20210304095637p:plain

インストールが完了するまで30秒ほど待ちましょう。
f:id:enia:20210304095846p:plain

インストールが完了したら「Next」を押します。
f:id:enia:20210304095824p:plain

「Finish」を押します。
f:id:enia:20210304100021p:plain

インストールはここまでで完了です。最後の手順で「Start Android Studio」にチェックが入っていれば、このままAndroid Studioが起動します。

Android Studioの初期設定

「Do not import settings」を選択してOKをクリックします。
f:id:enia:20210304100120p:plain

GoogleAndroid Stuidoを改善するために、どのように使っているか情報をGoogleに送信しても良いか?と聞かれているようです。「Don't send」を選択しても問題なく使えるので、こちらを選択しました。
f:id:enia:20210304100530p:plain

「Next」を選択します。
f:id:enia:20210304100746p:plain

「Standard」にチェックを入れてNextを押します。
f:id:enia:20210304100830p:plain

UIのテーマです。好きな方を選択してNextを押します。 私は夜電気を暗めにして作業するので、目が痛くならないようにダークモードを選びました。 f:id:enia:20210304101925p:plain

先ほどの画面でダークモードを選択したので、以降画面が暗くなっています。 「Finish」を押します。 f:id:enia:20210304102432p:plain

初期化が完了するまでしばらく待ちましょう。 f:id:enia:20210304103406p:plain

おっと、私の環境ではエラーが発生してしまいました。 とりあえずFinishしか押せないので押します。 f:id:enia:20210304122351p:plain

Intel® HAXM installation failed. To install Intel® HAXM follow the instructions found at: https://software.intel.com/android/articles/installation-instructions-for-intel-hardware-accelerated-execution-manager-windows
Installer log is located at C:\Users\xxxx\AppData\Local\Temp\haxm_log.txt
Installer log contents:
=== Logging started: 2021/03/04  10:40:11 ===
This computer does not support Intel Virtualization Technology (VT-x) or it is being exclusively used by Hyper-V. HAXM cannot be installed. 
Please ensure Hyper-V is disabled in Windows Features, or refer to the Intel HAXM documentation for more information.

Android Studioの初期化自体は完了しているようなので、いったんこのままにします。 ※特にこの後の手順で問題はおきませんでした。

Android Studioの初期設定は以上です。ここでAndroid Studioは閉じておきます。

Android向けビルド用モジュールの追加(Unity側作業)

ここからはUnityに戻ります。 トップメニューから「ファイル」->「ビルド設定」を選択します。
f:id:enia:20210304122959p:plain

ビルド設定画面が開きます。 プラットフォーム画面を見ると、現在は「PC, Mac & Linux Standalone」が選択されているのが分かります。 f:id:enia:20210304124052p:plain

Androidを選択して「Install with Unity Hub」をクリックします。 f:id:enia:20210304124336p:plain

Unity Hubが起動しますので、「Android Build Suppoert」、「Android SDK & NDK Tools」、「OpenJDK」の3つにチェックをいれて「次へ」を押します。
f:id:enia:20210322134607p:plain

Android SDK and NDKの利用規約の同意にチェックを入れ、実行を押します。 f:id:enia:20210304125300p:plain

インストールが終わると自動でUnityが再起動すると思います。再起動しなければ手動で再起動しましょう。 再度ビルド設定画面を開きます。 プラットフォームでAndroidを選択した時の画面が以下のように変わっていればOKです。 以上で、Android向けビルド用モジュールの追加は完了です。 ここまでは一度だけやれば良い作業で、以降の作業はプロジェクトごとに行う作業です。

Android向けビルド(Unity側作業)

「Switch Platform」を押します。 f:id:enia:20210304125758p:plain

1分弱かかるので待ちます。 f:id:enia:20210304122852p:plain

以下のようにプラットフォーム欄のチェックがAndroidに変ればOKです。 f:id:enia:20210304130046p:plain

次にプレイヤー設定を選択します。 f:id:enia:20210304130356p:plain

Player設定にはたくさんの項目がありますが、真ん中の方にパッケージ名という項目があります。 ここに、インターネットのURLと同様に、他の人と重複しない、世界で唯一の名前を設定する必要があるようです。 今回は自分のスマホで動作確認するのが目的ですので、ユニークであれば適当な名前で良いと思います。 設定したら閉じます。 f:id:enia:20210304131652p:plain

ビルド設定に戻って、「シーンを追加」ボタンを押してビルド対象のシーンを追加します。 「シーンを追加」では現在のシーンがビルド対象に追加されます。 今回は1シーンしかないのでこれで良いですが、複数シーンある場合はプロジェクトビューからドラッグアンドドロップする方法で追加するのが簡単だと思います。 f:id:enia:20210304132759p:plain

「ビルドして実行」を押します。 f:id:enia:20210304132958p:plain

名前を付けて保存のダイアログが出ます。 ここで付けた名前がapkファイル名になります。 保存先はプロジェクト内で、Assetsフォルダ以外であればどこでも大丈夫です。

私は、Buildsフォルダを作って「Roulette_Android」という名前を入力して実行しました。 (※前回のボール転がしではないプロジェクトで試していたので、名前がRoll a ballではないです) f:id:enia:20210304134008p:plain

おっと、No Android devices Connectdというエラーが出てしまいました。 f:id:enia:20210304135024p:plain

このエラーが出る原因は大きく2つです。

  1. Android端末とスマホをUSBで接続していない
  2. Androidが「USBデバッグオン」になっていない

今回は2が原因でした。 USBデバッグをオンにしてRetryを押します。 (USBデバッグをオンにする手順は割愛しますが、Googleで検索すればすぐに出てきます。)

今度は先に進みました。しばらく待ちます。 f:id:enia:20210304135303p:plain

javaの起動がブロックされたので許可します。 f:id:enia:20210304135414p:plain

スマホ側を見ていてください。 しばらく待ってビルドが完了すると、自動的にアプリが起動します。やりましたね!

Android向けのビルド方法は以上です。

残念ながら、前回まで作成していたボール転がしゲームはキーボード入力を前提としているので、スマホでそのまま遊ぶことはできませんが、少し変更すれば簡単にAndroidで動かせるようになりますよ。 今回はここまで!

ShareX試してみた

えにあです。今回はShareXというソフトを試してみます。

勉強過程をブログに残す際、よく画面キャプチャを取得します。 ウィンドウ全体をキャプチャしてしまうと大きすぎるので、「Win + Shift + s」で切り取りツールを起動し、指定範囲だけをキャプチャしています。

しかし、Windows標準の切り取りツールには課題があります。

課題

  1. キャプチャ後に自動でフォルダに保存されない
    とりあえずたくさんキャプチャ取っておいて、後でブログに載せるということができません。

  2. ボタンなどのターゲットに色付けできない
    画面にボタンがたくさんある場合など、この手順でどのボタンを押せば良いかわかりません。 もちろん、一度ファイルに保存してから編集すれば良いのですが、とても手間です。

  3. マウスカーソルが表示されない
    マウスカーソルもキャプチャに含めたいときがありますが、消えてしまいます。

これらの課題がShareXを使うことで改善されるか試していきます。

目次

ShareXのインストール

ダウンロードページにアクセスします。 getsharex.com

一番左のDownloadButtonを押します。こういう場合にボタンを赤枠などで囲みたいのですが、現状は手間なので諦めています。
f:id:enia:20210304082011p:plain

利用規約に同意して、「Nextボタン」を押します。 f:id:enia:20210304082133p:plain

インストール先のディレクトリを指定します。ここではデフォルトのままにしました。
f:id:enia:20210304082215p:plain

追加オプションの指定です。後で変更できそうな内容ばかりなので、いったんデフォルトのままにしました。
f:id:enia:20210304082323p:plain

Installボタンを押します。
f:id:enia:20210304082418p:plain

インストール時間は10秒程度でした。 f:id:enia:20210304082643p:plain

これでインストールは完了です。Finishを押して起動してみます。 f:id:enia:20210304082659p:plain

ShareXの最初の設定

いきなりですが、ShareXを起動したらエラーが出てしまいました。 OneDriveと競合しているようです。エラーの解消方法はブログの下の方に記載しておきます。 f:id:enia:20210304082947p:plain

一番最初に設定しておきたいのは、キャプチャー後のタスクです。
左のメニューからキャプチャー後のタスクをクリックします。
f:id:enia:20210304090542p:plain

デフォルトで、以下3つにチェックが入っていました。

  • 画像をクリップボードにコピー
  • 画像をファイルに保存
  • 画像をホストにアップロード

f:id:enia:20210304090623p:plain

気になるのは「画像をホストにアップロード」のチェックです。 デフォルトでImgurというサービスに画像がアップロードされてしまうようになっていました。 万が一、個人情報をキャプチャしてしまい、それがアップロードされたら怖いので、私はオフにしました。

ShareXを試してみよう

安心して使えるようになったので試してみます。

「Alt + PrtSc」でウィンドウをキャプチャしてみる

Alt + PrtScの効果はウィンドウズ標準と同じでフォーカスの当たっているウィンドウのスクリーンショットが取得されます。 試しにShareX自身のキャプチャを取ってみたところ、ShareXのトップ画面に取得したキャプチャが表示されました。 f:id:enia:20210304091458p:plain

「Ctrl + PrtSc」で指定範囲をキャプチャしてみる

「Ctrl + PrtSc」で、今までの「Win + Shift + s」と同じように指定した領域のスクリーンショットを取得できます。

Windows標準機能と異なり自由に領域を指定して切り取ることも、ウィンドウ内の領域をキレイに切り取ることもできます。マウスカーソルもしっかり入ってますね。
f:id:enia:20210304092047p:plain

取得したキャプチャは、OneDrive上に年月ごとのフォルダに分かれて保存されています。 とりあえずキャプチャを取っておくという要件にも使えそうです。 f:id:enia:20210304092218p:plain

キャプチャした画像を加工してみる

キャプチャを取ると、ShareXのトップ画面にキャプチャした画像が表示されます。 これを右クリックして「画像を編集」を押してみます。
f:id:enia:20210304092526p:plain

画像エディターが開きます。トップメニューの描画:「四角形」を選択します。 f:id:enia:20210304092806p:plain

試しに赤枠書いてみました。これで編集の要件にも耐えられそうです。 f:id:enia:20210304093159p:plain

四角形の枠線の色はここで変えられます。 f:id:enia:20210304092914p:plain

塗りつぶしの色はその隣で変えられます。 f:id:enia:20210304092947p:plain

ちなみに、枠線や塗りつぶしの色を透明にする場合は、カラーピッカーの右上にある透明のチェックを選択します。 f:id:enia:20210304093124p:plain

以上、ShareXを試してみました。 私のやりたいことは十分実現できそうな感じです。 便利な設定を見つけたら今後も追加していきます。
今回はここまで!

補足:OneDriveと競合してしまった場合

デスクトップの右下にある、雲のマークを右クリックします。
f:id:enia:20210304084117p:plain

表示されたポップアップメニューの「設定」をクリックします。
f:id:enia:20210304083948p:plain

「バックアップ」タブでスクリーンショットの欄のチェックを外します。
f:id:enia:20210304084101p:plain

ShareXを落として再起動し、エラーが表示されないことを確認しましょう。 ShareXは常駐アプリケーションなのでウィンドウの×ボタンを押しただけでは再起動にならないので注意しましょう。

補足:上の手順で解決しない場合

PCを買い換えた直後など、まだ一度もスクリーンショットを撮ったことのない場合は、 上記の手順で解決しないことがあります。

その場合、まず一度Print Screenボタンを押してみましょう。 すると、OneDriveにスクリーンショットを保存するか聞かれますので「必要ない」を選択します。 f:id:enia:20210322131916p:plain

ShareXを落として再起動し、エラーが表示されないことを確認しましょう。 ShareXは常駐アプリケーションなのでウィンドウの×ボタンを押しただけでは再起動にならないので注意しましょう。

この回避策は以下のgithubのissueで見つけました。 github.com

補足:ffmpegのインストール

試しに何か操作していたところ、以下のエラーが出ました。 「ffmpegがない」というエラーなので動画や音声録音の機能を起動してしまったのだと思います。 ダウンロード自体は問題なさそうなので「はい」を押しました。
f:id:enia:20210304091139p:plain

猫でもわかるUnity入門(第17回 VSCodeで快適コーディング)

f:id:enia:20210228230354p:plain

えにあです。猫でもわかるUnity入門第17回を進めていきます。

今まではWindows標準のメモ帳を使って開発してきましたが、メモ帳での開発はとても効率が悪いです。 そこで、今回は私がTypescriptの開発で愛用していたVSCodeを使えるようにしていきます。

VSCodeを導入すると、以下のようなことができます。 - 文字に色をつけてくれる - 自動で字下げを行ってくれる - 入力補完ができる - 構文エラーをコーディング中に検出できる

VSCodeをインストールしよう

VSCodeマイクロソフトが開発している軽量エディタです。 有志が開発したプラグインが充実していて拡張が容易です。 VSCodeは以下からダウンロードできます。 azure.microsoft.com

私はすでにインストール済みなので細かいインストール手順は割愛しますが、標準設定でインストールすれば問題ないでしょう。

VSCodeにUnity用の拡張機能を追加しよう

VSCodeに「C#」と「Debugger for Unity」の二つの拡張機能をインストールしていきます。

C#拡張機能のインストール

左側のメニューバーで拡張機能を選択します。 検索ボックスに「C#」と入力して、一番上に出てくるC#拡張機能を選択します。
f:id:enia:20210303133546p:plain

表示される画面でインストールを押します。これでインストール完了です。
f:id:enia:20210303133146p:plain

C# XML Documentation Commentsのインストール(任意)

同様の手順で今度は検索ボックスに「C# XML Documentation Comments」と入力して、二番目に表示されたC# XML Documentation Commentsを選択します。
この拡張機能を入れることで、「///」とコメントを打った時にドキュメントコメントの枠を生成してくれます。

f:id:enia:20210314085129p:plain

Debugger for Unity拡張機能のインストール

同様の手順で今度は検索ボックスに「Unity」と入力して、一番上に表示されたDebugger for Unityを選択します。
f:id:enia:20210303133441p:plain

表示される画面でインストールを押します。これでインストール完了です。 f:id:enia:20210303133631p:plain

検索ボックスを空にしてみてください。
インストール済みの一覧が表示されるので、その中に「C#」と「Debugger for Unity」の二つが含まれていればOKです。
f:id:enia:20210303133932p:plain

UnityとVSCodeの連携を設定する

Unity側でスクリプトの編集に使うエディタをVSCodeに変更します。 トップメニューから「編集」->「環境設定」を選択します。
f:id:enia:20210303134628p:plain

環境設定のウィンドウが開きますので、「外部ツール」->「外部のスクリプトエディタ」->「Visual Studio Code」を選択します。 f:id:enia:20210303134824p:plain

これで、UnityEditorからスクリプトを編集する際にVSCodeが起動するようになりました。 試しに、前回作成したPlayerControllerをダブルクリックしてみます。
f:id:enia:20210303152804p:plain

おぉ、VSCodeが起動してPlayerControllerが開かれました。 f:id:enia:20210303152830p:plain

しかし、私の場合、VSCodeにエラーが表示されてしまいました。 次の手順でエラーを解消していきます。

VSCodeのエラーを解消しよう

私の環境では、3つのエラーメッセージが出力されました。 以下に、3つのエラーメッセージと、解消手順を記載しています。 すべて完了したら、上述の手順で再度VSCodeを起動し、エラーが消えたことを確認しましょう。

.NET core SDKのインストール

1つ目のエラーはこちらです。.NET Core SDKがインストールされていない、というメッセージです。

The .NET Core SDK cannot be located. .NET Core debugging will not be enabled. Make sure the .NET Core SDK is installed and is on the pah.
f:id:enia:20210303135058p:plain

エラーメッセージに従って、以下のサイトにアクセスします。 dotnet.microsoft.com

Install for Windowsを選択します。自動的にダウンロードが始まります。 f:id:enia:20210303135337p:plain

ダウンロードされたインストーラを実行します。 f:id:enia:20210303140508p:plain

インストールには少々時間がかかります。 f:id:enia:20210303140544p:plain

インストールが完了したら閉じたのち、パソコンを再起動しましょう。
f:id:enia:20210303140613p:plain

 .NET Framework Developer Packsのインストール

2つ目のエラーはこちらです。

Some projects have trouble loading. Please review the output for more details. f:id:enia:20210303141621p:plain

「Show Output」を押してエラーメッセージを見てみます。 version4.7.1の.NET Framework Developer Packsがインストールされていない、というメッセージです。

.vscode\extensions\ms-dotnettools.csharp-1.23.9.omnisharp\1.37.6.msbuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(1180,5): Error: The reference assemblies for .NETFramework,Version=v4.7.1 were not found. To resolve this, install the Developer Pack (SDK/Targeting Pack) for this framework version or retarget your application. You can download .NET Framework Developer Packs at https://aka.ms/msbuild/developerpacks

エラーメッセージに従って、以下のURLから.NET Framework Developer Packsをダウンロードします。 aka.ms

.NET Framework 4.7.1」をクリックします。 f:id:enia:20210303150457p:plain

NOTE:
2021年3月時点では、4.7.1以降のバージョンは4.7.1、4.7.2、4.8の3つがありました。メジャーバージョンが同じであれば互換性があるのかと思い、4.8だけ入れてみたところエラーは解消しませんでした。4.7.1でないとダメなのか、4.7.2でも良いのかは試してないのでわかっておりません。

RuntimeとDeveloper Packsの二つがありますが、警告に従ってDeveloper Packesをダウンロードします。
f:id:enia:20210303150518p:plain

ダウンロードが完了したらインストーラを起動して、条項に同意したうえでインストールします。
f:id:enia:20210303150542p:plain

1分程度でインストールが完了します。 f:id:enia:20210303150609p:plain

インストールが完了したら閉じたのち、パソコンを再起動しましょう。
f:id:enia:20210303150620p:plain

Gitのインストール

3つめのエラーはこちらです。Gitがインストールされていないというエラーです。 f:id:enia:20210323120015p:plain

規約を読んでNextを押します。 f:id:enia:20210325081509p:plain

インストール先フォルダを指定してNextを押します。
私はデフォルトのパスのままとしました。
f:id:enia:20210325081540p:plain

インストールするコンポーネントを設定して、Nextを押します。
私はデフォルトの設定のままとしました。
f:id:enia:20210325081832p:plain

スタートメニューフォルダの名前を設定して、Nextを押します。
私はデフォルトの設定のままとしました。 f:id:enia:20210325081805p:plain

Gitがデフォルトで使うエディタを設定して、Nextを押します。 何でもよいですが、私はNotepad(Windowsのメモ帳)にしました。
f:id:enia:20210325082325p:plain

デフォルトのブランチ名を設定して、Nextを押します。 デフォルト設定ではGit推奨の名前にしてくれるので、そのままの設定が良いでしょう。
f:id:enia:20210325082454p:plain

環境変数関連の設定のようです。ここはRecommendedのままでよいでしょう。 Nextを押します。
f:id:enia:20210325082644p:plain

デフォルトでOpenSSLにチェックが入っているのでそのままNextを押します。 f:id:enia:20210325082827p:plain

改行コードの設定です。
デフォルトでpush時はLF、チェックアウト時はCR+LFです。
デフォルトの設定のままNextを押します。
f:id:enia:20210325083001p:plain

git bushが使うコンソールを指定して、NEXTを押します。 私はデフォルトの設定のままとしました。 f:id:enia:20210325083319p:plain

pull時のふるまいを指定します。デフォルト設定のままNextを押します。 f:id:enia:20210325083414p:plain

Credential Helperを選択するようですが、パスワードや鍵の管理に使うものでしょうか。
デフォルト設定のままNextを押します。二つ目に至ってはDeprecatedですしね。
f:id:enia:20210325083532p:plain

追加オプションを指定して、Nextを押します。 デフォルト設定のままとしました。
f:id:enia:20210325083729p:plain

実験的機能のオンオフを設定します。 私はデフォルト設定(オフ)にしました。
ここまで長かったですね。ようやく現れたInstallボタンを押します。 f:id:enia:20210325083827p:plain

しばらく待ちましょう。 f:id:enia:20210325083935p:plain

インストール完了です! f:id:enia:20210325084036p:plain

VSCodeの設定を変えて、より便利にしよう

これで、Riと入れただけでRigidbodyが候補に出てきます。 f:id:enia:20210303154358p:plain

既に便利ではありますが、以下のようにif文の括弧の位置がバラバラだったり、if文の中がインデントされていなかった場合に、自動で整形してくれればより便利ですね。 なんと、ファイルを保存した時に自動整形することができるのです。そう、VSCodeならね。

        if (other.gameObject.CompareTag("Pick Up"))
        {
            other.gameObject.SetActive(false);
            count = count + 1;
            countText.text = "Count: " + count.ToString();
            if (count >= 12) {
            winText.text = "Your Win!";
            }
        }

早速設定していきましょう。 メニューバーから「ファイル」->「ユーザ設定」->「設定」と選択します。 f:id:enia:20210303152118p:plain

表示された設定画面で、上の検索ボックスに「format」と入力します。 表示された「Format On Paste」と「Format On Save」にチェックを入れます。 f:id:enia:20210303152216p:plain

この状態で、先ほどのフォーマットが崩れたファイルを保存してみると、以下のようにキレイに整形されました!

        if (other.gameObject.CompareTag("Pick Up"))
        {
            other.gameObject.SetActive(false);
            count = count + 1;
            countText.text = "Count: " + count.ToString();
            if (count >= 12)
            {
                winText.text = "Your Win!";
            }
        }

他にも設定しておいた方が良い項目があるかもしれませんが、おいおい追加していきます。

これでUnityの開発がさらに捗りますね! 今回はここまで!

猫でもわかるUnity入門(第16回 玉転がし作成 最終回)

f:id:enia:20210228230354p:plain

えにあです。 猫でもわかるUnity入門の第16回を進めていきます。
前回までで玉転がしゲームへの機能追加は完了しました。 今回は玉転がしゲームをビルドしていきます。

ゲームをビルドしよう

ビルドの前にシーンを保存しておきましょう。 「Ctrl + s」またはトップメニューから「ファイル」->「保存」で保存できます。

トップメニューから「ファイル」->「ビルド設定」を選択しましょう。
f:id:enia:20210303084421p:plain

ビルド設定ウィンドウが開きます。 f:id:enia:20210303085241p:plain

左下のプラットフォームは、どの環境向けにビルドするかを表しています。 現在のビルドターゲットは「PC, Mac & Linux Standalone」に設定されています。 今回はWindowsのexeファイルとしてビルドするのでこのままの設定できます。

次に、上部のビルドに含まれるシーンに、ビルド対象を追加していきます。 の右下にある「シーンを追加」ボタンを押すと、現在編集中のシーンがビルド対象に設定されます。 f:id:enia:20210303085601p:plain

NOTE: 今回のゲームは一つしかシーンがありません。ですがもっと本格的なゲームを作る場合、メニュー画面、戦闘画面、フィールド画面などごとにシーンを分けることができるのだと思われます。 複数のシーンがある場合は、対象のシーンを複数登録していきます。

では、ビルド設定ウィンドウの右下にある「ビルド」ボタンを押しましょう。 どこに保存するかを聞かれますね。

ここでは、プロジェクト内に「Builds」フォルダを新たに作成して、そこに保存することにします。 f:id:enia:20210303090215p:plain

10秒程度待つと、ビルドが完了しBuildsディレクトリの中身が表示されました。 f:id:enia:20210303090152p:plain

さぁ、「Roll abll.exe」を実行してみましょう! アプリが起動してゲームがを遊べるようになりました!

NOTE:
私の環境では実行すると全画面表示されてしまい閉じることができませんでした。 閉じれない場合はAlt +F4などで強制終了してください。

NOTE:
私の環境では、Unityエディタ上で起動した時と異なり、ゲームクリアメッセージがボールに隠れてしまいました。テキストの位置を少し上に移動しておいた方がよさそうです。 f:id:enia:20210303090601p:plain

メニュー画面がなかったり、クリア後に再プレイできなかったり、本格的なゲームを作るにはまだまだ課題がありそうです。 しかし、一からゲームを作ることの基本はかなり学べたのではないでしょうか。

玉転がし作成に関しては以上となります。 次はまた別のチュートリアルでさらに理解を深めていきたいと思います。

今回はここまで!

猫でもわかるUnity入門(第15回 玉転がし作成 その7)

f:id:enia:20210228230354p:plain

えにあです。猫でもわかるUnity入門第15回を進めていきます。

前回はプレイヤーオブジェクトがアイテムを収集できるよにしました。 今回は収集したアイテムの数を画面に表示できるようにしていきましょう。

目次

テキストオブジェクトを追加しよう

文字を画面に表示するためには、テキストオブジェクトを使います。 テキストオブジェクトの追加はトップメニューから「ゲームオブジェクト」->「UI」->「テキスト」で行います。
f:id:enia:20210302145439p:plain

ヒエラルキービューを見てください。 Textを追加したつもりが、CanvasやEventSystemなども一緒に追加されています。
f:id:enia:20210302145641p:plain

テキストを表示するために必要なものが自動的に追加されるようです。 重要なことは、UIを動作させるためには、Canvasの子にする必要があるということです。 ここではまず、それだけ覚えておきましょう。

収集したアイテムの数を表示するテキストですので、Textオブジェクトの名前を「Count Text」に変更しておきます。
f:id:enia:20210302184228p:plain

フォントの色を白に変更しておきましょう。インスペクターで色の横にある四角をクリックします。
f:id:enia:20210302184411p:plain

RGBを(255, 255, 255)に設定します。
f:id:enia:20210302184841p:plain

一度ここでプレイモードにして動かしてみましょう。 画面の中央にテキストが表示されていますね。
f:id:enia:20210302185151p:plain

しかし、テキストは常に画面の中央に位置しています。 これでは邪魔なので画面の左上に配置させましょう。

インスペクターで「Rect Transform」->「左側の四角」を選択すると、アンカープリセットがのポップアップが表示されます。
f:id:enia:20210302185338p:plain

現在は真ん中に設置されてることが分かりますが、何を基準にした真ん中なのでしょう。 これはCanvasに対して真ん中になります。 Canvasは画面全体にオーバーレイされているので、画面の中心に配置されるわけです。

画面の左上にテキストを表示するために「left-top」に変更します。 「left-top」を選択する際、「Shift + Alt」を押しながら選択してください。 ポップアップに説明が記載されていますが、Shiftを押すことでピボットを、Altを押すことで位置を設定してくれます。
f:id:enia:20210302193128p:plain

さあ、もう一度実行してみましょう。画面の左上に表示されますね。
f:id:enia:20210302193515p:plain

しかし、ピッタリ左上にくっついてしまっているので、少し余白を作りましょう。 インスペクターで位置(X, Y)をそれぞれ(10, -10)に変更します。 Canvasが画面全体に対してオーバーレイされていて、左上が(0, 0)になっており、右に行くほどX軸がプラスに、下に行くほどY軸がマイナスになるようです。
f:id:enia:20210302200508p:plain

さあ、もう一度実行してみましょう。いい感じに表示されましたね!
f:id:enia:20210302200915p:plain

カウントを更新しよう

PlayerControllerスクリプトを修正して、アイテムを取得する度にカウントCount Textを更新していくようにしましょう。

PlayerControllerスクリプトを以下のように変更します。 修正している箇所には★マークをつけています。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // ★追加

public class PlayerController : MonoBehaviour
{
    public float speed;
    public Text countText;  // ★追加
    private int count;  // ★追加
    private Rigidbody rb;

    void Start ()
    {
        rb = GetComponent<Rigidbody>();
        count = 0;  // ★追加
        countText.text = "Count: 0"; // ★追加
    }

    void FixedUpdate ()
    {
    float moveHorizontal = Input.GetAxis("Horizontal");
    float moveVertical= Input.GetAxis("Vertical");

        Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
        rb.AddForce(movement * speed);
    }

    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Pick Up")) {
            other.gameObject.SetActive(false);
            count = count + 1;  // ★追加
            countText.text = "Count: " + count.ToString(); // ★追加
        }
    }
}

まず最初の修正箇所はこちらです。

using UnityEngine.UI; // ★追加

テキストなどのUIオブジェクトを使う場合、Unity標準のUIパッケージのインポートが必要です。

次はフィールドの追加です。 countTextは画面左上に表示するテキストを保持する変数です。 countはプレイヤーが取得したアイテムの数を保持する変数です。

    public Text countText;  // ★追加
    private int count;  // ★追加

次に、上記フィールドの初期化です。初期化に最適な場所はstartメソッドです。 countの初期値は当然0です。 countTextは、"Count: 0"という文字列で表示します。

        count = 0;  // ★追加
        countText.text = "Count: 0"; // ★追加

最後に、テキストを更新する処理を記載していきます。 プレイヤーがアイテムに触れて、アイテムを非アクティブにするのと同じタイミングでテキストを更新すればよさそうです。 countは現在の値に+1すればよいですね。 countTextは更新後のcountの値を使って作成します。

        if (other.gameObject.CompareTag("Pick Up")) {
            other.gameObject.SetActive(false);
            count = count + 1;  // ★追加
            countText.text = "Count: " + count.ToString(); // ★追加
        }

それでは、Unityに戻ってPlayerObjectをインスペクターで見てみましょう。 PlayerControllerの欄を見てください。Count Textというプロパティが追加されていますね。 これはcountTextフィールドをPublicで宣言したからです。 以前speedフィールドを作成した時と同じですね。
f:id:enia:20210303073902p:plain

speedと異なるのは、speedはint型のためインスペクターで直接値を設定することができます。 一方でcountTextに設定するのは「Count Textオブジェクトへの参照」です。 現状はCountTextが「なし」と表示されていますので、正しく参照を設定してあげましょう。

参照を設定するには、ヒエラルキービューで「Count Textオブジェクト」をドラッグし、Playerオブジェクトの「Count Textプロパティ」にドロップするだけです。

以下のように表示されればOKです。
f:id:enia:20210303073957p:plain

さあ、実際に動かして試してみましょう。 アイテムを取得するたびに、左上のカウントが更新されていきますね!
f:id:enia:20210303074211p:plain

NOTE:
参照を設定しなかったらどうなるでしょう?プレイモードにして動かしてみると、コンソールに以下のエラーがでました。

NullReferenceException: Object reference not set to an instance of an object PlayerController.Start () (at Assets/scripts/PlayerController.cs:19)

Unityのステータスバー(Unityの左下)にも赤字でエラーが表示されているのでうまく動かない場合は確認するようにしましょう。

全部アイテムを取得したらゲームクリアメッセージを出そう

最後に、アイテムを12個すべて取得したらゲームクリアメッセージを出すようにしてみましょう。 まずはTextオブジェクトをもう一つ追加します。名前は「Win Text」にしましょう。
f:id:enia:20210303074801p:plain

クリアで、ゲームの真ん中に表示された方が良いですね。 アンカープリセットはデフォルトで「middle-center」になっているはずです。 この状態で位置を(0, 0, 0)にすれば画面中央に文字が表示されます。
f:id:enia:20210303074848p:plain

あれ?ゲーム画面で見てみるとボールより左に寄ってますね。
f:id:enia:20210303075046p:plain

インスペクターの下の方に整列プロパティがあります。左揃えになっているので中央揃えに変更します。
f:id:enia:20210303075132p:plain

いい感じに中央に来ました。
f:id:enia:20210303075228p:plain

ではPlayerControllerスクリプトの方を修正していきます。 CountTextと同様にPublicなWinTextフィールドを追加しましょう。

    public Text winText;

次に、startメソッドでこのwinTextを初期化します。 クリアした時だけ表示される文字列なので、初期値は空文字にします。

    void Start ()
    {
        rb = GetComponent<Rigidbody>();
        count = 0;
        countText.text = "Count: 0";
        winText.text = ""; // ★追加
    }

最後に、OnTriggerEnterメソッドを修正してアイテムを集め終わったタイミングでwinTextを"You Win!"という文字列に更新します。 アイテム数は12個ですので、countが12以上になったらwinTextを更新すればよいですね。

    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Pick Up")) {
            other.gameObject.SetActive(false);
            count = count + 1;
            countText.text = "Count: " + count.ToString();
            if (count >= 12) { //★追加
                winText.text = "Your Win!";  //★追加
            } //★追加
        }
    }

Unityに戻ってインスペクターでWin Textフィールドに参照を設定しましょう。 f:id:enia:20210303080442p:plain

さぁ、実際に動かしてみましょう。 アイテムを全部取得したら”You Win!"という文字列が表示されますね! f:id:enia:20210303080713p:plain

玉転がしゲームへの機能追加は今回で最後となります。
次回はゲームをビルドしていきます。今回はここまで!

猫でもわかるUnity入門(第14回 玉転がし作成 その6)

f:id:enia:20210228230354p:plain

えにあです。猫でもわかるUnity入門 第14回を進めていきます。
前回はピックアップオブジェクト作成し、ゲームエリアに配置しました。 今回は配置したオブジェクトにプレイヤーが衝突したら、そのオブジェクトを取得できるようにしていきます。

目次

アクティブ/非アクティブ

まず、前回非アクティブにしたプレイヤーオブジェクトをアクティブに戻しましょう。 インスペクターでチェックボックスにチェックをいれればOKです。

ここで、アイテムを集めるためには何ができれば良いかを考えてみましょう。 プレイヤーがアイテムを取得したら、取得したアイテムはフィールド上から消す必要がありますよね。 この消す処理に非アクティブ化が使えそうです。

つまり、プレイヤーがピックアップオブジェクトに衝突したら、スクリプトの中でピックアップオブジェクトを非表示にするのです。 スクリプトはこの後作成しますので、ここではアクティブ/非アクティブについて覚えておきましょう。

衝突を検出しよう

ピックアップオブジェクトを非アクティブにする処理は、どこに書けばよいでしょうか。 Updateメソッドの中に書いてしまっては、ゲーム開始後すぐに非アクティブになってしまいます。

実は、オブジェクトとオブジェクトが衝突した時に実行される便利なメソッドがあります。 OnTriggerEnterメソッドです。

PlayerControllerスクリプトを以下のように修正します。 最初なので、今までの修正も含めてすべてのコードを記載していますが、追加したのはOnTriggerEnterメソッドだけです。

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

public class PlayerController : MonoBehaviour
{
    public float speed;
    private Rigidbody rb;

    void Start ()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate ()
    {
    float moveHorizontal = Input.GetAxis("Horizontal");
    float moveVertical= Input.GetAxis("Vertical");

        Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
        rb.AddForce(movement * speed);
    }

    void OnTriggerEnter(Collider other)
    {
        other.gameObject.SetActive(false);
    }
}

OnTriggerEnterメソッドはCollider型のotherを引数として受け取ります。 この引数にはプレイヤーオブジェクトに衝突したオブジェクトが入っています。

メソッドの中身を見てください。
other.gameObject.setActive(false)と書かれていますね。 other.gameObjectで衝突したオブジェクトを取得し、そのgameObjectをsetActive(false)で非アクティブにすることで非表示にすることができるのです。

しかし、これだけでは大事な要素が抜けています。 次の手順で修正しましょう。

何と衝突したか判定する

先ほどのスクリプトでは、プレイヤーオブジェクトがピックアップオブジェクトと衝突した時に、ピックアップオブジェクトを非表示にするという要件を満たしていません。 そう、衝突したものが何かを判定できていないのです。

衝突したものが何かを判定するにはどうすればよいでしょう。
その答えはタグです。
オブジェクトにタグ文字列をつけて、衝突したオブジェクトのタグが期待したものであるかどうかを判定するのです。 Twitterハッシュタグで検索するのと同じようなものですね。

Unityに戻って、Pick Upオブジェクトにタグをつけます。 Pick Upオブジェクトは12個ありますが、プレイヤーオブジェクトと衝突した時の動作はどれも変わらないはずです。 つまり、12個のピックアップオブジェクトはすべて同じタグ名でよいはずです。 一度に設定するにはどうすればよいでしょう。 プレハブの出番です。

まず、プロジェクトビューでプレハブを選択します。 ※前回1列レイアウトに変更した続きなので、そのままにしています。
f:id:enia:20210302130955p:plain

次に、インスペクターでタグを追加します。現状はUntaggedになっていますね。
f:id:enia:20210302131106p:plain

遷移後の画面で+ボタンを押してタグを追加します。名前をPick UpにしてSaveボタンを押しましょう。
f:id:enia:20210302131243p:plain

さて、もう一度プロジェクトビューでPick Upプレハブを選択して、インスペクターを再表示してみてください。
f:id:enia:20210302131521p:plain

おっと。まだUntaggedになっていますね。 変更を反映させるために、プルダウンからPick Upを選択してください。
f:id:enia:20210302131605p:plain

今度はヒエラルキービューでPick Upオブジェクトを一つ選んでインスペクターで見てみましょう。 私はPick Up(5)を見てみましたがタグに「Pick Up」が設定されています。 プレハブの変更が全てのPick Upオブジェクトにちゃんと反映されていますね。
f:id:enia:20210302131702p:plain

では次に、このタグを使って、PlayerControlelrスクリプトを修正していきましょう。 修正後のOnTriggerEnterメソッドは以下のようになります。

    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Pick Up")) {
            other.gameObject.SetActive(false);
        }
    }

タグを判定するにはgameObjectのCompareTagメソッドを使います。 これで衝突したオブジェクトに”Pick Up"というタグが設定されている場合だけ、非アクティブにすることができます。

プレイモードにして試してみましょう。 あれ?ピックアップオブジェクトにぶつかると、壁にぶつかったときと同じようにボールが止まってしまいますね。

トリガーに設定する

Pick Upプレハブを選択し、インスペクターでBox Colliderのトリガに設定するにチェックを入れてみましょう。 f:id:enia:20210302133409p:plain

これを有効にするとコライダーはトリガーイベントに反応し、物理エンジンからは無視されます。

というポップアップが出ていますね。

先ほどまではUnityの物理エンジンの計算に従って処理が行われていたため、動くオブジェクトが、止まっているオブジェクトにぶつかると弾かれる、というデフォルトの動作になっていました。 このチェックを入れることで物理エンジンから無視されるため、弾かれることはなくなります。

さぁ、もう一度プレイモードにして試してみましょう。

おぉー。アイテムに触れたら消えるようになりましたね! f:id:enia:20210302133920p:plain

NOTE:
OnTriggerEnterと似たようなメソッドに、OnCollisionEnterがあります。 OnTriggerEnterはオブジェクトとオブジェクトが重なり、すり抜けたときに呼ばれるメソッドなのに対し、OnCollisionEnterはオブジェクトとオブジェクトがぶつかり、反発するときに呼ばれるメソッドです。 「トリガーにする」にチェックを入れることで物理エンジンから無視され、OnTriggerEnterメソッドが呼ばれるようになったわけですね。 ※こちらの記事を参考にしました。 nullkun0803.hateblo.jp

パフォーマンスを改善する

ここまでで目的の動作を実現できましたが、最後にもう少しだけ改善しましょう。

Unityはパフォーマンスを最適化するために、シーン内のすべての静的なオブジェクトの領域を計算し、キャッシュとして保存しています。 静的なオブジェクトとは、簡単に言えば基本的にはじっとしていて動かないオブジェクトです。 フレームごとに衝突の計算をする場合、動かないオブジェクトであれば今どの範囲にオブジェクトが存在するか計算する必要はありません。動かないのですからキャッシュの値をそのまま使えば良いわけです。

しかし、動かないオブジェクトを動かした場合はどうでしょう。 今回で言えば、ピックアップオブジェクトは元々はただのキューブでしたが、スクリプトで回転させていますね。 このように、オブジェクトの位置や角度が変更された場合、Unityは変更されるたびにキャッシュを更新していきます。これは負荷のかかる作業です。

一方で、動的なオブジェクトの場合、キャッシュの計算は行われません。 動的なオブジェクトとは、簡単に言えばプレイヤーオブジェクトのような動くオブジェクトです。動くことを前提としているのでキャッシュを保存する必要はありません。(※必要な都度計算するのだと思います)


では、ピックアップオブジェクトをキャッシュさせないようにするにはどうしたら良いでしょう。 動的なオブジェクトに変更すればよいのです。

Unityにおいて、静的か動的かに判定はどのように判定されるのでしょうか。 実はRegitbodyとColliderを持っているオブジェクトは動的と判定されます。 プレイヤーオブジェクトは、元々Sphere Colliderを持っており、以前の手順でRegidbodyを追加しているので動的オブジェクトとして判定されています。 一方、ピックアップオブジェクトをインスペクターで見ると、BoxColliderは持っていますが、Regidbodyはありません。そのため、静的オブジェクトとして判定されています。

動的にオブジェクトに変更するために、Regidbodyをアタッチしてみましょう。 リジッドボディのアタッチは、プレイヤーオブジェクトを作成する時に一度やりましたね。 ただし、複数のピックアップオブジェクトを一度に更新するため、プレハブの方に設定していきます。 インスペクターから「コンポーネントを追加」->「リジットボディ」で追加しましょう。
f:id:enia:20210302140317p:plain

これで、ピックアップオブジェクトはRegidBodyとColliderを持つ動的オブジェクトになりました。 セーブして、プレイモードにして実行してみましょう。
あれ?」スタートするとすぐに、ピックアップオブジェクトが地面に吸い込まれてしまいました。

リジットボディをアタッチしたことで、重力の影響を受けるようになり落下してしまったのです。 さらに、前の手順でトリガーにしたことで床に衝突することもなくすり抜けてしまいます。

ピックアップオブジェクトは物理的な力の影響を受けないようにしたいので、RegidBodyの設定を変えましょう。 インスペクターで「RegidBody」 -> 「isKinematic」にチェックを入れましょう。 isKinematicにチェックをつけると物理演算が無効になり、 チェックを外すと他の物体が衝突した時にその影響を受けるようになります。 f:id:enia:20210302140858p:plain

NOTE:
UseGravityというチェックボックスもあります。このチェックボックスにチェックを入れると重力の影響を受け、外すと重力の影響をうけません。
UseGravityにチェックをいれ、isKinematicのチェックを外した場合はどうなるでしょうか?重力の影響は受けませんが他の物理演算は行われます。つまり、プレイヤーとピックアップオブジェクトは衝突してしまいます。
逆に、isKinematicだけにチェックを入れた場合、全ての物理演算が行われなくなるため、重力の影響も含めてすべての物理的な影響を受けなくなるようです。

これで、動作は変えずにキャッシュ計算を減らし、パフォーマンスを改善することができました。

ゲームらしさがどんどん増してきましたね! 今回はここまで!

猫でもわかるUnity入門(第13回 玉転がし作成 その5)

f:id:enia:20210228230354p:plain

初めに

えにあです。猫もでも分かるUnity入門の第13回を進めていきます。
前回はフィールドに壁を追加しましたね。 今回はマリオにおけるコインのように、プレイヤーが収集するためのオブジェクトを配置していきます。
Unityの操作にもだいぶ慣れてきたと思うので、既出の操作については説明を短めにしたいと思います。

目次

ピックアップオブジェクトを作成しよう

まず新しいキューブオブジェクトを作成し、名前を「Pick Up」とします。 f:id:enia:20210302072457p:plain

作成したピックアップオブジェクトはリセットして位置を(0, 0, 0)に戻しておいてください。 f:id:enia:20210302072536p:plain

ヒエラルキービューでピックアップオブジェクトを選択した状態で「Shift + F」を押してみてください。 シーンビューの中心に今作成したピックアップオブジェクトが表示されたでしょうか。 f:id:enia:20210302073215p:plain

これからピックアップオブジェクトを編集していきますが、このままではプレイヤーオブジェクトが少し邪魔ですね。 プレイヤーオブジェクトを非アクティブにすることで、一時的に非表示にしましょう。 非アクティブにするには、インスペクターで名前の横のチェックボックスを外します。
f:id:enia:20210302073357p:plain

すると、シーンビューからプレイヤービューが消えましたね。
f:id:enia:20210302073449p:plain

このキューブが、このゲームで収集していくアイテムの基本形になります。

収集アイテムっぽくしていこう1

さて、ピックアップオブジェクトも、初めてプレイヤーオブジェクトを作成した時と同じように地面に埋まってしまっていますね。 キューブのデフォルトサイズは、スフィアと同様に(1, 1, 1)です。 つまり、0.5ポイントだけY軸方向にずらせば、ちょうど地面の上に乗りますね。 f:id:enia:20210302073712p:plain

これだと、まだ収集できるアイテムのようには見えませんね。 サイズを少し小さくて、(0.5, 0.5, 0.5)に変更してみましょう。 するとピックアップアイテムが少し宙に浮きます。
※カメラの角度を変えると、浮いているのが分かりやすいと思います。 f:id:enia:20210302074154p:plain

このように、小さくして浮かばせると収集アイテムっぽさが出てきます。 さらに、回転を(45, 45, 45)に設定して傾けてみましょう。

ピックアップオブジェクトのTransformは以下のように設定されていればOKです。 f:id:enia:20210302074413p:plain

おぉ、よりアイテムっぽくなりましたね。 f:id:enia:20210302074351p:plain

収集アイテムっぽくしていこう2

ピックアップオブジェクトがクルクルと回転していたら、各段に収集アイテムっぽさが増しますね。 こんな時はスクリプトの出番です。

スクリプトの追加はインスペクターから「コンポーネントの追加」->「新しいスクリプト」で行い、オブジェクトへのアタッチまでワンステップで行います。 名前は「Rotator」にしましょう。 スクリプトファイルの位置を「Scripts」フォルダの下に移動するのを忘れずに!

今回はオブジェクトに力を加えるわけではなく、フレームごとに回転させるだけなのでUpdateメソッドを使います。

スクリプトを以下のように修正してみましょう。

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

public class Rotator : MonoBehaviour
{
    void Update()
    {
        transform.Rotate(new Vector3(15, 30, 45));
    }
}

transformクラスは以前にもしれっと使われていましたが、オブジェクトの位置や角度を変えるためのメソッドが用意されているクラスです。 ドキュメントはこちらにあります。 UnityEngine.Transform - Unity スクリプトリファレンス

フレームごとに、自身の角度を(15, 30, 45)だけ回転させているわけですね。 プレイモードに変更して、実際に動かしてみましょう。

 ・
 ・
 ・

いかがでしたか?ものすごいスピードでピックアップオブジェクトが回転してしまいましたね。 毎フレームごとに(15, 30, 45)の角度で回転しているので、当然と言えば当然です。

回転速度を調整する必要がありそうです。 Updaetメソッドを、以下のように修正してみましょう。

  void Update()
    {
        transform.Rotate(new Vector3(15, 30, 45) * Time.deltaTime);
    }

新たに登場したTime.deltaTimeについて考える前に、再度プレイモードに変更して実際に動かしてみましょう。 今度はゆっくりと回転するようになりましたね?

このdeltaTimeについて公式のチュートリアルでは特に解説がありませんでしたが、なぜこの数字を掛け算するのか考えていきましょう。

回転の速度を遅くしたいだけなら、例えばnew Vector3(15, 30, 45) * 0.01f); でも良いはずですよね?
こうすると、毎フレームごと(0.15, 0.3, 0.45)だけ回転することになります。
実際に試してみると、ゆっくりと回転することが分かるはずです。

しかし、キレイに回転させようと思うと「この毎フレームごと」というのが問題です。
実は、1フレームにかかる時間というのは一定ではありません。

  1フレーム -> (0.016秒) -> 2フレーム -> (0.018秒) -> 3フレーム・・・

というように、フレームとフレームの間で実際にかかっている時間は毎回異なります。

ということは、1秒間に含まれるフレーム数は一定ではないということです。 1秒間に100フレームの場合もあれば、200フレームの場合もあるかもしれません。
(※分かりやすく大げさにしていますが、そこまで差が出ることはないのでしょう)

先ほどのように0.01fを掛ける方法だと、100フレーム/秒の場合は1秒で(15, 30, 45)だけ回転し、200フレーム/秒の場合は1秒で(30, 60, 90)回転する、というように1秒ごとの回転量が一定になりません。 これでは、滑らかに回転しているようには見えないですよね?

滑らかに回転させるためには、1フレームごとの回転量を一定にするのではなく、1秒ごとの回転量を一定にする必要があるのです。


そこで、deltaTimeの出番です。 deltaTiemにはフレーム間の「時間差」が設定されています。単位は秒です。

距離 = 速度×時間の公式を思い出しましょう。 ここでは移動ではなく回転を扱っていますが、(15, 30, 45)が1秒当たりの回転量だと考えれば、これは回転速度と捉えられますね。 そして、フレーム間の時間はTime.deltaTimeです。 この二つを掛け算すれば、1フレームごとの移動距離(回転量)が求められます。

結果として、滑らかに、1秒かけて(15, 30, 45)の角度だけ回転するようになるわけです。

deltaTimeの理解に関しては下記のブログを参考にさせていただきました! thinline196.hatenablog.com

収集アイテムを増やしていこう1

基本となるピックアップオブジェクトの形は出来てきました。 収集するアイテムが一つだけでは寂しいので12個に増やしていきます。

その前に1つやることがあります。 ピックアップオブジェクトをプレハブ(prefabs)にすることです。

プレハブとはオブジェクトの設計図です。 1つのプレハブ(設計図)からたくさんのインスタンス(実体)を作ることで、設計図を変更するだけで全ての実体に変更を反映させることが可能になります。

プロジェクトビューに、Prefabsフォルダを追加します。 f:id:enia:20210302085726p:plain

そして、ヒエラルキービューからPick Upオブジェクトをドラッグし、プロジェクトビューのPrefabsディレクトリにドロップします。 PrefabsディレクトリにPickUpオブジェクトが格納されたでしょうか? f:id:enia:20210302085833p:plain

次に、これから作成する12個のPick Upオブジェクトのフォルダとなる、「Pick Ups」という空のオブジェクトを作成します。 東西南北の壁をまとめるためにWallsオブジェクトを作ったのと同じですので手順は割愛しますね。 Pick Upsオブジェクトをリセットして、原点に位置させるのを忘れずに。

壁を作成した時と異なり、今回は親である「Pick Ups」より先に、既に子である「Pick Up」が存在します。 このような場合は、ヒエラルキービューで「Pick Up」をドラッグし、「Pick Ups」にドロップすればOKです。

以下のように、親子関係になったでしょうか。
f:id:enia:20210302090813p:plain

次に、ピックアップオブジェクトを配置してみます。 ヒエラルキービューで「Pick Up(子の方)」を選択し、シーンビューに表示される、赤・緑・青(X・Y・Z)の線を引っ張ればオブジェクトを移動させることができます。

インスペクターで位置を設定する方法でもオブジェクトを移動できますが、今回の方法ですとグラフィカルに位置を変えることができます。

試しに赤い線を引っ張ってみると、斜めに移動してピックアップオブジェクトが空中に飛び出してしまいました。 f:id:enia:20210302091704p:plain

これは、ピックアップオブジェクトは(45, 45, 45)に回転しているので、その軸をベースに移動してしまうためです。 「ctrl + Z」、または「編集」->「Undo Mode」で元の位置に戻しておきます。

地面に沿って、水平に移動させる場合はグローバルモードを使います。 トップメニューの下に「ローカル」という表示がありますね。
f:id:enia:20210302092538p:plain

ここをクリックすると「グローバル」に変わります。
f:id:enia:20210302092553p:plain

グローバルモードにすると、表示される軸が縦・横・高さの一般的な方向に戻り、水平に移動できるようになります。 f:id:enia:20210302092728p:plain

ローカルモードはそのオブジェクトの中でのX・Y・Z軸を基準にし、グローバルモードはゲーム全体の世界でのX・Y・Z軸を基準にするということですね。

ピックアップオブジェクトを配置する際、カメラを上から移すと位置関係が分かりやすいです。 シーンビューの右上にカメラの方向が映っています。 緑色のYを押してみてください。 f:id:enia:20210302093413p:plain

すると、このように真上からの撮影に切り替わりますね。 f:id:enia:20210302093551p:plain

NOTE:
Yが表示されていない場合はX、Zなどを押してみればYが表示されるはずです。

この状態でヒエラルキービューで「Pick Up」を選択してみてください。 図のように青軸と赤軸の間に正方形が表示されると思います。
f:id:enia:20210302093827p:plain

ここを左クリックしながらマウスを動かすと、平面上を自由にオブジェクトを動かすことができます。

収集アイテムを増やしていこう2

前準備は完了です。ではPickUpオブジェクトを増やしていきましょう。 ヒエラルキービューで「Pick Up(子の方)」を選択し「Ctrl + d」を押してみてください。

オブジェクトが複製(duplicate)され、以下のようになるはずです。 f:id:enia:20210302094029p:plain

同様の手順でPick Upオブジェクトを12個に増やし、配置してきます。 円作るのが下手すぎてすみません。 f:id:enia:20210302094726p:plain

さあ、プレイモードに変更して試してみましょう。 12個のピックアップオブジェクトが回転していますね!

収集アイテムに色をつけよう

オブジェクトに色を付ける場合、オブジェクト鬼マテリアルをアタッチする必要があります。 地面に色をつける際に一度やりましたね。

まずはピックアップオブジェクト用のマテリアルを作成しましょう。 一から作成してもよいですが、地面用のマテリアルをコピーして再利用します。 プロジェクトビューでMaterialsフォルダを開き、Backgroundマテリアルを選択して「ctrl + D」で複製します。
f:id:enia:20210302101218p:plain

このマテリアルの名前をPick Upに変更します。
名前の変更はマテリアルを右クリックして「名前の変更」、またはF2で行います。
f:id:enia:20210302101303p:plain

地面と同じ色では見づらいので、黄色に変更してきます。
色の変更方法は、インスペクターでアルベドの欄にある四角をクリックです。
f:id:enia:20210302101522p:plain

RGBを(255, 255, 0)に変えましょう。
f:id:enia:20210302101543p:plain

次にこのマテリアルをピックアップオブジェクトに適用していきます。 ここで、先ほどピックアップオブジェクトをプレハブにしたことが生きてきます。 プレハブ(設計図)に色の変更を適用すれば、12個のピックアップオブジェクト全てに変更が反映されるのです。

まず、プロジェクトビューの表示方法を切り替えます。 プロジェクトタブを右クリックして、1列レイアウトにします。
f:id:enia:20210302102135p:plain

アセットが、このように縦に表示されるようになりましたね?
f:id:enia:20210302102211p:plain

次に、Materialsの「Pick Up」をドラッグし、Prefabsの「Pick Up」にドロップします。 ピックアップオブジェクトの色が変わったでしょうか?

NOTE:
公式チュートリアルではドロップした瞬間にシーンビューの色が変わりましたが、私の場合ドロップした時点では変わりませんでした。
その場合、プレイモードに一度変更すると反映されると思います。

さあ、プレイモードにして確認してみましょう。 12個の黄色い立方体が、くるくると回転していますね!

今回はここまで!