- 投稿日:2019-10-09T21:54:54+09:00
Unity玉転がしチュートリアル 2-1.カメラの移動
この記事の対象者
- Unity入門したい人
- 最初の一歩が踏み出せない人
OSとか環境とか
- Windows 10 Pro
- macOS Mojave
- Unity 2019.2.8f1
- Rider 2019.2.2
補足
- 公式動画にて利用しているのはMacなので、Windowsユーザーはある程度脳内変換して見る事
- 筆者はWindows、Macの両方の環境で確認。Ubuntuとかでは検証してない。
- 基本Unityは英語メニューで利用
- 間違いがあったらツッコミ大歓迎
公式
https://unity3d.com/jp/learn/tutorials/projects/roll-ball-tutorial/moving-camera
カメラの移動
現状のままだとカメラが固定なので、プレイヤーオブジェクトが非常に見づらい
→カメラとプレイヤーオブジェクトを紐付ければ万事解決じゃない?下準備としてカメラの位置調整
PositionのYを10,Zを-10
RotationのXを45
に調整して、少し上から見下ろす形にするPlayerの子としてMainCameraを設定
この状態にすると、Playerオブジェクトが動かした場合(移動や回転)Main Cameraも一緒に移動する
※上記設定後「あー余裕だわー」とPlayして玉を動かすと高速なラートみたいな視点になるので落ち着きましょうカメラとプレイヤーの関係性
あくまで「プレイヤーの子としてカメラが設定された」だけで、相対的な位置関係は変わっていない
なので
・親のSphereオブジェクトが動く
→回転して移動する
・子のMain Cameraオブジェクトが動く
→親のSphereオブジェクトに連動して同じく「回転」するなので、Main CameraがSphereの子の状態だと視点がラートになる
カメラとプレイヤーはスクリプトで紐付ける必要があるカメラへのスクリプトの追加
CameraControllerという名前でスクリプトを追加します
※カメラとスクリプトの紐付けは行っている事追加するスクリプトは以下
CameraController.csusing System.Collections; using UnityEngine; public class CameraController : MonoBehaviour { public GameObject player; private Vector3 offset; void Start() { offset = transform.position - player.transform.position; } void LateUpdate() { transform.position = player.transform.position + offset; } }内容については単純なので割愛
ポイントとしては、毎フレーム処理する時にUpdateを使わずにLateUpdateを利用する事
ライフサイクルだとGame Logicに当たる箇所の
はじめに呼ばれるのがUpdate
最後に呼ばれるのがLateUpdate
となる真・カメラとプレイヤーの紐付け
スクリプトを保存して、UnityエディタでCameraControllerのPlayer部分を見ると「None」となっているので紐付け
紐付ける方法は動画ではPlayerオブジェクトをドラッグしているが、フィールドの右にある小さい○をクリックして
出てくるダイアログで選択してもOKこれでPlayをすると、ボールの動きを追従するカメラの出来上がりとなる
- 投稿日:2019-10-09T19:50:16+09:00
UnityのCreator Kit: PuzzleをVR空間内でPuzzleの配置ができるようにする
はじめに
前回記事 UnityのCreator Kit: PuzzleをOculusQuestで動かしてみる の続きです。
前回記事では、既存のPuzzleが配置されたシーンを動かすところまででしたが、今回、Puzzleのオブジェクトを自由に配置できるようにしました。
元のコードではPuzzleを配置する機能はエディター拡張機能を使用して実装されているのですが、VR空間内で動作させるためにはエディター拡張機能は使用できないため、この部分のコードは新規に作成する必要がありました。
ソースコードはGitHubのCreatorKitPuzzleに置いています(前回記事から更新しました)。
UnityのCreator Kit: PuzzleをOculusQuestで動かせるように改造しました pic.twitter.com/KpULf8AguD
— 高浜 (@SatoshiTakahama) October 9, 2019開発環境
Unity 2019.2.4f1
Creator Kit: Puzzle - 1.1
Oculus Integration for Unity - 1.40
VrGrabber-v0.0.3 (hecomi氏作)
DotNetZip-v1.9ビルド手順
- GitHubのCreatorKitPuzzle からcloneでファイルをローカルに持ってきます。
- 持ってきたファイルを指定してUnityでプロジェクトを開きます。
- Build Settings から Platform を Android に Switch Platformします。
- Oculus Integrationをアセットストアからダウンロードし、インポートします。
- Creator Kit: Puzzleをアセットストアからダウンロードし、インポートします。インポートする際、すべてインポートしてしまうとプロジェクトの設定が上書きされてしまうため、ProjectSettingsのチェックを外します。
- オブジェクトをつかむためのアセットVrGrabberをVrGrabber からダウンロードし、インポートします。自分がダウンロードしたファイルは"VrGrabber-v0.0.3.unitypackage"ですが、数字の部分はバージョンにより変わります。
- OculusQuest向けに変更したシーンLevelFreeを開きます。
- OVRCameraRigのTarget DevicesをQuestに変更します。
- ビルドするシーンを選択し、Build Settings からビルドします。
操作方法
・左側コントローラー
スティック 前後移動、左右方向転換・右側コントローラー
スティック つかんだPuzzleのオブジェクトの操作
スティック押下 オブジェクトを消去(オブジェクトをつかんでいる状態の時)
B UIの表示切り替え
A ハンマー、フリッパー等稼働するオブジェクトの操作/UI上での選択
IndexTrigger オブジェクトの生成
HandTrigger オブジェクトをつかむ改造方法の検討
Puzzleを配置する機能を実現するために、以下のことができればよさそうと考えました。
・配置できるPuzzleを表示し、選択する機能
・選択したPuzzleを生成し、自由に配置する機能
・配置をセーブ・ロードする機能さらに各機能について以下のように検討しました。
配置できるPuzzleを表示し、選択する機能
元のプロジェクトにPuzzleのPrefabが含まれているので、それをシーンに一度配置して、後で検索できるようにタグをつけます。FindGameObjectsWithTagで検索したオブジェクトをリスト化してUIに表示し、選択できるようにします。(グラフィカルなプレビュー画面があるほうがわかりやすいのですが、とりあえずはオブジェクトの名前のテキストで表示します)
リスト化が終わったら、シーンに配置したオブジェクトを無効化して見えなくします(最初は有効にしておかないと検索できないので)。選択したPuzzleを生成し、自由に配置する機能
選択したPuzzleをInstantiateでインスタンス化します。配置するときは勝手に動いてほしくないので、RigidbodyのuseGravity=falseに、isKinetic=trueに設定しておきます。
インスタンス化した後、Puzzleを動かす方法はVrGrabberの機能をそのまま使用します。このためにPuzzleのPrefabにはあらかじめVrgGrabbableコンポーネントをつけておきます。また、消去する機能を実現するために、VrgGrabbableコンポーネントのOn Grab Clickedには消去するためのスクリプトを設定しておきます。配置をセーブ・ロードする機能
Unityでデータを保存する機能としてはPlayerPrefsがありますが、今回のように保存するデータが大きくなる可能性がある用途には向かなさそうでした。手順としてはC#オブジェクトからJsonに変換し、System.IO等でファイルに保存すればよさそうということがわかりましたが、色々調べたところ、@tricrow氏の記事Unityでユーザーデータをローカルにファイルとして保存するが私にはわかりやすかったため使用させていただくことにしました(自分の使い方ではコードを変更する箇所がなく、全くのコピペです)。
1点、現在では圧縮に使用しているライブラリDotNetZipのファイルを入手する方法が難しく(わかりにくく)なっており、CodePlexからバイナリを入手を参考にさせていただきました。DotNetZipのライセンスはMicrosoft Public License (MS-PL)となっています。また、バイナリをAssets\Plugins\DotNetZipに置いています。
Jsonへの変換にはJsonUtilityを使用していますが、変換可能なオブジェクトには色々と制約があります。最初知らずにPuzzleのオブジェクトを突っ込んでいたらうまくいかず、結構はまりました。最終的には、オブジェクトの名前と位置だけを保存し、復元するときはそれをもとに再度インスタンス化するようにしました。この辺りは実機上でデバッグするのは難しく、PC上で実行して生成されたJsonを確認(自分はVisual Studio Codeを使いました)を繰り返しました。GitHubに置いたソースコードについて
DebugUIBuilderHand.csは、Oculus Integrationに含まれているDebugUIBuilder.csをもとに改変したもののため、ライセンスはOculus Integrationに従います(Assets\Oculus\SampleFramework\license.txtをご確認ください)。
IDataFile.cs, DataFilePlain.csは、@tricrow氏の記事Unityでユーザーデータをローカルにファイルとして保存する中に記載されているコードをそのまま持ってきたものです。
そのほかのソースコードはCC0としますので好きなようにご使用ください。
PlayUI.csは、Puzzleの操作に関するUIを構築するためのもので、Puzzleを配置する機能はほとんどこのコードで実装しています。DebugUI.csは、デバッグ用の情報を表示するためのUIを構築するためのもので、DebugMover.csは、キャラクターを操作するためのものです。制限事項
以下既知の問題があります。
・オブジェクトを消去すると、アプリが落ちることがあります。
・複数のパーツで構成されたオブジェクトを移動するとバラバラになることがあります。
・ボールに映る映像には配置したオブジェクトは反映されません。
・Restartすると配置モードに戻ります。
・Restartするとログが更新されなくなります。
- 投稿日:2019-10-09T15:42:53+09:00
[随時更新]超初心者がUnityで気を付けること
プログラミング全般
・ちゃんとした変数名、関数名をつけよう。void Test()とかint countとか作っちゃだめだぞ
GameObject関係
・GameObject.Findは重いから使わない(使っても精々Start、Awake系だけ)
Transform関係
・transform.rotationは理解できるまで触らない
Quatanionは複雑な値なので、RotateやeulerAnglesを使おう・scaleの比率を1:1:1以外にした上で回転させると予想外のことが起きやすい。やめとこう。
・transform.Findで参照できるのは直近の子供だけ
全ての子供を取りたい時はGetComponentsInChildren()を使おう(Tは欲しいクラス。Transformも取れる)。ただし重い。・子の中の、常に特定の物を取りたいなら、transform.GetChild()を使うとよい
その他
別PCにプレハブを移動させたい時は、Assets/ExportPackageからパッケージにして持っていこう
- 投稿日:2019-10-09T12:03:06+09:00
Unity玉転がしチュートリアル 1-2.プレイヤーの移動
この記事の対象者
- Unity入門したい人
- 最初の一歩が踏み出せない人
OSとか環境とか
- Windows 10 Pro
- macOS Mojave
- Unity 2019.2.8f1
- Rider 2019.2.2
補足
- 公式動画にて利用しているのはMacなので、Windowsユーザーはある程度脳内変換して見る事
- 筆者はWindows、Macの両方の環境で確認。Ubuntuとかでは検証してない。
- 基本Unityは英語メニューで利用
- 間違いがあったらツッコミ大歓迎
公式のリンク
https://unity3d.com/jp/learn/tutorials/projects/roll-ball-tutorial/moving-player
プレイヤーの移動
追加したSphereがキーボードで動く様に調整する
移動時の条件
・ゲームエリア全体を転がる
・壁にぶつかる
・常に接地している(宙に浮かない)
・アイテムに接触したらアイテムを取得する→物理演算が必要
Rigidbodyコンポーネントをアタッチする必要があるアタッチする方法
- アタッチする対象のゲームオブジェクトを選択(今回はPlayerゲームオブジェクト)
- Component>Physics>Rigidbodyを選択
上記のようにアタッチされる
アタッチした要素は並び替えが可能となるので、要素が増えたりしたら並び替え等でキレイキレイするキーボードの入力について
動きを制御するスクリプトをアタッチして実現する
スクリプトを格納するフォルダ「Scripts」を作成し、その中にスクリプトを格納するのが良い
追加方法は何個かあるのだが、今回は「Add Component」から追加する方法が有効
メニューよりNew Scriptという項目から追加
→スクリプトを別で用意しても良いが、そのスクリプトをアタッチする手間が省けるので楽
PlayerControllerという名前でスクリプトを追加これでこのPlayerオブジェクトにスクリプトがアタッチされる
スクリプトの記述
基本スクリプトファイルをダブルクリックして紐付いたエディタが起動する
※筆者はRiderを使ってコーディングするので、Riderが起動するが、こだわりがなければVisualStudio2019 Communityあたりが起動する
PlayerController.csの記述方法等については動画参照の事ですが何点か補足
- 動画でも説明されているが、**公式のドキュメントを読むのは基本
Unityに限った事ではないので、なんか文字沢山書いてあるなーと思わないで
公式のドキュメントはちゃんと読みましょう!
何なら公式ドキュメントの読み方も超丁寧に動画にしてくれている
Just Do It!
- ライフサイクル
https://docs.unity3d.com/ja/2019.1/Manual/ExecutionOrder.html
を参照すれば良さそう出来上がったものがこちら!
PlayController.csusing UnityEngine; public class PlayerController : MonoBehaviour { public float speed; public Rigidbody rb; // See also:https://docs.unity3d.com/ja/2019.1/Manual/ExecutionOrder.html private void Start() { rb = GetComponent<Rigidbody>(); } private void FixedUpdate() { float moveHorizontal = Input.GetAxis("Horizontal"); float moveVertical = Input.GetAxis("Vertical"); Vector3 movement = new Vector3(moveHorizontal,0.0f,moveVertical); rb.AddForce(movement * speed); } }Publicで定義した変数はUnityのエディタ内で直接値を編集出来るのが特徴的なので覚えておく事
これでボールの制御が出来るようになるので大勝利
- 投稿日:2019-10-09T11:00:39+09:00
Unity iOS/Androidで位置情報を取得する
Unity上のiOS/Androidで位置情報を取得とiOS/Androidのパーミッションまわりについて試して見たことを記載します。
Unity公式の位置情報取得のサンプルコード
Unity公式の位置情報取得のサンプルコードのコメントを訳したものを下記に記載します。
このコードでも位置情報を取得できますが、Unityの位置情報の取得を管理するクラスLocationServiceがシンプルすぎて、iOS/Androidの位置情報取得の可否の状態によってどういう挙動をするのかがドキュメントからは不明瞭なので、本記事ではそのあたりを実機を動かして確認していきます。
using UnityEngine; using System.Collections; public class TestLocationService : MonoBehaviour { IEnumerator Start() { // 最初に、ユーザーがロケーションサービスを有効にしているかを確認する。無効の場合は終了する if (!Input.location.isEnabledByUser) yield break; // 位置を取得する前にロケーションサービスを開始する Input.location.Start(); // 初期化が終了するまで待つ int maxWait = 20; // タイムアウトは20秒 while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0) { yield return new WaitForSeconds(1); // 1秒待つ maxWait--; } // サービスの開始がタイムアウトしたら(20秒以内に起動しなかったら)、終了 if (maxWait < 1) { print("Timed out"); yield break; } // サービスの開始に失敗したら終了 if (Input.location.status == LocationServiceStatus.Failed) { print("Unable to determine device location"); yield break; } else { // アクセスの許可と位置情報の取得に成功 print("Location: " + Input.location.lastData.latitude + " " + Input.location.lastData.longitude + " " + Input.location.lastData.altitude + " " + Input.location.lastData.horizontalAccuracy + " " + Input.location.lastData.timestamp); } // 位置の更新を継続的に取得する必要がない場合はサービスを停止する Input.location.Stop(); } }動作環境
- Unity 2018.4f8 Mac版
- XCode 11.0
各OSの位置情報取得の許可の状態について
iOSとAndroidのOSごとの位置情報取得の許可の状態について下記で記載します。
UnityではこのあたりがLocationServiceによって抽象化されてしまっています。iOS
CLAuthorizationStatusに記載されているように、下記の5状態が存在します。
- notDetermined - ユーザーは未選択
- restricted - 許可されていない(ユーザーは特に拒否していないが何らかの理由で使用できない場合)
- denied - ユーザーは拒否
- authorizedAlways - 常に許可
- authorizedWhenInUse - アプリの使用中のみ許可
notDetermined
ユーザーはアプリで位置情報サービスを使用できるかどうかを選択していない。
位置情報取得の確認ダイアログをまだ表示したことがないのがこの状態。
restricted
アプリは位置情報サービスの使用を許可されていない。
ユーザーは位置情報サービスの使用を特に拒否していないが、何らかの理由で使用できない場合にこの状態になるはず。
「設定 > プライバシー > 位置情報サービス」で位置情報サービスをオフにした場合はこの状態(iOS 13.1.2で確認)。denied
ユーザーがアプリの位置情報サービスの使用を拒否したか、設定でグローバルに無効化されている。
位置情報の取得確認ダイアログで拒否を選択したか、「設定 > プライバシー > 位置情報サービス」で「なし」を選択したかのどちらかがこの状態。
authorizedAlways
ユーザーは、いつでも位置情報サービスを開始することをアプリに許可した。
位置情報の取得確認ダイアログで「常に」を選択するとこの状態になる。アプリがバックグラウンドにいてもアプリは位置情報が取得可能。
authorizedWhenInUse
ユーザーは、アプリが使用中に位置情報サービスを開始することを承認した。
位置情報の取得確認ダイアログで「使用中のみ」を選択するとこの状態になる。アプリがフォアグラウンドの状態でのみアプリは位置情報が取得可能。
Android
下記の3状態が存在する。
- 未選択・1度だけ拒否
- 許可済み
- 拒否
未選択・1度だけ拒否
ユーザーはアプリで位置情報を使用できるかどうかを選択していない。
または、アプリで位置情報を使用を許可していない。位置情報取得の確認ダイアログをまだ表示したことがないのがこの状態。
または、位置情報取得の確認ダイアログで拒否を選択したのがこの状態。
- Androidでは、この状態で PermissionChecker.checkSelfPermission を呼ぶと、 PackageManager.PERMISSION_DENIED(未許可)が返ってきます。
- Androidでは、この状態で Activity.requestPermissions を呼ぶと、位置情報取得の確認ダイアログが表示されます。
許可済み
ユーザーは位置情報サービス使用することをアプリに許可した。
位置情報取得の確認ダイアログで許可を選択したのがこの状態。
- Androidでは、この状態で PermissionChecker.checkSelfPermission を呼ぶと、 PackageManager.PERMISSION_GRANTED (許可済み)が返ってきます。
拒否
アプリで位置情報を使用を許可していない。
位置情報取得の確認ダイアログで「今後表示しない」を選択したのがこの状態。
- Androidでは、この状態で PermissionChecker.checkSelfPermission を呼ぶと、 PackageManager.PERMISSION_DENIED(未許可)が返ってきます。
- Androidでは、この状態で Activity.requestPermissions を呼ぶと、即座に Activity. onRequestPermissionsResult にコールバックが返ってきます。
Android 9での位置情報取得の確認ダイアログで「今後表示しない」のチェックが存在するもの
位置情報取得の許可ごとの挙動について
LocationService.isEnabledByUser
LocationService.isEnabledByUser
ユーザーが位置情報サービスを有効にするかどうか。iOS
「設定 > プライバシー > 位置情報サービス」で位置情報サービスをオフにした場合にfalseが返る。
位置情報の許可の有無とは関係なさそう。
状態 LocationService.isEnabledByUserの返値 notDetermined true restricted false denied true authorizedAlways true authorizedWhenInUse true Android
状態 LocationService.isEnabledByUserの返値 未選択・1度だけ拒否 false 許可済み true 拒否 false LocationService.Start
LocationService.Start
位置情報サービスの更新を開始します。
LocationService.Start
を呼び出し後、LocationService.statusがLocationServiceStatus.Runningになったら、LocationService.lastDataより位置情報を取得できます。iOS
状態 LocationService.Start呼び出し後の動作 notDetermined 位置情報の取得の確認ダイアログが表示される。 restricted "位置情報を利用できるようにするには、位置情報をサービスをオンにしてください"というダイアログが表示される。LocationService.statusは Failed
になる。denied LocationService.statusは Failed
になる。authorizedAlways LocationService.statusは Running
になる。authorizedWhenInUse LocationService.statusは Running
になる。位置情報の取得の確認ダイアログで許可を選択した場合に、
LocationService.status
はRunning
となる。"位置情報を利用できるようにするには、位置情報をサービスをオンにしてください"のダイアログ
Android
状態 LocationService.Start呼び出し後の動作 未選択・1度だけ拒否 位置情報の取得の確認ダイアログが表示される。LocationService.statusは Stopped
のままで、許可を選択するとLocationService.isEnabledByUser
はtrueになる。許可済み LocationService.statusは Running
になる。拒否 LocationService.statusは Stopped
になる。位置情報の取得の確認ダイアログで許可を選択しても、
LocationService.isEnabledByUser
はtrueになるがLocationService.status
の状態に変化はない。
位置情報を取得する場合はもう一度LocationService.Start
を呼ぶ必要がありそう。LocationService.Stop
LocationService.Stop
位置情報サービスの更新を停止します。iOS/Android
LocationService.status
がStopped
になります。
LocationService.lastData
の値が更新されなくなります。まとめ
- iOSは「設定 > プライバシー > 位置情報サービス」がオンかオフかは
LocationService.isEnabledByUser
を見れば分かる- iOSはアプリの位置情報取得が許可されているかどうかはあらかじめ分からない。
LocationService.Start
を呼んだ挙動で判定するしかなさそう。iOSアプリは位置情報取得の許可ダイアログが表示されるかどうかはあらかじめ分からない。
LocationService.Start
を呼んだときにOSにより位置情報取得の許可ダイアログが表示される。Androidはアプリの位置情報取得が許可されているかどうかは
LocationService.isEnabledByUser
を見れば分かるAndroidアプリは位置情報取得の許可が無い場合(
LocationService.isEnabledByUser
がfalseの場合)に、位置情報取得の許可ダイアログが表示されるかどうかはあらかじめ分からない。LocationService.Start
を呼んだときにOSにより位置情報取得の許可ダイアログが表示される。位置情報が取得できるかどうかをiOSとAndroidの両方に対応しようとすると、
LocationService.Start
を呼んだ上でLocationService.status
の値がどうなるかを監視するくらししかなさそうです。コード
https://github.com/yhirano/UnityLocationServiceResearch
参考
- 投稿日:2019-10-09T08:26:50+09:00
Unity AddressableAssetSystemの使用方法
はじめに
実装したソースはこちら
https://github.com/zi-su/ScriptLibrary/tree/master/EditorUnityではアセット管理としてAssetBundleがあります。
このAssetBundleを使い膨大なアセットをまとめてアセット管理を行ってきました。
そのためにそれぞれAssetBundleManagerクラスを作成していたと思います。UnityがAssetBundleManagerを提供していましたが現在ではサポートされておりません。
https://bitbucket.org/Unity-Technologies/assetbundledemo/src/default/
AssetBundleクラス自体は低レベルなクラスであり、実際のゲーム開発で使いやすくするために拡張が必要です。
オレオレAssetBundleManagerを作り出すと参照カウント付きクラスで隠蔽したり、依存バンドルを調べてロード・アンロード処理を書いたりすることが必要です。こういった面倒な実装とAssetBundleの仕組みをもっと楽にしようということでAddressableAssetSystem(AAS)が作られました。
https://blogs.unity3d.com/jp/2019/07/15/addressable-asset-system/
Unity2018.3以降では使用可能ということです。
このAddressableAssetSystemの使い方、機能、ゲーム開発に使えるのかを調べていきます。使用したバージョン
Addressables ver1.2.4
Unity 2019.3.0b4AddressableAssetSystemとは
公式ドキュメント
まずは公式ドキュメントです。
一次ソースを調べることは何より重要です。
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/manual/index.html
UniteTokyo2018の講演
https://learning.unity3d.jp/355/GettingStartedを読めば最低限の導入まではできます。
1. PackageManagerからAddressablesをインストール
2. 初期化ウィンドウが出るので初期化
3. 各アセットのインスペクタでアドレスを指定
4. Window->AssetManagement->Addressablesを開く
5. 各アセットをグループに分ける
6. BuildからBuildPlayerContentでアセットバンドルを作成GettingStartedだけではロード処理しか書いていないのでこのままではメモリに残り続けます
ReleaseやメモリについてはMemoryManagementを読みます。
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/manual/MemoryManagement.html実際に使用する
AASをゲーム開発で使用するケースを考えます。
マニュアルやスライドを見ているとAASの各種設定は
Window->AssetManagement->Addressablesのメニューから行っています。
GUI上でグループを作成しアセットをグループへドラッグアンドドロップすることはとてもわかりやすいです。サンプルで数十ファイルの間は。膨大なアセット数
ゲームに使用するアセットは軽く数百を超えていき、数万アセットにもなることがあります。
数万を超えるアセット数に対してこの手順は人間がするものではありません多くの場合アセットを保存しているルートディレクトリからのパスでグループ化しフォルダ内のアセットはそのグループに属するといった設定になるでしょう。
アセットインポート時にグループの作成とグループへの追加を実装する方法がないか、APIドキュメントを読んで探します
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/api/index.htmlAddressableAssetSettings
最初にAddressablesメニューを開くときに作成されたAddressableAssetSettings.assetを選択したときのインスペクタを見ます。名前からしてAASに関する設定を持っていそうです。
Groupsを開くと自分で作成したグループが追加されていることがわかります。
他にもいろいろな設定があります。
インスペクタ上で歯車をクリックするとEditScriptが表示されるのでスクリプトを確認するとScriptableObjectであることがわかります。
APIドキュメントを見るとグループの追加やアセットの登録に必要な機能があることがわかります。(CreateGroupやCreateOrMoveEntry)
このScriptableObjectを取得してきます。
//アドレサブルアセットセッティング取得
var s = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEditor.AddressableAssets.Settings.AddressableAssetSettings>(
"Assets/AddressableAssetsData/AddressableAssetSettings.asset"
);
グループ作成の自動化
取得してきたAddressableAssetSettingsスクリプトを使用してグループ作成をします。
APIはCreateGroupを使用します。
APIドキュメントを見て引数を調べます。
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/api/UnityEditor.AddressableAssets.Settings.AddressableAssetSettings.html#UnityEditor_AddressableAssets_Settings_AddressableAssetSettings_CreateGroup_System_String_System_Boolean_System_Boolean_System_Boolean_System_Collections_Generic_List_UnityEditor_AddressableAssets_Settings_AddressableAssetGroupSchema__System_Type___
変わった引数でschemasToCopyがあります。
何を設定するのか迷いますがAddressablesメニューのDefaultLocalGroupと同じ設定にするには
//スキーマ生成
List<UnityEditor.AddressableAssets.Settings.AddressableAssetGroupSchema> schema = new List<UnityEditor.AddressableAssets.Settings.AddressableAssetGroupSchema>() {
new UnityEditor.AddressableAssets.Settings.GroupSchemas.BundledAssetGroupSchema(),
new UnityEditor.AddressableAssets.Settings.GroupSchemas.ContentUpdateGroupSchema()
};
というリストを指定しますアセットをグループへ追加・削除
各アセットを作成したグループへ追加しなければアセットバンドルに含まれません。
APIはCreateOrMoveEntryを使用します。
APIドキュメントを見て引数を調べます。
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/api/UnityEditor.AddressableAssets.Settings.AddressableAssetSettings.html#UnityEditor_AddressableAssets_Settings_AddressableAssetSettings_CreateOrMoveEntry_System_String_UnityEditor_AddressableAssets_Settings_AddressableAssetGroup_System_Boolean_System_Boolean_
guidとtargetParentでアセットのGUIDとグループを指定するだけで良さそうです。
guidはAssetPathToGUIDで取得できます
//アセットGUIDを取得
var assetGuid = UnityEditor.AssetDatabase.AssetPathToGUID("Assets/Data/hogeMat.mat");
自動ビルド
UnityEditor.AddressableAssets.Settings.AddressableAssetSettings.BuildPlayerContent();
を呼ぶだけでビルドしてくれます。
アセットバンドルビルドスクリプトを自作していた時のことを思い出すとこれだけで感動します。おわりに
AddressableAssetSystemはゲーム開発に使用する機能も揃っているようです。
AssetBundleManagerを使用してビルドスクリプトを自作してといった旧時代の遺物は捨て去り、Unity2018.3以降はAddressableAssetSystemを使用していきましょう。
どんどん使用されていき知見が溜まっていくことを期待してます。
- 投稿日:2019-10-09T08:26:50+09:00
Unity AddressableAssetSystemの使用方法と自動化の機能調査
はじめに
実装したソースはこちら
https://github.com/zi-su/ScriptLibrary/tree/master/EditorUnityではアセット管理としてAssetBundleがあります。
このAssetBundleを使い膨大なアセットをまとめてアセット管理を行ってきました。
そのためにそれぞれAssetBundleManagerクラスを作成していたと思います。UnityがAssetBundleManagerを提供していましたが現在ではサポートされておりません。
https://bitbucket.org/Unity-Technologies/assetbundledemo/src/default/
AssetBundleクラス自体は低レベルなクラスであり、実際のゲーム開発で使いやすくするために拡張が必要です。
オレオレAssetBundleManagerを作り出すと参照カウント付きクラスで隠蔽したり、依存バンドルを調べてロード・アンロード処理を書いたりすることが必要です。こういった面倒な実装とAssetBundleの仕組みをもっと楽にしようということでAddressableAssetSystem(AAS)が作られました。
https://blogs.unity3d.com/jp/2019/07/15/addressable-asset-system/
Unity2018.3以降では使用可能ということです。
このAddressableAssetSystemの使い方、機能、ゲーム開発に使えるのかを調べていきます。使用したバージョン
Addressables ver1.2.4
Unity 2019.3.0b4AddressableAssetSystemとは
公式ドキュメント
まずは公式ドキュメントです。
一次ソースを調べることは何より重要です。
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/manual/index.html
UniteTokyo2018の講演
https://learning.unity3d.jp/355/GettingStartedを読めば最低限の導入まではできます。
1. PackageManagerからAddressablesをインストール
2. 初期化ウィンドウが出るので初期化
3. 各アセットのインスペクタでアドレスを指定
4. Window->AssetManagement->Addressablesを開く
5. 各アセットをグループに分ける
6. BuildからBuildPlayerContentでアセットバンドルを作成GettingStartedだけではロード処理しか書いていないのでこのままではメモリに残り続けます
ReleaseやメモリについてはMemoryManagementを読みます。
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/manual/MemoryManagement.html実際に使用する
AASをゲーム開発で使用するケースを考えます。
マニュアルやスライドを見ているとAASの各種設定は
Window->AssetManagement->Addressablesのメニューから行っています。
GUI上でグループを作成しアセットをグループへドラッグアンドドロップすることはとてもわかりやすいです。サンプルで数十ファイルの間は。膨大なアセット数
ゲームに使用するアセットは軽く数百を超えていき、数万アセットにもなることがあります。
数万を超えるアセット数に対してこの手順は人間がするものではありません多くの場合アセットを保存しているルートディレクトリからのパスでグループ化しフォルダ内のアセットはそのグループに属するといった設定になるでしょう。
アセットインポート時にグループの作成とグループへの追加を実装する方法がないか、APIドキュメントを読んで探します
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/api/index.htmlAddressableAssetSettings
最初にAddressablesメニューを開くときに作成されたAddressableAssetSettings.assetを選択したときのインスペクタを見ます。名前からしてAASに関する設定を持っていそうです。
Groupsを開くと自分で作成したグループが追加されていることがわかります。
他にもいろいろな設定があります。
インスペクタ上で歯車をクリックするとEditScriptが表示されるのでスクリプトを確認するとScriptableObjectであることがわかります。
APIドキュメントを見るとグループの追加やアセットの登録に必要な機能があることがわかります。(CreateGroupやCreateOrMoveEntry)
このScriptableObjectを取得してきます。
//アドレサブルアセットセッティング取得
var s = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEditor.AddressableAssets.Settings.AddressableAssetSettings>(
"Assets/AddressableAssetsData/AddressableAssetSettings.asset"
);
グループ作成の自動化
取得してきたAddressableAssetSettingsスクリプトを使用してグループ作成をします。
APIはCreateGroupを使用します。
APIドキュメントを見て引数を調べます。
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/api/UnityEditor.AddressableAssets.Settings.AddressableAssetSettings.html#UnityEditor_AddressableAssets_Settings_AddressableAssetSettings_CreateGroup_System_String_System_Boolean_System_Boolean_System_Boolean_System_Collections_Generic_List_UnityEditor_AddressableAssets_Settings_AddressableAssetGroupSchema__System_Type___
変わった引数でschemasToCopyがあります。
何を設定するのか迷いますがAddressablesメニューのDefaultLocalGroupと同じ設定にするには
//スキーマ生成
List<UnityEditor.AddressableAssets.Settings.AddressableAssetGroupSchema> schema = new List<UnityEditor.AddressableAssets.Settings.AddressableAssetGroupSchema>() {
new UnityEditor.AddressableAssets.Settings.GroupSchemas.BundledAssetGroupSchema(),
new UnityEditor.AddressableAssets.Settings.GroupSchemas.ContentUpdateGroupSchema()
};
というリストを指定しますアセットをグループへ追加・削除
各アセットを作成したグループへ追加しなければアセットバンドルに含まれません。
APIはCreateOrMoveEntryを使用します。
APIドキュメントを見て引数を調べます。
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/api/UnityEditor.AddressableAssets.Settings.AddressableAssetSettings.html#UnityEditor_AddressableAssets_Settings_AddressableAssetSettings_CreateOrMoveEntry_System_String_UnityEditor_AddressableAssets_Settings_AddressableAssetGroup_System_Boolean_System_Boolean_
guidとtargetParentでアセットのGUIDとグループを指定するだけで良さそうです。
guidはAssetPathToGUIDで取得できます
//アセットGUIDを取得
var assetGuid = UnityEditor.AssetDatabase.AssetPathToGUID("Assets/Data/hogeMat.mat");
自動ビルド
UnityEditor.AddressableAssets.Settings.AddressableAssetSettings.BuildPlayerContent();
を呼ぶだけでビルドしてくれます。
アセットバンドルビルドスクリプトを自作していた時のことを思い出すとこれだけで感動します。おわりに
AddressableAssetSystemはゲーム開発に使用する機能も揃っているようです。
AssetBundleManagerを使用してビルドスクリプトを自作してといった旧時代の遺物は捨て去り、Unity2018.3以降はAddressableAssetSystemを使用していきましょう。
どんどん使用されていき知見が溜まっていくことを期待してます。
- 投稿日:2019-10-09T08:26:50+09:00
Unity Addressable Asset Systemの使用方法と自動化の機能調査
はじめに
実装したソースはこちら
https://github.com/zi-su/ScriptLibrary/tree/master/Editor
AASUtility.csにまとめています。Unityではアセット管理としてAssetBundleがあります。
このAssetBundleを使い膨大なアセットをまとめてアセット管理を行ってきました。
そのためにそれぞれAssetBundleManagerクラスを作成していたと思います。UnityがAssetBundleManagerを提供していましたが現在ではサポートされておりません。
https://bitbucket.org/Unity-Technologies/assetbundledemo/src/default/
AssetBundleクラス自体は低レベルなクラスであり、実際のゲーム開発で使いやすくするために拡張が必要です。
オレオレAssetBundleManagerを作り出すと参照カウント付きクラスで隠蔽したり、依存バンドルを調べてロード・アンロード処理を書いたりすることが必要です。こういった面倒な実装とAssetBundleの仕組みをもっと楽にしようということでAddressableAssetSystem(AAS)が作られました。
https://blogs.unity3d.com/jp/2019/07/15/addressable-asset-system/
Unity2018.3以降では使用可能ということです。
このAddressableAssetSystemの使い方、機能、ゲーム開発に使えるのかを調べていきます。使用したバージョン
Addressables ver1.2.4
Unity 2019.3.0b4AddressableAssetSystemとは
公式ドキュメント
まずは公式ドキュメントです。
一次ソースを調べることは何より重要です。
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/manual/index.html
UniteTokyo2018の講演
https://learning.unity3d.jp/355/GettingStartedを読めば最低限の導入まではできます。
1. PackageManagerからAddressablesをインストール
2. 初期化ウィンドウが出るので初期化
3. 各アセットのインスペクタでアドレスを指定
4. Window->AssetManagement->Addressablesを開く
5. 各アセットをグループに分ける
6. BuildからBuildPlayerContentでアセットバンドルを作成GettingStartedだけではロード処理しか書いていないのでこのままではメモリに残り続けます
ReleaseやメモリについてはMemoryManagementを読みます。
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/manual/MemoryManagement.html実際に使用する
AASをゲーム開発で使用するケースを考えます。
マニュアルやスライドを見ているとAASの各種設定は
Window->AssetManagement->Addressablesのメニューから行っています。
GUI上でグループを作成しアセットをグループへドラッグアンドドロップすることはとてもわかりやすいです。サンプルで数十ファイルの間は。膨大なアセット数
ゲームに使用するアセットは軽く数百を超えていき、数万アセットにもなることがあります。
数万を超えるアセット数に対してこの手順は人間がするものではありません多くの場合アセットを保存しているルートディレクトリからのパスでグループ化しフォルダ内のアセットはそのグループに属するといった設定になるでしょう。
アセットインポート時にグループの作成とグループへの追加を実装する方法がないか、APIドキュメントを読んで探します
https://docs.unity3d.com/Packages/com.unity.addressables@1.2/api/index.htmlAddressableAssetSettings
最初にAddressablesメニューを開くときに作成されたAddressableAssetSettings.assetを選択したときのインスペクタを見ます。
名前からしてAASに関する設定を持っていそうです。
Groupsを開くと自分で作成したグループが追加されていることがわかります。
他にもいろいろな設定があります。
インスペクタ上で歯車をクリックするとEditScriptが表示されるのでスクリプトを確認するとScriptableObjectであることがわかります。
APIドキュメントを見るとグループの追加やアセットの登録に必要な機能があることがわかります。(CreateGroupやCreateOrMoveEntry)
AddressableAssetSettings
このScriptableObjectを取得してきます。//アドレサブルアセットセッティング取得 var s = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEditor.AddressableAssets.Settings.AddressableAssetSettings>( "Assets/AddressableAssetsData/AddressableAssetSettings.asset" );グループ作成の自動化
取得してきたAddressableAssetSettingsスクリプトを使用してグループ作成をします。
APIは CreateGroup を使用します。
APIドキュメントを見て引数を調べます。
CreateGroup
変わった引数でschemasToCopyがあります。
何を設定するのか迷いますがAddressablesメニューのDefaultLocalGroupと同じ設定にするには//スキーマ生成 List<UnityEditor.AddressableAssets.Settings.AddressableAssetGroupSchema> schema = new List<UnityEditor.AddressableAssets.Settings.AddressableAssetGroupSchema>() { new UnityEditor.AddressableAssets.Settings.GroupSchemas.BundledAssetGroupSchema(), new UnityEditor.AddressableAssets.Settings.GroupSchemas.ContentUpdateGroupSchema() };というリストを指定します。
初期状態のグループが
AASUtility.csのCreateGroupメソッドを呼べば
CreatedGroupというグループが作成されました。アセットをグループへ追加・削除
各アセットを作成したグループへ追加しなければアセットバンドルに含まれません。
APIはCreateOrMoveEntryを使用します。
APIドキュメントを見て引数を調べます。
CreateOrMoveEntry
guidとtargetParentでアセットのGUIDとグループを指定するだけで良さそうです。
guidはAssetPathToGUIDで取得できます//アセットGUIDを取得 var assetGuid = UnityEditor.AssetDatabase.AssetPathToGUID("Assets/Data/hogeMat.mat");AASUtility.csのAddAssetToGroupメソッドを呼べば
グループにアセットが追加されました。アセットにラベルを指定
複数のアセットを一括でロードする機能としてラベルがあります。
ゲームの一ステージを構成するアセットをステージ遷移が発生する前に先読みしておきシームレスに見せるといった時に使えそうな機能です。
このラベルを設定するAPIを調べます。
AddressableAssetEntry.labelsが該当します。
APIドキュメントを見てセット関数を調べます。
SetLabel
AddressableAssetEntryを取得してSetLabels関数を使用することで設定できそうです。AddressableAssetEntryを取得する方法を調べます。
AddressableAssetSettingsにGetAllAssetsという関数があります。
APIドキュメントを調べます。
GetAllAssets
第一引数のリストに設定されてる全アセットを返してくれることがわかります。
アセット数が数万になりリストが膨大になる場合Filterの引数で絞れそうです。これで取得したリストの中からラベルをセットしたいアセットのassetGUIDを検索し取得したAddressableAssetEntryのSetLabelを呼べば設定完了です。
static void SetLabelToAsset(List<string> assetGuidList, string label, bool flag) { var s = GetSettings(); //ラベルを追加するように呼んでおく。追加されていないと設定されない。 s.AddLabel(label); List<UnityEditor.AddressableAssets.Settings.AddressableAssetEntry> assetList = new List<UnityEditor.AddressableAssets.Settings.AddressableAssetEntry>(); s.GetAllAssets(assetList, true); foreach (var assetGuid in assetGuidList) { var asset = assetList.Find((a) => { return a.guid == assetGuid; }); if(asset != null) { asset.SetLabel(label, flag); } } }自動ビルド
UnityEditor.AddressableAssets.Settings.AddressableAssetSettings.BuildPlayerContent();
を呼ぶだけでビルドしてくれます。
アセットバンドルビルドスクリプトを自作していた時のことを思い出すとこれだけで感動します。おわりに
AddressableAssetSystemはゲーム開発に使用する機能も揃っているようです。
AssetBundleManagerを使用してビルドスクリプトを自作してといった旧時代の遺物は捨て去り、Unity2018.3以降はAddressableAssetSystemを使用していきましょう。
どんどん使用されていき知見が溜まっていくことを期待してます。