原カバンは鞄のお店ではありません。

Unityを使ったゲーム制作のあれこれを綴っていきます。

【Unity】今更ながらAddressable Asset Systemを使ってみる

予定

理容室で髪を切っている時に「今日はこの後ご予定とかあるんですか?」という質問が一番苦手な休日ニートの皆さんこんにちは。それから髪を洗っている時に何の断りもなく頭のマッサージへ移行するサービスも苦手です。思わず声が出そうになるので

 

Addressables

Unityで動的にアセットを読み込む場合、Resourcesフォルダにアセットを配置してLoadする実装は随分前から非推奨な方法となっています。

理由としてはResourcesディレクトリ内に配置されたファイルはゲーム起動時に自動的に全てメモリにロードされる為、ゲームの起動が遅くなったり細かなメモリ管理ができなくなるだけでなく、プラットフォームに応じたリソースの配信ができないというデメリットの為ですが、その代替えとなるAssetBundleを利用する方法は少し面倒でソースの修正も必要で、個人的には従来通りResourcesフォルダを利用していました。

とは言え、いつまでもResourcesフォルダを使うわけにもいかないので、次作の開発を始めたのを機にAssetBundleをより使いやすくしたAddressable Asset System(以下、Addressables)を導入することにしました。

docs.unity3d.com

 

このシステムはUnity2019で本リリースされているのでUnity2019以降のバージョンであれば利用することが出来ます。
エディタのメニューから[Window] > [PackageManager]を選択し、パッケージ一覧から「Addressables」を選択してInstallボタンを押します。

 

AddressablesはAssetBundleをグループ単位で管理するシステムなので最初に管理するグループの設定を行います。
メニューの[Window] > [Asset Management] > [Addressables] > [Groups]を選択

表示されたウィンドウの[Create Addressables Settings]ボタンを押します。

ProjectウィンドウのAddressableAssetsDataフォルダの下にAddressable Assets Systemに関する設定ファイルが出力され、「Default Local Group(Default)」というグループが作成されます。
以後、特にリソースを分ける必要が無ければこのDefaultグループにアセットを登録していきます。

 

ローカル(自PC内)での使用

AddressablesをResourcesフォルダ代わりにローカル(自PC内)で使用する場合は、以下の手順の設定を行ってResources.Loadの箇所をAddressables.LoadAssetAsyncに変更します。

  1. 対象となるアセット(画像やプレハブ)をAddressables Groupに登録する
  2. AddressablesのPlayModeを「Use Asset Database」に設定する
  3. Addressables.LoadAssetAsyncでアセットをロードする

 

1.Addressables Groupへの登録

Addressablesをプロジェクトに導入するとImageやPrefabを選択した際、InspectorにAddressableのチェックボックスが表示されるようになります。

Addressables使って動的に読み込みたいアセットに対しては、最初にこのAddressableという項目にチェックします。

チェックすると自動的に選択したアセットがDefaultグループにAddressable欄の名前で登録されますが、ここでは自分で管理しやすい名前に変えて問題ありません

 

メニューの[Window] > [Asset Management] > [Addressables] > [Groups]を選択して表示されるAddressables Groupウィンドウを確認すると、先ほどのアセットが設定した名前で登録されていることが分かります。

 

2.PlayModeの設定

先程のAddressables Groupウィンドウで「Play Mode Script」を押して表示されるリストの中から「Use Asset Database(fastest)」を選択します。

 

3.Addressables.LoadAssetAsyncでロード

ここまでの設定を終えたらスクリプトでAddressables.LoadAssetAsyncにてアセット名を指定してロードすることができます。
ただい、LoadAssetAsyncは非同期処理なのでCompletedイベントで処理をする必要があります。

Completedではなくコルーチンで処理の終了を待つこともできます。

 

上記の実装によりゲームを起動するとAddressablesに登録した画像(傘のアイコン)がロードされ、スプライトの画像が変更されます。

 

リモートでの使用

Addressablesを利用する真の目的はプラットフォーム毎やバージョン毎のリソース管理・配布を簡単にする事です。

そういった場合、ロード対象となるアセット(画像やプレハブ)を一旦、Assebundleという形に変換してサーバに配置、リモートでAssebundleをダウンロードして対象のアセットをロードします。
この為、リモートでAddressablesを使用する場合は、少し複雑な手順と設定を行います。しかし、スクリプトはリモートとローカルで変更する必要がありません(超重要)
制作現場の規模によってビルド・設定手順は様々異なりますが、単独や少人数での開発では以下のような手順になると思います。

  1. Addressablesの設定をリモート用に変更する
  2. Addressables GroupのアセットをビルドしてAssebundleを作成する
  3. ビルドしたAssebundleをサーバへアップロードする
  4. AddressablesのLoadPathの設定にサーバのURLを指定する
  5. Addressables GroupのPlayModeを「Use Existing Build」に変更する

 

1.リモート用に変更

最初に[Window] > [Asset Management] > [Addressables] > [Settings]を選択してBuild&Load Pathsの設定を「Remote」に変更します。

そしてPath PreviewのBuildPath欄の記載を確認しておきます。

 

2.Assebundleを作成 → 3. サーバへアップロード

Addressables Groupウインドウを表示して[Build] > [new Build / Default Script]を選択します。

これによりAssebundleが先程のBuildPathの箇所に作成されます。

ファイルが幾つかありますがいずれも必要な物なので、全てサーバへアップロードします。

 

4.LoadPathにサーバのURLを指定

次に[Window] > [Asset Management] > [Addressables] > [Profiles]からAddressables Profileウィンドウを開き、Remote欄をCustomに変更、RemoteLoadPath欄にサーバのURLを指定します。

 

再度メニューから[Window] > [Asset Management] > [Addressables] > [Settings]を選択してLoadPathがProfileで設定したURLとなっていることを確認します。

 

5.PlayModeを変更

最後に[Window] > [Asset Management] > [Addressables] > [Groups]からAddressables Groupウインドウを表示、「Play Mode Script」を押して「Use Existing Build」を選択します。

 

少々複雑ですが設定を変えるだけでスクリプトを変更することなくアセットをリモートでロードすることが出来ます。
アセットに新しく素材を追加したり、変更した場合はAssebundleのビルドから同じ手順を行う必要があります。Assebundleのビルドに失敗する場合は、一旦、Addressablesの設定をローカルに戻すと良いかもしれません。
(ビルド後はリモートに戻す)

 

最後に

Addressablesは初期設定の煩わしさを超えてしまえば、後はAssebundleのビルドとサーバへのアップロード(リモートの場合)を行うだけで、Resourcesと同じように使うことができます。

リモートとローカルでスクリプトを分ける必要がない事も大きな利点で、容量制限の厳しいスマホ向けのゲームを開発されている方は導入を検討してもそれだけの価値はあると思います。

 

【雑記】ゲーム制作進捗報告

腱鞘炎

仕事もゲーム制作もサボり気味なのに何故か手首が腱鞘炎になった脆弱な皆さんこんにちは。先週はポケットから財布を取り出すのにも苦労するほど右手首が痛くPCを起動する気力さえ起きなかったのですが、母親に勧められたロキソニンテープを貼ると見事に効いて何とか週末は作業することが出来ました。ロキソニンテープは神。

 

スーパーゲ制作デー

いつの頃からかインディーゲーム界隈では毎月第2土曜日に制作中のゲームの進捗状況を「#スーパーゲ制作デー」とハッシュタグをつけてX(旧Twitter)で発表するという企画が盛り上がっていて、この日に合わせて多数の進捗動画が投稿されています。
個人、少人数でのゲーム開発はどうしてもクローズドな環境になりがちなんですが、このような互いの進捗をシェアしあうような企画があれば、モチベーションの向上にも繋がりますし、開発の刺激にもなります。

というわけで、私も「スーパーゲ制デー」企画に乗って制作中のリズムゲーム「Under A Groove」の進捗報告を投稿しました。

Under A Groove」は試作版を福岡インディーゲームEXPOで出展したのですが、今回はその展示会で頂いた意見や反応を受けて再度ベースから作り成したバージョンの進捗報告となっています。
その為、展示会で出展した試作版と比べてかなり地味(かつ短い)動画ですが、現状ではゲームのベース部分の開発&動作確認を行っている最中なので、これがお見せできる精一杯の所と言えるでしょう。

ちなみに試作版(福岡インディーゲームEXPO出展バージョン)はこんな感じです。

youtu.be

 

Under A Groove

このゲームでは従来の音ゲーと同じく"特定のアイコンが指定された場所に移動したタイミングでボタンを押下する"という操作でプレイの正否を判定するのですが、上の動画の通り、プレイヤーが操作タイミングを図る「アイコン」部分と「判定箇所」部分が一つのユニットとして表示される方式となっています。(このユニット全体を「ノーツ」と呼ぶ)

 

操作の正否は従来の音ゲーのように「Just」「Good」等の判定が表示されたり、得点・スコアが表示されたりするのではなく、表示されているアニメーションが分岐することで操作正否を表現するようにしています。

 

今回作成しているバージョンでもこの辺の方向性は試作版から変わっていないのですが、

  • ノーツのバリエーションを増やす
  • ワンボタンのみだった操作方法に幅をつける
  • 操作の正否判定処理を改良する

等々の変更を行っています。特に正否判定処理の改良(ベースから作り直した一番の理由)により、下の動画のように同時に複数のノーツを動作→判定させる事ができるようなり、ゲームの幅を増やすことができました。
(試作版では短い間隔で複数のノーツを判定する事が出来なかった)

ベース部分の作成はあと少しという所ですが、楽曲毎にそれに合わせたアニメーションを作る必要があるので制作にはまだまだ時間が掛かりそうです。

 

製品版「W.T.」

去年の夏にアーリーアクセス版をリリースしてからそろそろ一年になります。当初の予定では今年の春に製品版をリリースする予定でしたが、アーリーアクセス版リリース後、コンテストへの応募やイベントへの出展等々、他の優先課題の解消に時間が掛かり、あまり手つかずの状態となっていました。

store.steampowered.com

ここ最近、ようやく最終ステージの作成に手が出せる状況になったので、ボチボチと始めているのですが中断期間が長かった所為か制作のペースが取り戻せずにいます。

作成中の最終ステージ

 

W.T.は制作にフレームワークのアセットを使用しているのですが、その辺の操作方法&仕様を思い出すのに苦戦する、かつ、自身が作ったのに処理が思い出せない謎スクリプトがあったり等、色々時間が掛かっていますが製品版を必ず完成させるので、地道に頑張っていこうと思います。

 

 

【Unity】以外に便利なUnityエディタの検索機能

夏の予定

東京ゲームダンジョン外伝に申し込み損ねたウッカリ者の皆さんこんにちは。申し込み開始日は日中いろいろ予定があり、帰宅後の深夜にXを確認したら締め切られた後でした。おかげで直近の出展予定がゼロになったばかりでなく、金欠でBitsummitも見に行けないので夏の予定は真っ白です。

 

リスペクトが過ぎたゲーム

その昔「ドリームキャスト」(以下DC)というSEGA製のゲーム機があったのですが、競合したPS,PS2の影に隠れてあまり一般に浸透することなく消え去ったので、DC専用で発売されたゲームソフトの数々も一部ファンの間でしか知られていない存在でした。
そんなDC専用ゲームの中でも熱狂的なファンが存在するゲームが幾つかあり、特に「ジェットセットラジオ」というゲームに対しては現在でも続編を待ちわびている熱心なファンがいるようで、ついにはそのファンメイド的なゲームが発売されました。

 

スケート、スケボー、BMXを乗りこなしながらグラインド、マニュアル、ブーストなどのテクニックを使って街を滑り、その過程でマップの至る所に設置されているポイントにグラフィティ(落書き)を描いていく、というゲームとなっています。

 

トゥーン系のアートスタイルにストリートカルチャーを題材にしたゲーム内容、ゲーム内で流れる楽曲にジェットセットラジオでも楽曲を担当した長沼英樹氏の楽曲が含まれている等、「ジェットセットラジオ」のクローンと言っても差支えないような内容で、ローポリゴンで粗目のテクスチャのキャラクターや、リアクション動作がワンテンポ遅いイベントシーンなど、元ネタのゲームを現代版にアレンジしたというより、DC版をそのまま引き継いで現代に蘇らせたような造り。
ゲームプレイ中にマップや設定等の確認を行うオプション画面には(スマホではなく)ガラケーの画面が採用されていたりするほど、制作側のこだわりを感じたのですが、その分どうしてもゲームプレイの古臭さ、不親切さ、単調さは拭いきれず、プレイ中はずっとレトロゲームを遊んでいるような感覚になりました。

左のガラケーがオプション画面となっている

 

元ネタの「ジェットセットラジオ」同様にストリートを駆け巡り、グラインド等のテクニックを駆使した時の「クールさ」、「ファンキーさ」を感じて気持ちよくなるゲームですが、20年前のゲームの「ノリ」を受け入れて最後まで楽しめるかは人によって異なるゲームだと思います。

 

検索機能

UnityエディタでProject内やHierarchy内を検索する機能は以前からありましたが、Unity2021からその機能が強化されているようです。
Unity Searchという機能名がわざわざ付けられてマニュアルにも記載されている程に多機能となっており、様々な検索条件が指定できたり、検索結果として表示されたオブジェクトに対して検索結果画面から直接編集出来たりします。(SearchウィンドウにInspectorが付属している)

docs.unity3d.com

このUnity Searchを使うにはCtl+K(Command+K)を押下するか、Unityエディタの右上にある拡大鏡のアイコンをクリックします。

Searchウィンドウが開くのでウィンドウ上部のテキストボックスに検索したいキーワードを入力するだけです。また、Unity Searchではキーワードだけでなくクエリを使っても検索する事ができます

 

ただし、このクエリを使った検索は事前にIndexを作成する必要があるため、デフォルトの場合、最初にSearchウィンドウを開いたタイミングでIndexの作成が行われます。
Unityエディタの右下に「Building assets search index」の文言とプログレスバーが表示されるので、これが完了するまで待ちます。

これが結構時間が掛かる

クエリにより複雑な検索条件を指定することができます。

例えばProject内のテクスチャ(Texture)でファイルサイズが大きい物を探したい場合は、テキストボックスに「sort{t:texture, @size, desc}」と入力すると、Project内のテクスチャがファイルサイズの大きい順に並べて表示されます。

 

簡単に使いたい

クエリを使えば様々な検索が行えますが、もっと簡潔に検索したい場合の機能もUnity Searchでは用意されています。
Searchウィンドウのテキストボックス横のカプセルアイコンを押し、「+」ボタンを押すと検索対象の種別(GameObject,Type)を指定した検索が行えます。
例えばProject内でAnimationファイルを探したい場合は

上の動画のような操作を行うことで検索が出来ます。

上記の操作で検索を行うとテキストボックスには検索内容を示すアイコンが表示されます。下の図はHierarchy内で「UnderPlayerJudgementComponent」というスクリプトがアタッチされたオブジェクトを検索した例です。

この状態でカプセルアイコンをクリックすると、検索内容がクエリで表示されます。

 

さらに便利な検索

長期間ゲーム制作を続けていると、シーン内のオブジェクトについてプロパティの参照設定が外れていたり、参照していたオブジェクトを削除してしまい未設定となっている物があったりします。

例えば以下のスクリプトでは「EffectDiscObj」プロパティの参照先が未設定となっていますが、

EffectDiscObjの参照先がNoneとなっている

これをSearchウィンドウで「Hierarchy内→"ShapesSnowLine**"の名前が付いたコンポーネント→プロパティ"EffectDiscObj"がNoneとなっているもの」という意味で

h: t:ShapesSnowLine #EffectDiscObj=<$object:none$>

とクエリを書くことで検索する事が出来ます。

 

他にもいろいろな検索が行うことができますが、クエリに関してはマニュアルを見ても分かりづらいため、LIGHT11さんがまとめた様々な使用例を参考にして学ぶ方が簡単だと思います。

light11.hatenadiary.com

【Unity】TextMeshProUGUIでUIをマスクする

Instagram

インスタで小さい子供やペットの可愛い写真や動画を載せていたアカウントが急に商品の宣伝をしだすとなんだか悲しくなるナイーブな皆さんこんにちは。子供やペットが無邪気な分、将来の姿を勝手に心配してしまいます。

 

UIのマスク

UnityではImageなどのUIに関してはMask機能が用意されていて、切り抜きたい形の画像にAddComponentでMaskコンポーネントをアタッチして、その子オブジェに切り抜かれる側の画像を配置すれば良いだけとなっています。

docs.unity3d.com

 

なので非常に手軽に実装できるのですが、Imageの内側をくり抜くような逆マスクには対応していないので、そういった場合には有志の方が公開してるアセットを使う必要がありました。

github.com

 

そういった状況でしたが、Unity公式コミュニティの投稿によりMaskコンポーネントもオブジェクトの親子関係も必要とせずにマスク処理、及び逆マスク処理を行う手法が明らかになったようです。

www.zkn0hr.com

 

マスク処理(逆マスク含む)と言えばシェーダーのステンシル処理を使う為、これまではシェーダーに手を加える必要がありましたが、上記の手法ではInspetor上からステンシル用の設定を行う事ができる為、新たにシェーダーを起こす必要はありません
今回はその手法を利用して、いままでは行う事ができなかったTextMeshProUGUIの文字列でのUIのマスクを試みてみようと思います。

 

TextMeshProUGUI側の設定

今回はTextMeshProUGUIの文字列でマスクするため、TextMeshProUGUIがステンシルバッファにRef値を書き込む必要があります
最初にTextMeshProUGUI用のMaterialを用意する為、TextMeshProUGUIのInspetorにあるSDFのアイコンを右クリック→「Create Material Preset」でMaterialを作成します。


その際、分かりやすいような名前を設定しておくと後で使いまわし易くなります。

 

作成したMaterialのシェーダーにはステンシル処理用の設定を行う為、「UI→Default」を指定します。(後でTextMeshProUGUI用のシェーダーに変えます)


「UI→Default」では以下のように設定します。

重要なのはStencil ID(Ref値)とStencil Comparison(比較方法)とStencil Operation(操作方法)なんですが、どれも数値で指定する必要があるため、一度マニュアルで確認してください。

docs.unity3d.com

ステンシルの設定を行ったら、シェーダーをTextMeshProUGUI用のシェーダーに変更します。シェーダーに「TextMeshPro -> Mobile -> Distance Field – Masking」を指定、先程のステンシルの設定が内部に保存されたままTextMeshProUGUI用のシェーダーに切り替わります。(Inspector上からは見えなくなります)

 

Image側の設定

マスクされる側のImageは何でも良いのですが、マスク効果が分かりやすいように今回は白い四角を使いました。

 

マスクされる(文字列で切り抜かれる)Imageの方もステンシル処理用の設定を行うのでシェーダーに「UI→Default」を指定し、以下の設定を行います。

 

ここでStencil IDには先程TextMeshProUGUI側で指定した値と同じ値を設定、Stencil Comparisonに「Equal」(レファレンス値がバッファの値と等しい場合のみレンダリング)を指定すると

Image(白い四角)が文字列の形で切り抜かれました。

今度はStencil Comparisonに「NotEqual」(レファレンス値がバッファの値と等しくない場合にレンダリング)を指定します。

以下のように逆マスクとして機能します。

 

注意点

先程も記述しましたが、TextMeshProUGUI側では一度設定するとStencil ID(Ref値)が見えなくなるので、設定時にはメモ等の記録を取っておくことをお勧めします。
また、当然ながらマスク側(TextMeshProUGUI)はマスクされる側(Image)より先に描画する必要があるので、ヒエラルキー上の順番は「マスクされる側」が「マスク側」の下の順になるように配置してください。(オブジェクトを親子関係とする事は不要です)

【Unity】Shapesのステンシル設定を利用したマスク表現

自動車税

GWに浮かれて洋服を購入したりプリンタを新調したりアレコレと浪費していたら「自動車税を今月中に払え」と通知が来て赤貧になりかけた皆さんこんにちは。GWと母の日と自動車税の時期が重なるのは国の罠だと思う。

 

ステンシル

Unityではシェーダーの機能として1pixel毎にそのpixelの描画有無の判断として利用できるバッファ領域(ステンシルバッファ)が用意されています。
ステンシルバッファではpixel単位に8bitの整数値を設定する事が可能で、後続のドローコールでその整数値を参照してピクセルを廃棄するか描画するかを決定します。

docs.unity3d.com

これは3Dオブジェクトにマスク表現(切り抜き描画)を行いたい時に良く利用される機能ですが、アセットストアで販売されているような一般的な(トゥーンシェーダーのような)シェーダーには、このステンシルに対する操作のパラメータを用意している物は殆どなく、マスク表現をしたい場合にはマスク専用のシェーダーアセットを購入するか、シェーダーを自分で改良or作成するかの二択になっていました。

一応、技法として確立している為、Web上を検索すると有志の方がステンシルバッファを利用したマスクシェーダーを公開していたりするので、こちらを利用する事も可能です。私も以前お世話になり、このブログで紹介させてもらいました。

www.karvan1230.com

 

Shapesというアセット

Shapes」というアセットはゲーム空間に円、線、矩形といったプリミティブな図形のオブジェクトを作ることができるアセットで、図形描画に必要なパラメターをInspetor上やスクリプトで自由に変更可能な為、非常に使い勝手が良く、その辺りの基本的な機能については以前記事にしました。

www.karvan1230.com

で、このShapesではステンシルバッファに対して書き込み・参照もどちらも可能なパラメターが用意されている為、これを利用すればマスクとして手軽に利用する事が出来そうです。

赤い四角部分がステンシルバッファに対する設定箇所

 

例えば下図のように黒円の前に白三角がある場合、カメラからは白三角しか見えません


そこで黒円側のInspectorにてRef値に値を設定&Passの値に「Repalce」を選択してステンシルバッファにその値を書き込みます

 

白三角側ではRef値に黒円側と同じ値を設定し、Compareに「Equal」を選択すると

 

黒円側がステンシルバッファにRef値を書き込んだ領域のみが描画されるので、円形に切り抜かれます(マスキング)

 

逆にCompareで「NotEqual」を選択するマスク側と重なっていない領域が描画され(逆マスク)、背後にある黒円が見えるようになります。

 

白三角をマスクの形(円形)で切り抜きたい場合には、マスクする側(黒円)のColorのAlpha値を「1」と極めて小さい値にします。0だとステンシルバッファにRef値が設定されません

黒円のColorのAlpha値を「1」とした場合

 

ここで一番最初にお見せしたカメラと白三角、黒円の位置を確認するとマスクとなる黒円が白三角よりカメラから見て奥に配置されることに気づくと思います。

これはShapesでマスキングをする場合、ステンシルバッファに値を書き込む側(マスクする側)のオブジェクトは参照する側(マスクされる側)より奥に設置する必要があるためです

というのもShapesではRenderQueueがデフォルトで3000(Transparent)となっている為、

  • UnityではRenderQueueが2500以上の場合はカメラから遠い順に描画される
  • マスクされる側(ステンシルバッファを参照する側)よりマスクする側(ステンシルバッファを更新する側)の方が先に描画される必要がある
  • よってマスクする側をマスクされる側より奥側に設置する

となるからです。(以下のリンク参照)

www.vr-fluffyscafe.com

 

この性質を利用

先述のようにShapesのRenderQueueがデフォルトで3000(Transparent)となっている為、通常(不透明)の3Dオブジェクトの描画後にステンシルバッファの更新→参照が行われる事になります。
これを逆に考えると3DオブジェクトがShapesのマスクの手前にある領域ではステンシルバッファの更新はされない、という事なので、例えば下図のようにマスク側(白四角)のオブジェクトとマスクされる側(黒四角)の間に少女の3Dモデル(不透明)がある場合では

(カメラから見て)少女モデルが白い四角を遮っている為、その部分はステンシルバッファに値が書き込まれず、マスクされる黒い四角部分に本来なら見えないはずの少女モデルが見えるようになります。

 

これを先ほどと同じようにマスクされる側の設定を「NotEqual」(逆マスク)に変えてみます。

先程とは逆に少女モデルの部分に逆マスク部分(黒い四角)が反映されて影絵のような表現になりました。

少女を歩かせてみるとこんな感じ

マスク部分でShapseの黒四角が少女モデルの形に切り抜かれて表示されていますね。ちょっと演出に使えそうです。

 

【Unity】Splineを利用してLitMotionでパス移動を実現する

ゲーム漬け

休暇前はゲーム開発のみならずアレコレと意識高めの計画を立てるも結局は部屋に引き籠ってゲーム三昧だった怠惰な皆さんこんにちは。
このGW中には東京ゲームダンジョン5が開催されていたので東京近辺にお住まいの方はそちらへ出向かれた方もいらっしゃるでしょうが、福岡住まいの私は飛行機+ホテル代の高さと別の予定の為に参加を断念し、10連休のほぼ6割をRise of roninに費やし、そのうちの7割ぐらいの時間を道場での鍛錬(ボスキャラと1対1での対戦モード)で過ごすという全く"無駄"以外に表現のしようがない休暇を過ごしました。おかげさまで石火(パリィ)は非常にうまくなりました。そしてそれを誰にも誇れない事が残念です。

 

パス移動

ゲーム制作をしているとオブジェクトの移動は通常の直線移動以外に経路に沿った移動(パス移動)も必要となる事も多く、そういった場合はこれまで主にDOTweenのDOPath/DOLocalPathを使っていました。
逆に現状Tween系最速のアセットLitMotionではDOPath/DOLocalPathに該当するメソッドは用意されておらず、対策としてUnitaskとforループを駆使して経由点毎に移動を繰り返すような処理を組んでみたのですが、その手法だと経由点が多くなると指定した時間では経路全体を移動し終えない事もあったりで、DOTweenからLitMotionへ完全に移行する事はできませんでした。

なのでちょっと視点を変えて、DOPathのように通過したい地点の配列を使用するのではなく、それら(経由点)を通るようなSplineを利用する手法を取ることにしました。

4点を通るSpline

 

Spline自体はUnity2022以降であればPackage Managerからインストールする事ができ、Unityエディタ上で簡単にSplineを作成してくれるTool機能がついているので手軽に作成する事ができます。
導入法や簡単な使用法についてはこのブログでも以前記事にしているので、そちらを参考にしてください。

www.karvan1230.com

そしてこのSplineは便利なことに0~1の割合を指定すればEvaluteメソッドによりSpline上の指定した点での位置、向き、法線ベクトルといった情報を取得する事ができます。

 

割合をTweenする

という事は、その機能を利用して以下の手順で処理すれば経路に沿ってオブジェクトを動かすことが出来そうです。

  1. LitMotionで割合の値(0~1)をTweenさせる
  2. その値をEvaluteメソッドに指定してSpline上の地点(ワールド座標)を取得
  3. Bindで取得した地点をTransformに反映する

コードに表すとこんな感じ

LMotion.Create(0.0f, 1.0f, 移動時間)
    .WithEase(Ease.Linear)
    .Bind(
        value =>
        {
            // splineの位置、向き、法線ベクトルを取得
            spline.Evaluate(value, out var splinePos, out var splineTangent, out var upVector);

            // Transformに反映
            transform.SetPositionAndRotation(splinePos, Quaternion.LookRotation(splineTangent, upVector));
        }
    );

上の処理を組み込んだコンポーネントを動かしたいオブジェクトにアタッチして動作させてみると

狙った通りに動かすことが出来ました。

 

まとめ

今回の手法ではDOTweenのDOPathと比べてSplineを作るという手間は増えますが、逆にSplineで描いた自由曲線に沿った移動が可能なため使い勝手は良いのではないでしょうか。例えば

 

上のような曲線もSplineを作成して先程の処理を利用すれば

曲線に沿って綺麗に移動させることが出来ます。

【作業報告】アルファマスク使って少女の幽霊を作る

満員電車

毎年4月の初めになると朝の通勤電車が学生や新社会人で溢れて満員になるも、GWを過ぎたあたりから徐々に減り始め夏前にはすっかり元の乗車率に戻る事を知っている大人な皆さんこんにちは。ここ最近の新人の方は入社前の理想と入社後の現実とのギャップに挫けるというよりは、見習い・下働きといった下積み作業に耐性がなくて挫折する方が多いような気がしますが、実際どうなんでしょうか?

 

少女の幽霊

次作(Under A Groove)の新しいデモ版を作成するにあたりどうしても(ホラーではない)少女の幽霊のモデルが欲しかったのですが、アセットストアを漁ってもBOOTHを探してもコレといったものが見つからなかったので、既存の3Dモデルに手を加えて作ることにしました。

 

オリジナルのモデルはSURIYUNの「Farmer Girl SD」を使い、シェーダにはlilToonを使います。

 

booth.pm

lilToonではアルファマスクが使えるので、上のモデルのテクスチャ画像を基に少女の足元が徐々に消えて見えるようグラデーションを掛けたアルファマスク画像を用意します。



lilToon側の設定は「描画モード」を「半透明」に設定し

 

「アルファマスク」に「乗算」を指定してアルファマスク画像として上の画像を指定します。

 

するとこんな感じになりました。

まぁ狙い通りに足元は消えてくれたのですが、幽霊だから足元が見えないというよりは欠損したように見えるのでちょっと幽霊感が薄い感じがします。

 

発光させる

足元が徐々に消えるというだけではなく、逆に足元の部分が発光して見えるように設定を加えます。
なので今度はアルファマスク画像を反転して発光テクスチャ画像を作りました。

これをlilToonの「発光設定」にチェックを付けて上の画像を発光テクスチャとして指定します。

 

発光設定を加えたことで足元が白っぽく薄れて見えるので先程よりは幽霊っぽくなったと思います。

 

仕上げ

最後に足元の部分に光球がドロップするようなパーティクルを付けます。否が応でも常人ではない感がでるので、ただ足元を薄くするよりは「この少女は幽霊です」がプレイヤーに伝わりやすいかなと思います。

 

歩かせるとこんな感じに見えます

 

◇プライバシーポリシー

●個人情報の利用目的

当ブログでは、メールでのお問い合わせ、メールマガジンへの登録などの際に、名前(ハンドルネーム)、メールアドレス等の個人情報をご登録いただく場合がございます。

これらの個人情報は質問に対する回答や必要な情報を電子メールなどをでご連絡する場合に利用させていただくものであり、個人情報をご提供いただく際の目的以外では利用いたしません。

●個人情報の第三者への開示

当サイトでは、個人情報は適切に管理し、以下に該当する場合を除いて第三者に開示することはありません。

・本人のご了解がある場合
・法令等への協力のため、開示が必要となる場合

個人情報の開示、訂正、追加、削除、利用停止
ご本人からの個人データの開示、訂正、追加、削除、利用停止のご希望の場合には、ご本人であることを確認させていただいた上、速やかに対応させていただきます。

アクセス解析ツールについて

当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。

このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。このトラフィックデータは匿名で収集されており、個人を特定するものではありません。
この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。

●免責事項

当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。

当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。

当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

●プライバシーポリシーの変更について

当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。