- 投稿日:2022-01-31T22:50:13+09:00
【Unity】リソースデータ(アセット)読み込みについてまとめてみた
リソースデータについて Unity プロジェクトに「画像」「3Dモデル」「音声」「動画」など、ファイルサイズが大きいアセットが含まれる ユーザーに届ける方法は大きく分けると2つ 全アセットをビルドに含める DLC(ダウンロードコンテンツ)としてゲーム内(アプリ内)でダウンロードさせる Resources 旧来の Unity 開発で頻繁に利用されていたアセットの動的読み込みを行うための仕組み Resources という名前がついたフォルダは、ビルド時にアプリのバイナリに同梱される Resources.Load("path/to/asset") といったAPIから読み込みが行える 現在は非推奨 メモリ管理が難しくなる アプリの起動時間が長くなる リソースを特定のプラットフォームにのみ配信するなどの対応ができない Resources を使ってもよいケース プロトタイプ開発時 アプリが立ち上がっている間常駐するリソース メモリをあまり使わない場合 プラットフォーム間でリソースを切り替える必要がない場合 StreamingAssets アセットを変換しないでそのままアプリに持っていく仕組み バイナリとして保存するのでデシリアライズが必要 プラットフォームごとに配置されるフォルダは異なり、 Application.streamingAssetsPath で取得できる Unity Editor、Windows、Linux、PS4、Xbox、Switch は Application.dataPath + "/StreamingAssets" macOS は Application.dataPath + "/Resources/Data/StreamingAssets" iOS は Application.dataPath + "/Raw" Android は圧縮された APK/JAR ファイル "jar:file://" + Application.dataPath + "!/assets" Android の場合は UnityWeRequest を使ってロードする StreamingAssets を使ってもよいケース ビルド済みの AssetBundle を格納する AssetBundle は変更しなければビルドし直し不要のため、ビルド時間の削減 ビルド前処理に buildTarget に指定されたプラットフォームの AssetBundle のみを StreamingAssets に配置する必要がある プラットフォームごとに変換が不要なアセットの読み込み AssetBundle Import済アセットのバイナリデータを固めたモノ DLCとしてダウンロードすることで、ビルドに含まれないリソースを追加読み込みできる AssetBundle として使えるアセットは 画像 オーディオファイル フォント Scene Prefab フォルダ C#スクリプトを固めることはできない 通常の AssetBundle と Streamed AssetBundle に分類できる 通常の AssetBundle Scene を除く任意の Asset を固めた AssetBundle のこと 1つ以上の Asset が固められたバイナリデータをファイルとして出力したもの 内部的には Lz4 などの圧縮アルゴリズムを用いて圧縮されたファイル Streamed AssetBundle Scene そのものを AssetBundle として固めたもの Scene 内の GameObject から参照されているアセットも一緒に固められる 圧縮などの仕組みは通常の AssetBundle と変わらない AssetBundle を Load した時点で SceneManager からアクセス可能になる AssetBundle でできること DLC としてアセットを動的ロードする バリエーションを持たせる 複数のプラットフォーム、国、地域に配信するときなど、リソースデータにバリエーションをもたせたい AssetBundle Variants 機能を使う 任意の粒度でまとめる 設定した AssetBundle Name 単位でグルーピングされる APIを叩いてグルーピング可能 依存関係を構築する Addressable Asset System アドレスを指定することでリソースデータをロードできる機能 アドレスは Asset ごとに付けることができる任意の名前 ローカルのデータか、リモートから AssetBundle をロードするか設定ひとつで変更できる 呼び出し側は同じインターフェースでロードできる 使い方 Unity2019.3以上ならば Package Manager から Addressables をインストールすることで使用可能 Window > Asset Management > Addressables > Settings を選択すると。 AddressableAssetsData フォルダが作成される Addressable にチェックを入れることで、Addressable の管理対象になる Addressables Group に追加される フォルダ構成 アセット 内容 AddressableAssetSettings.asset ・プロジェクトのAddressableの設定が保存されている AssetGroups/ ・Groupに属しているアセットのGUIDやLabel情報などを管理 AssetGroups/Built In Data.asset ・Resources や Scene in Buildに関わる情報を管理 AssetGroups/Default Local Group.asset ・Playerビルドに含めるアセットを管理・初期状態に作成される Schemas/ ・Groupの詳細な設定を管理・GroupごとにSchemasが配置される AssetGroupTemplates/ ・Groupの新規作成時につかうテンプレ・新規でGroup Templeteを作成したときは AddressableAssetSettings に追加しなければならない DataBuilders/ ・ビルド、エディタ再生時に使用される設定・AssetBundleのビルド方法を定義したScriptableObjectが配置される DefaultObject.asset ・AddressableAssetSettings.assetの場所を示すScriptableObject ※ DataBuilders や AssetGroupTemples はあまり編集しない AssetBundle をビルドする 新規の場合h AddressableGroups で、 Build > New Build > Default Build Script を選択する すでにビルド済みの AssetBundle を更新する場合は Update a Previous Build Build される場所は以下で設定できる LoadBuildPath: Library/com.unity.addressables/[BuildTarget](デフォルト) Playerビルド時に一時的に StreamingAssets にコピーされることで Player ビルドに同梱される RemoteBuildPath: ServerData/[BuildTarget](デフォルト) プロジェクトルート直下に作成される ServerData 以下に作成された AssetBundle を RemoteLoadPath のURLに対応するようにアップロードする必要がある AssetBundle を読み込む 通常はアプリ起動時に自動的に Addressable の初期化処理が実行される 何らかの理由でスクリプトから初期化、実体化したい場合は Addressables.LoadAssetAsync() してから Instantiate() する 直接 Addressables.InstantiateAsync() する // Load してから Instatiate() var gameobject = await Addressables.LoadAssetAsync<GameObject>("Assets/Prefabs/Cube.prefab"); var obj = Instantiate(go); // 直接 Instatiate() Addressables.LoadAssetAsync<GameObject>("Assets/Prefabs/Cube.prefab"); 参考文献
- 投稿日:2022-01-31T22:50:13+09:00
【Unity】リソースデータ (Resources/StreamingAssets/AssetBundle) 読み込みについてまとめてみた
リソースデータについて Unity プロジェクトに「画像」「3Dモデル」「音声」「動画」など、ファイルサイズが大きいアセットが含まれる ユーザーに届ける方法は大きく分けると2つ 全アセットをビルドに含める DLC(ダウンロードコンテンツ)としてゲーム内(アプリ内)でダウンロードさせる Resources 旧来の Unity 開発で頻繁に利用されていたアセットの動的読み込みを行うための仕組み Resources という名前がついたフォルダは、ビルド時にアプリのバイナリに同梱される Resources.Load("path/to/asset") といったAPIから読み込みが行える 現在は非推奨 メモリ管理が難しくなる アプリの起動時間が長くなる リソースを特定のプラットフォームにのみ配信するなどの対応ができない Resources を使ってもよいケース プロトタイプ開発時 アプリが立ち上がっている間常駐するリソース メモリをあまり使わない場合 プラットフォーム間でリソースを切り替える必要がない場合 StreamingAssets アセットを変換しないでそのままアプリに持っていく仕組み バイナリとして保存するのでデシリアライズが必要 プラットフォームごとに配置されるフォルダは異なり、 Application.streamingAssetsPath で取得できる Unity Editor、Windows、Linux、PS4、Xbox、Switch は Application.dataPath + "/StreamingAssets" macOS は Application.dataPath + "/Resources/Data/StreamingAssets" iOS は Application.dataPath + "/Raw" Android は圧縮された APK/JAR ファイル "jar:file://" + Application.dataPath + "!/assets" Android の場合は UnityWeRequest を使ってロードする StreamingAssets を使ってもよいケース ビルド済みの AssetBundle を格納する AssetBundle は変更しなければビルドし直し不要のため、ビルド時間の削減 ビルド前処理に buildTarget に指定されたプラットフォームの AssetBundle のみを StreamingAssets に配置する必要がある プラットフォームごとに変換が不要なアセットの読み込み AssetBundle Import済アセットのバイナリデータを固めたモノ DLCとしてダウンロードすることで、ビルドに含まれないリソースを追加読み込みできる AssetBundle として使えるアセットは 画像 オーディオファイル フォント Scene Prefab フォルダ C#スクリプトを固めることはできない 通常の AssetBundle と Streamed AssetBundle に分類できる 通常の AssetBundle Scene を除く任意の Asset を固めた AssetBundle のこと 1つ以上の Asset が固められたバイナリデータをファイルとして出力したもの 内部的には Lz4 などの圧縮アルゴリズムを用いて圧縮されたファイル Streamed AssetBundle Scene そのものを AssetBundle として固めたもの Scene 内の GameObject から参照されているアセットも一緒に固められる 圧縮などの仕組みは通常の AssetBundle と変わらない AssetBundle を Load した時点で SceneManager からアクセス可能になる AssetBundle でできること DLC としてアセットを動的ロードする バリエーションを持たせる 複数のプラットフォーム、国、地域に配信するときなど、リソースデータにバリエーションをもたせたい AssetBundle Variants 機能を使う 任意の粒度でまとめる 設定した AssetBundle Name 単位でグルーピングされる APIを叩いてグルーピング可能 依存関係を構築する Addressable Asset System アドレスを指定することでリソースデータをロードできる機能 アドレスは Asset ごとに付けることができる任意の名前 ローカルのデータか、リモートから AssetBundle をロードするか設定ひとつで変更できる 呼び出し側は同じインターフェースでロードできる 使い方 Unity2019.3以上ならば Package Manager から Addressables をインストールすることで使用可能 Window > Asset Management > Addressables > Settings を選択すると。 AddressableAssetsData フォルダが作成される Addressable にチェックを入れることで、Addressable の管理対象になる Addressables Group に追加される フォルダ構成 アセット 内容 AddressableAssetSettings.asset ・プロジェクトのAddressableの設定が保存されている AssetGroups/ ・Groupに属しているアセットのGUIDやLabel情報などを管理 AssetGroups/Built In Data.asset ・Resources や Scene in Buildに関わる情報を管理 AssetGroups/Default Local Group.asset ・Playerビルドに含めるアセットを管理・初期状態に作成される Schemas/ ・Groupの詳細な設定を管理・GroupごとにSchemasが配置される AssetGroupTemplates/ ・Groupの新規作成時につかうテンプレ・新規でGroup Templeteを作成したときは AddressableAssetSettings に追加しなければならない DataBuilders/ ・ビルド、エディタ再生時に使用される設定・AssetBundleのビルド方法を定義したScriptableObjectが配置される DefaultObject.asset ・AddressableAssetSettings.assetの場所を示すScriptableObject ※ DataBuilders や AssetGroupTemples はあまり編集しない AssetBundle をビルドする 新規の場合h AddressableGroups で、 Build > New Build > Default Build Script を選択する すでにビルド済みの AssetBundle を更新する場合は Update a Previous Build Build される場所は以下で設定できる LoadBuildPath: Library/com.unity.addressables/[BuildTarget](デフォルト) Playerビルド時に一時的に StreamingAssets にコピーされることで Player ビルドに同梱される RemoteBuildPath: ServerData/[BuildTarget](デフォルト) プロジェクトルート直下に作成される ServerData 以下に作成された AssetBundle を RemoteLoadPath のURLに対応するようにアップロードする必要がある AssetBundle を読み込む 通常はアプリ起動時に自動的に Addressable の初期化処理が実行される 何らかの理由でスクリプトから初期化、実体化したい場合は Addressables.LoadAssetAsync() してから Instantiate() する 直接 Addressables.InstantiateAsync() する // Load してから Instatiate() var gameobject = await Addressables.LoadAssetAsync<GameObject>("Assets/Prefabs/Cube.prefab"); var obj = Instantiate(go); // 直接 Instatiate() Addressables.LoadAssetAsync<GameObject>("Assets/Prefabs/Cube.prefab"); 参考文献
- 投稿日:2022-01-31T16:31:57+09:00
Oculus Integration で Firebase Analytics と Crashlytics を設定する
はじめに Oculus アプリで Firebase Analytics と Crashlytics を実装したので、備忘録としてまとめました。 Firebase とは アプリを開発の際に、ユーザーベースを拡大、収益を高めるためのツールです。Firebaseを使えば、インフラ構築に手間取ることなくビジネスを収益化し、効率よくアプリを開発し、運用・管理することができるようになります。 スマホアプリでの実装 Flutter アプリに Firebase を追加する FlutterとFirebaseでログイン画面を実装する 事前準備 Oculus Integration Firebase のアカウント 詳細 : Analytics / Crashlytics 実装 Firebaseをインストールする "UnityプロジェクトにFirebaseを追加する" の記事に記載されているステップ1〜4に従って実装します。 ※ ステップ5はサンプルコードに含まれているため、必須ではありません。 ステップ 1: Firebase プロジェクトを作成する ステップ 2: アプリを Firebase に登録する ステップ 3: Firebase 構成ファイルを追加する ステップ 4: Firebase Unity SDK を追加する ダウンロードした firebase_unity_sdkから、dotnet4 / FirebaseAnalytics.unitypackageと dotnet4 / FirebaseCrashlytics.unitypackageをインポートします。 Firebase Unity SDK は こちら からもダウンロードできます。 AndroidAuto-Resolver が有効でない場合、必ず有効に設定します。 Assets > Play Serveces Resolver > Android Resolver -> Settings テンプレート google-services.jsonを独自のものに置き換えます。 テンプレートは下記の場所に保存されているので上書きします。 プロジェクトコードを有効にする Firebase Analytics と Crashlytics がプロジェクトに追加されたら、Oculusメニューからサンプルコードを有効にします: Oculus> Samples> Firebase> Enable Firebase Sample 'unsafe'を許可する クラッシュを強制する的に発生させるために、Crashlyticsサンプルでは C#の unsafeキーワードを使用しています。これはデフォルトでは禁止されているのでunityで設定して動作できるようにする必要があります。unsafeキーワードは、プレーヤーの設定で有効にする事ができます。 : Edit > Project Settings... > Player > Android settings > Allow 'unsafe' code ビルドして実行 この時点で、サンプルシーンを開いて、いくつかのイベントとクラッシュをトリガーできるはずです。レポートは、Firebaseコンソール で確認できます。 自分の作成したアプリへも、 StartCrashlytics.cs を使用するだけで簡単にクラッシュを解析する事ができます。 symbols.zip ファイルをFirebaseにアップロードする Scripting Backend を IL2CPP に設定してビルドし、symbols.zip を作成して Firebase にアップロードするとより詳細なクラッシュ報告を確認することが出来ます。 Firebase CLI コマンドを実行して、生成した Crashlytics 互換のシンボル ファイルを Firebase サーバーにアップロードします。 firebase crashlytics:symbols:upload --app=FIREBASE_APP_ID PATH/TO/SYMBOLS FIREBASE_APP_ID: Firebase Android アプリ ID(パッケージ名ではありません) Firebase Android アプリ ID の例: 1:567383003300:android:17104a2ced0c9b9b Firebase アプリ ID を確認する方法 google-services.json の mobilesdk_app_id に記載されています。 Unity 内で直接 APK をビルドした場合: PATH/TO/SYMBOLS は、ビルドが完了したときにプロジェクトのルート ディレクトリに生成される、圧縮されたシンボル ファイルのパスです(例: myproject/myapp-1.0-v100.symbols.zip )。 最後に、強制的にテスト クラッシュを発生させて Crashlytics の設定を完了し、Firebase コンソールの Crashlytics ダッシュボードで最初のデータを確認します。
- 投稿日:2022-01-31T12:40:21+09:00
Facebookでゲーム広告を配信するまで
Unityで製作したFacebookで広告を配信する方法が書かれた記事が少なかったため、情報共有のため書きます。 全体の流れ Facebookへの登録 Meta for Developersへの登録 Facebook SDKをUnityにインポートする ATT(App Tracking Transparency)への対応 AndroidでBuildする時の注意点 広告を出稿する 環境 MacBook Pro Monterey 12.0 Unity 2020.3.24f1 Facebook SDK 11.0 なお、Facebookは設定方法やWebのレイアウトが頻繁に更新されるので、手順が違った場合、適宜自分で調べてください。 Facebookへの登録 まず、Facebook Business Managerへの登録をします。Facebook Business Managerとは、広告アカウント、Facebookページ、アカウントの権限などを全て一か所で設定できるサイトです。 次に、広告アカウントと支払方法を追加していきます。 詳しいやり方は省きますので、こちらの動画を参考にしてください。Business Managerは構造が複雑ですが、それが適切に説明されているので理解しやすいと思います。また、やってはいけない広告出稿についても言及されています。 また、Instagramのアカウントも作っておくと後々便利かと思います。FacebookはInstagramへの広告も自動でしてくれます。 Meta for Developersへの登録 Meta for Developersへの登録をします。Meta for Developersとは、Facebookを使ったログインなどを簡単に実装できるツール群です。これで、アプリとFacebook Business Managerを紐づけます。 アプリの作成 ログインする 右上のマイアプリをクリック アプリの作成をクリック ゲームを選択 必要な情報を入力する とりあえず以上です。Facebook SDKをインポートしたら、また戻ってきます。 Facebook SDKをUnityにインポートする 下記のリンクからFacebook SDK for Unityを入手します。 unity packageをインポートします。 タブにFacebookが追加されるので、Edit Settingsを選択。 するとインスペクターに表示されるので、先ほどMeta for Developersで作ったアプリのFacebook App Idをインスペクターに入力します。Facebook App Idは設定>ベーシックから見れます。 また、androidでローンチする場合は、Debug Android Key Hashも後に必要なのでメモしておきます。 Meta for Developersに戻り、設定>ベーシックから、必要な情報を入手します。 その後、ページの下部のプラットフォームを追加から任意のプラットフォームを選択します。必要な情報を入手してください。 iOSの場合、iPhoneストアIDやiPadストアIDを記入する欄があるのですが、それはAppleStoreのURLのidと書かれた番号になります。 Androidの場合、キーハッシュが先ほどメモしたDebug Android Key Hashになります。 ATT(App Tracking Transparency)への対応 広告からアプリへの流入を計測するためにFacebook SDKをInisializeする必要があります。これをしないと広告出稿出来ません。 また、iOS14.5以降ATT(App Tracking Transparency)へ対応するために、ダイアログを表示します。 自分はAdmobも使用しているので、そこに付け足す形で実装しました。詳しい解説は下記のリンクをご覧ください。 一応コードも置いておきますが、これが正しい使い方か分かりません・・・ FacebookのReferenceがどうも少なすぎます。正しい情報知っている方がいらしたら、情報提供お願いします。 ATT.cs using UnityEngine; using UnityEngine.SceneManagement; using GoogleMobileAds.Api; using GoogleMobileAds.Common; using GoogleMobileAds.Placement; using Facebook.Unity; using System; public class ATT : MonoBehaviour { private void Awake() { #if UNITY_IOS int status = ATTUtili.GetTrackingAuthorizationStatus(); Debug.Log("ATT状態 = " + status); // ATT状態は4択 // ATTrackingManagerAuthorizationStatusNotDetermined = 0 // ATTrackingManagerAuthorizationStatusRestricted = 1 // ATTrackingManagerAuthorizationStatusDenied = 2 // ATTrackingManagerAuthorizationStatusAuthorized = 3 if (status == 0) { // ATT設定可能 & 未承認なのでATT承認要求アラートを表示 ATTUtili.RequestTrackingAuthorization(CallbackFunction); } else { if (status == 1 || status == 2) { // ATT設定不可なので、ATT承認が必要になる旨をユーザーに伝える } else if(status == 3) { FB.Init(this.OnInitComplete, this.OnHideUnity); } // Google Mobile Ads SDK を初期化 MobileAds.Initialize(initStatus => { // AdMobからのコールバックはメインスレッドで呼び出される保証がないため、次のUpdate()で呼ばれるようにMobileAdsEventExecutorを使用 MobileAdsEventExecutor.ExecuteInUpdate(() => { // バナーをリクエスト RequestAds(); }); }); } #elif UNITY_ANDROID MobileAds.Initialize(initStatus => { // AdMobからのコールバックはメインスレッドで呼び出される保証がないため、次のUpdate()で呼ばれるようにMobileAdsEventExecutorを使用 MobileAdsEventExecutor.ExecuteInUpdate(() => { // バナーをリクエスト RequestAds(); }); }); #endif } private void OnHideUnity(bool isUnityShown) { } private void OnInitComplete() { if (FB.IsInitialized) { FB.ActivateApp(); } else { //Handle FB.Init FB.Init(() => { FB.ActivateApp(); FB.Mobile.SetAdvertiserTrackingEnabled(true); }); } } void CallbackFunction(int status) { Debug.Log("ATT最新状況 --> " + status); // ATTの状況を待ってから Google Mobile Ads SDK を初期化 MobileAds.Initialize(initStatus => { // AdMobからのコールバックはメインスレッドで呼び出される保証がないため、次のUpdate()で呼ばれるようにMobileAdsEventExecutorを使用 MobileAdsEventExecutor.ExecuteInUpdate(() => { // バナーをリクエスト RequestAds(); }); }); // Facebook SDK if (status == 1 || status == 2) { // 設定不可 } else if (status == 3) { FB.Init(this.OnInitComplete, this.OnHideUnity); } } void RequestAds() { //バナーをリクエスト } AndroidでBuildする時の注意点 AndroidをBuildする際、Facebook SDKが他のUnityPackageと競合を起こすので解消します。そのままBuild通る方はやらなくても大丈夫だと思います。 1. Error Configure project :launcher WARNING: The option setting 'android.enableR8=false' is deprecated 対策 Project Settings>Player>Android>Publish Settings>Build>Custom Gradle Properties Templateをチェック。表示されるファイルのR8該当行の先頭に#を追加 #android.enableR8=MINIFY_WITH_R_EIGHT 2. Error D8: Cannot fit requested classes in a single dex file (# methods: xxxxx > 65536) com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: The number of method references in a .dex file cannot exceed 64K. 対策 Project Settings>Player>Android>Publish Settings>Build>Custom Launcher Gradle Templateを開く。表示されるファイルに以下の行を追加する。 build.gradle android { defaultConfig { ... minSdkVersion 15 targetSdkVersion 28 multiDexEnabled true <<これ } ... } dependencies { implementation "androidx.multidex:multidex:2.0.1" <<これ } 対策は下記のリンクを参考にしました。 広告を出稿する 長くなったので別記事です。 参考にしたドキュメント 自己紹介 ハイパーカジュアルゲームを個人製作してます! フォローお願いします! @1mono2 以上です。情報漏れや意見などございましたら、気軽にコメントしてください。フィードバック待ってます!
- 投稿日:2022-01-31T02:33:00+09:00
UnityでShaderを書き始めるミニマムな手順
UnityでShaderを書いて動かすためのミニマムな手順をまとめる。 具体的には、以下のように紫のグラデーションをシェーダーで描画させる。 確認環境 MacBook Pro (16-inch 2019) macOS Monterey 12.0.1 1. プロジェクトを作成する ここではUnity 2020.3.18f1、URPで作成する(BRPでも同様の手順でOK) 2. アセットウインドウで右クリックして [Create] -> [Shader] -> [Unlit Shader] 名前は"NewUnlitShader"のままでよい。 3. アセットウインドウで右クリックして [Create] -> [Material] 名前は"New Material"のままでよい。 4. マテリアルのインスペクタのShaderに"NewUnlitShader"を選ぶ。[Unlit] -> [NewUnlitShader] 5. ヒエラルキービューで右クリックして[3D Object] -> [Plane] 6. Planeのインスペクタを開き、作ったマテリアル("New Material")をドラッグ&ドロップする。 7. 作ったシェーダー(NewUnlitShader)を開き、frag関数を以下のコードに書き換える。 fixed4 frag (v2f i) : SV_Target { float4 col = float4(i.uv, 1.0, 1.0); return col; } 以下のように紫のグラデーションがシェーダーによって描画される。 以上 参考: Unityゲームプログラミングバイブル2nd P214「レイマーチング:基礎から応用まで」 サンプルコード: https://github.com/gam0022/UnityBible2-RaymarchingTutorial
- 投稿日:2022-01-31T01:25:35+09:00
スプライトの一部を光らせる
今どきのUnityはURPやHDRPを使わなくてもShaderGraphが使えてしまうので、この段階ですでに古いテクノロジーになってしまうのですが、一応自分の備忘録を兼ねて記事化しておきたいと思います。 ちなみにシェーダーグラフで行う場合はこちらの動画がわかりやすいです。 1.スプライトに使用する画像と、光らせたい部分を赤く塗った画像を用意する 光らせたい部分を赤く塗った画像は、RGBAのRとAの部分のみを使用します。 下の例では、光らせない部分をわかりやすくするために黒く塗ってありますが、特になくても大丈夫です。 2.画像をスプライト化しSpriteEditorを開く 3.Secondary Texturesを選択 Nameに _EmitTex と入力し、先ほどの光らせたい部分を赤く塗ったテクスチャを選択します。 4.シェーダーを作成する ビルトインのスプライトシェーダーにちょい足しした下記のシェーダーを用意します。 先ほど指定した _EmitTex という名前はこのシェーダーの中で使用します。 SpritesEx.shader // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) Shader "Sprites/DefaultEx" { Properties { [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} [PerRendererData] _EmitTex("Emit Texture", 2D) = "black" {} _Color ("Tint", Color) = (1,1,1,1) [HDR] _EmitColor("Emit Color", Color) = (1,1,1,1) [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1) [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1) [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {} [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0 } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" "CanUseSpriteAtlas"="True" } Cull Off Lighting Off ZWrite Off Blend One OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex SpriteVertEx #pragma fragment SpriteFragEx #pragma target 2.0 #pragma multi_compile_instancing #pragma multi_compile_local _ PIXELSNAP_ON #pragma multi_compile _ ETC1_EXTERNAL_ALPHA #include "UnitySprites.cginc" sampler2D _EmitTex; fixed4 _EmitColor; v2f SpriteVertEx(appdata_t IN) { v2f OUT; UNITY_SETUP_INSTANCE_ID(IN); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); OUT.vertex = UnityFlipSprite(IN.vertex, _Flip); OUT.vertex = UnityObjectToClipPos(OUT.vertex); OUT.texcoord = IN.texcoord; OUT.color = IN.color * _RendererColor; #ifdef PIXELSNAP_ON OUT.vertex = UnityPixelSnap(OUT.vertex); #endif return OUT; } fixed4 SpriteFragEx(v2f IN) : SV_Target { float2 uv = IN.texcoord; fixed4 texCol = tex2D(_MainTex, uv); clip(texCol.a-0.001); fixed4 emCol = tex2D(_EmitTex, uv); fixed4 color = (emCol.r * emCol.a > 0) ? _EmitColor * (emCol.r) : texCol * _Color; #if ETC1_EXTERNAL_ALPHA fixed4 alpha = tex2D(_AlphaTex, uv); color.a = lerp(color.a, alpha.r, _EnableExternalAlpha); #endif return color; } ENDCG } } } 5.マテリアルを作成 作成したシェーダーを使用してマテリアルを作成します 6.Post Processingで光らせる こちらを参考に光らせます 7.(おまけ)アニメーションを付ける こちらを参考にアニメーションを付けることができます。
- 投稿日:2022-01-31T00:06:07+09:00
UnityでVRに物理的ボタンを作る(VR Beginner: The Escape Roomのコードを読んでみる)
この記事について タイトルだけを読むと「何言ってるんだ?」と思われるかもしれませんが、Unity上で「ボタン」というとUIボタンの記事が出てきてしまうので「物理的なボタン」と書かせていただきました。 この記事で実装したいのは以下のようなものです。 3Dオブジェクトがボタンとして存在して、それをコントローラーで一定上押すと入力処理が走るというのが今回作成するものです。 これが作りたかったんや! Twitterにあげた動画 参考プロジェクト この記事で使用しているソースコードはUnityのチュートリアルプロジェクトの「VR Beginner: The Escape Room」のものを利用しております。 VR Beginner: The Escape Room 環境 Mac unity 2020.3.25 実装! オブジェクトの作成については省略します。 キューブを作って配置しただけです。 今回の中で最小の単位は3Dオブジェクトが一つだけで大丈夫です。 失礼、あとはプレイヤーも必要ですが、今回の実装ではスルーします。 がんばれ。 そしてこのオブジェクトに対してスクリプトをくっつけます。 いきなり完成形を貼り付けます。中に書いてあるコメントがそのまま説明になるかと思います。 ButtonManager using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; public class ButtonManager : MonoBehaviour { [System.Serializable] public class ButtonPressedEvent : UnityEvent { } public ButtonPressedEvent OnButtonPressed; public Vector3 Axis = new Vector3(0,-1,0 ); public float MaxDistance; public float ReturnSpeed = 10.0f; Vector3 m_StartPosition; Rigidbody m_Rigidbody; Collider m_Collider; bool m_Pressed = false; void Start() { m_Rigidbody = GetComponent<Rigidbody>(); m_Collider = GetComponentInChildren<Collider>(); m_StartPosition = transform.position; } void FixedUpdate() { // 押し込む方向の指定(自身の方向をワールド空間内での方向へ変換する) Vector3 worldAxis = transform.TransformDirection(Axis); // MAxDistanceを利用して最大移動地点を指定する Vector3 end = transform.position + worldAxis * MaxDistance; // スタート時点の位置からの現在までの移動量を測定(平方根) float m_CurrentDistance = (transform.position - m_StartPosition).magnitude; RaycastHit info; float move = 0.0f; // 戻る方向に物体がなければ元の位置に戻る処理。あったら逆方向(押し込まれる方向)へ移動する。 if (m_Rigidbody.SweepTest(-worldAxis, out info, ReturnSpeed * Time.deltaTime + 0.005f)) {//hitting something, if the contact is < mean we are pressed, move downward move = (ReturnSpeed * Time.deltaTime) - info.distance; } else { move -= ReturnSpeed * Time.deltaTime; } // 初期地点から最大移動距離の間に収まる値に位置が変換される float newDistance = Mathf.Clamp(m_CurrentDistance + move, 0, MaxDistance); // 新しい位置を設定する m_Rigidbody.position = m_StartPosition + worldAxis * newDistance; // ボタンが押されていない状態 & 新しく移動する予定の場所までの距離と最大移動距離が近侍であるならIF内処理 // ボタンが押されている状態 & しく移動する予定の場所までの距離と最大移動距離が近侍でないならELSEIF内処理 if (!m_Pressed && Mathf.Approximately(newDistance, MaxDistance)) {//was just pressed m_Pressed = true; OnButtonPressed.Invoke(); } else if (m_Pressed && !Mathf.Approximately(newDistance, MaxDistance)) {//was just released m_Pressed = false; } } } あとはオブジェクトにRigidbodyをアタッチして、is Kinematicにチェックを入れて重力を使用するのチェックを外します。 アタッチしたスクリプトの変数に値を設定するのですが、設定値は以下の通りです。 項目名 内容 On Button Pressed ボタンが押された時の処理 軸 ボタンが押される方向 最大距離 どれだけ押されたらイベントが発生するか 戻るスピード ボタンが抑えれる際にオブジェクトが認識される距離 これだけです! あとはご自由にここに発動したい処理を入れて実行してみましょう! 終了! おすすめ VR Beginner: The Escape Room * おそらくやりがいことが全て載ってる神プロジェクト * VRゲームをUnityで作りたいならこのプロジェクトを読めば大体載ってそう * UI関連は載っていないので注意 * XR Interaction Toolkit対応 * Device BaseなのでActionBaseでゲームを作りたい人は注意 XR Interaction Toolkit Examples * XR Interaction Toolkitのサンプルプロジェクト * こちらはUI関連のサポートもあるし各オブジェクトの動作やテレポートなんかも載っているがちょっと難しく感じる * 上が初心者向けならこっちは慣れてきた時に触ると良いかな? * こちらはDeviceBaseとActionBaseが両方とも触れる