UniTaskとMagicaCloth2を使ってWebGLでクロスシミュレーション

ソースコードを改造してMagicaCloth2をWebGLでも無理やり動かせるようする方法を解説していきます。

※旧MagicaClothをWebGLで動かす場合はこちら

ソースコードの改造は自己責任でお願いします。

本記事はMagicaCloth2 バージョン2.0.0の内容となります。

初版という事もあり、バージョンアップによって変更箇所が変わる可能性はかなり高いです。ご注意ください。

最新版のchrome、firefox、Microsoft Edgeで動作確認済みです。

結論

・動かない原因は『Task』

・UniTaskを使えばWebGLでも動作可能

・ただしWebGLではマルチスレッド非対応なので『UniTask.Create』を使う

改造した結果がこちら

自己責任で!

Magica Cloth 2とは

2023年2月11日に公開された、Magica Clothの後継版です。

旧Magica Clothと同様にボーン、メッシュ両方を揺らすことが可能な他、旧MagicaClothではシミュレーションさせるために複数のコンポーネントが必要だったり、導入の手順がややこしかったのですが、Magica Cloth 2では1個のコンポーネント(+必要なコリジョン)だけで簡単に実装できるようになっています。

・Asset Store

https://assetstore.unity.com/packages/tools/physics/magica-cloth-2-242307

・公式サイト

で、そんな新しくなったMagica Clothの公式サイトには

WebGLを除くすべてのプラットフォームで動作可能

https://magicasoft.jp/mc2_about/

残念ながら、WebGLはMagica Cloth 2になっても非対応らしく、実際にWebGLでビルドしてもシミュレーションしてくれません。

しかも旧MagicaClothの時とは異なり、エラーログは一切出現しません。

なのでそのままじゃ動きませんし、なんなら旧MagicaClothで行った対応方法も効果がありません

(そもそも現versionのMagicaCloth2のソースコード内にComputeShaderは存在しません)

原因

先述の通りMagicaCloth2にComputeShaderが使われているコードはありません。

ですので、別の処理がWebGLの動作を阻害している事になります。

それで調査した結果、どうやらWebGLで動かない原因はマルチスレッド処理を行う『Task』でした。

Taskとは非同期処理を行う機能なのですが、そのTaskには『SynchronizationContext』というマルチスレッドを行うための機能(?)が内部搭載されているらしいです。

で、WebGLはマルチスレッド非対応なため『SynchronizationContext』が搭載されたTaskクラスを用いると動かなくなる、という事らしいです。

※私はマルチスレッド関連に全く詳しくないため、ここら辺の情報は間違っている可能性があります。鵜呑みにはせず、正しい情報を各自で調べてください。

対応

先のとおりTaskではWebGLが動かせないもののasync awaitは使用する必要があります。

ですので、Taskを使用している箇所は『SynchronizationContext』を搭載していないUniTaskに書き換えていきます。

UniTaskの導入

まずは下記のURLから最新版のUniTaskをダウンロードしてプロジェクトに追加します。

https://github.com/Cysharp/UniTask

MagicaCloth2のAssemblyにUniTaskの参照を追加

プロジェクトにUniTaskを追加したら、次はMagicaCloth2のAssenbly Definition AssetにUniTaskの参照を追加します。

Assembly Definition ReferencesにUniTaskを追加する

これによってMagicaCloth2のソースコード内で、UniTaskが使えるようになります。

Taskを全てUniTaskに書き換え

v2.0.0時点の内容ですが、Magica Cloth2のソースコードでTaskが使われているクラスは1個だけです。

そのクラス内にあるTaskを全てUniTaskに置き換えていきます。

ただし、『Task.Run』はマルチスレッドに移行する処理なので、『UniTask.Run』とは書き換えずにちょっと工夫する必要があります。

WebGLで実行させる場合は『Task.Run(() =>』 を『UniTask.Create(() =>』に変更します。

これでシングルスレッドのまま非同期処理を行うことが出来ます。

ただ、このままだとWebGL以外の時もシングルスレッドで動いてパフォーマンスが下がるので、WebGL以外の時は『UniTask.RunOnThreadPool』を使うように分けた方がよいです

Task.Runの変更前
UniTask変更後

また、関数を変更する事によって、第二引数にはboolしか渡せないエラーや(UniTask.RunOnThreadPooi)、第ニ引数を指定できないエラー(UniTask.Create)が発生します。

なので、それぞれの第二引数もちゃんと変更する必要があります。

Task.Runの変更前(ラムダ式の後に記述されてる箇所)

UniTask変更後(ラムダ式の後に記述されてる箇所)

以上の改造によって、WebGLでも動作するようになります

 改造したMagica Cloth2でWebGLビルドしたものはこちら

この作品はユニティちゃんライセンス条項の元に提供されています

注意

改造は自己責任でお願いします!

上記対応によってエラーが出たからと言って、公式にDMやバグレポートを送らない様に!

コード改造して出現したエラーは自力で対応しましょう。

また、本対応は2023/2/17時点の最新バージョンであるv2.0.0での対応となります。

バージョンアップによって対応箇所が変化する可能性がるので、ご注意ください。

コメントする

CAPTCHA