ゲーム開発
Unity
UnrealEngine
C++
Blender
ゲーム数学
ゲームAI
グラフィックス
サウンド
アニメーション
GBDK
制作日記
IT関連
ツール開発
フロントエンド関連
サーバサイド関連
WordPress関連
ソフトウェア設計
おすすめ技術書
音楽
DTM
楽器・機材
ピアノ
ラーメン日記
四コマ漫画
その他
おすすめアイテム
おもしろコラム
  • ゲーム開発
    • Unity
    • UnrealEngine
    • C++
    • Blender
    • ゲーム数学
    • ゲームAI
    • グラフィックス
    • サウンド
    • アニメーション
    • GBDK
    • 制作日記
  • IT関連
    • ツール開発
    • フロントエンド関連
    • サーバサイド関連
    • WordPress関連
    • ソフトウェア設計
    • おすすめ技術書
  • 音楽
    • DTM
    • 楽器・機材
    • ピアノ
  • ラーメン日記
    • 四コマ漫画
      • その他
        • おすすめアイテム
        • おもしろコラム
      1. ホーム
      2. 20221011_01

      【Unity】WebGL対応した際に発生したエラーまとめ【WebGL】

      UnityWebGL
      2022-10-13

      マイケル
      マイケル
      みなさんこんにちは!
      マイケルです!
      エレキベア
      エレキベア
      こんにちクマ〜〜〜
      マイケル
      マイケル
      今日は開発中のオセロゲームをWebGL対応した際に
      発生したエラーと対処内容
      についてまとめていくぜ!
      エレキベア
      エレキベア
      WebGL対応については確か以前もまとめていたクマね
      マイケル
      マイケル
      そう、前対応した時はビルドが通るようにすればすんなり上手くいったんだけど、
      今回はそれに加えていくつか対応しないといけない箇所があったからまとめてみたんだ!
      エレキベア
      エレキベア
      今回は少しやっかいだったクマね
      マイケル
      マイケル
      それではさっそく見ていこう!

      発生したエラー内容

      マイケル
      マイケル
      対応した内容としては
      ・URPでのビルド時エラー
      ・UTSがWebGL非対応で表示がおかしい
      ・マルチスレッド処理が機能しない

      の3つになります!
      エレキベア
      エレキベア
      結構対応する箇所が出てきたクマね
      マイケル
      マイケル
      なお、今回使用したUnityのバージョンは
      2021.3.1f になります!
      バージョンの差異によってはエラー内容が違ったり、解消されていたりする場合もあるためご注意ください!

      URPでビルドしたらエラー

      マイケル
      マイケル
      一つ目はURPプロジェクトとしてWebGLビルドした際に発生した下記のエラーです。
      Shader error in 'Hidden/kMotion/CameraMotionVectors': SV_VertexID semantic is not supported on GLES 2.0 at line 11 (on gles)
      
      マイケル
      マイケル
      こちらはエラー文言通り、Shaderの一部がGLES2.0(WebGL1)をサポートしていないために発生しているエラーになります。
      エレキベア
      エレキベア
      今は確かWebGL2が主流でWebGL1は非推奨になっていた気がするクマね
      マイケル
      マイケル
      今回は Build Settings – Other Settings から
      Graphics APIs の Auto Graphics APIのチェックを外してWebGL1を削除 することで解決しました!
      ↑Graphics APIsからWebGL1を削除
      エレキベア
      エレキベア
      簡単な対応クマ〜〜

      UTSがWebGL非対応

      マイケル
      マイケル
      さあこれでビルドも通ったし一見落着!
      ・・・と思っていたところ、ゲーム画面を見て異変に気がつきました。
      マイケル
      マイケル
      キャラクター表示がバグっている・・・・
      エレキベア
      エレキベア
      これはひどいクマ・・・
      マイケル
      マイケル
      調べたところ、今回使用させていただいた
      UTS(UnityChanToonShader)はWebGLには非対応 らしく、その影響でバグってしまっているようでした。

      GitHub – UnityChanToonShaderVer2_Project

      エレキベア
      エレキベア
      確かにTargetPlatdformに載っていないクマ・・・
      マイケル
      マイケル
      しかし開発終盤だったこともあり今からシェーダを変えたくないなという気持ちもありました・・・。
      どうにかできないか見ていたところ、どうやら表示がおかしいのはアウトラインのみのようだったため、今回はアウトラインのみ無効にすることで対処できました。
      ↑アウトラインを無効にすることで解決
      エレキベア
      エレキベア
      それだけで済んでよかったクマ・・・
      マイケル
      マイケル
      今回は助かったけど、ちゃんとプラットフォームのサポートは見て決めないといけないなと痛感しました・・・

      マルチスレッド処理が動かない

      マイケル
      マイケル
      さあ今度こそバッチリだぜ!
      そう思いながらオセロをプレイしてみたところ・・・
      ↑止まっている・・・
      マイケル
      マイケル
      今度はオセロを開始した途端にAIが何も反応しないという事象が発生しました・・・
      エレキベア
      エレキベア
      これでは何もできないクマ・・・
      マイケル
      マイケル
      これを調べた結果、WebGLではマルチスレッドが使用できないために、
      スレッドを切り替えて実行している処理は全く動作しない ということが分かりました。
              /// <summary>
              /// モンテカルロ探索処理
              /// </summary>
              private async UniTask<StoneIndex> SearchMonteCarloStoneTask()
              {
                  await UniTask.SwitchToThreadPool(); // 時間がかかるため別スレッドで実行
                  var gameRate = StoneCalculator.GetGameRate(StoneStates);
                  var result = AIAlgorithm.SearchMonteCarloStone(StoneStates, MyStoneState, (int) (150 * gameRate));
                  await UniTask.SwitchToMainThread();
                  return result;
              }
      ↑モンテカルロ等の重い処理はスレッドを切り替えていた
      エレキベア
      エレキベア
      ここに来て高い壁がクマ・・・
      マイケル
      マイケル
      元々重かったからスレッドを分けたわけなので、シングルスレッドに戻すとそれはそれでカクカクしてひどいです。
      つまりマルチスレッド以外の方法で重い処理を対処する必要があります。
      エレキベア
      エレキベア
      むむ・・・どうすればいいクマか・・・
      マイケル
      マイケル
      今回は手を決めるまでの時間を犠牲にして、
      ある程度の処理を行なった後に1フレーム待機させることで対処しました。
      マイケル
      マイケル
      具体的には下記のように対処しています。
      モンテカルロ処理の中で指定回数ゲームを行なって勝利した回数を求める関数になるのですが、一定回数石を置いたら1フレーム待機させるよう、実装しました。

      GitHub – unity-reversi-game-scripts/masarito617 – AIAlgorithm.cs

              /// <summary>
              /// 指定回数ゲームを行い、勝利した回数を返却する
              /// </summary>
              private static async UniTask<int> GetPlayGameWinCountAsync(StoneState[,] stoneStates, StoneState checkStoneState, StoneIndex checkStoneIndex, int playCount, bool isSaveRunOption, CancellationToken token)
              {
                  // 別スレッドでも動作するようSystemの乱数を使用
                  var random = new Random();
                  // 石を置いた数(処理負荷対策チェック用)
                  var checkPutCount = 0;
                  // 勝利した回数をカウントする
                  var winCount = 0;
                  for (var i = 0; i < playCount; i++)
                  {
                      // 勝敗が決まるまでゲームを行う
                      var activeStoneState = checkStoneState;
                      var activeStoneStates = StoneCalculator.GetPutStoneState(stoneStates, activeStoneState, checkStoneIndex.X, checkStoneIndex.Z);
                      while (true)
                      {
                          // 手番を交代して置くことが可能なストーン状態を取得
                          activeStoneState = StoneCalculator.GetReverseStoneState(activeStoneState);
                          var canPutStonesIndex = StoneCalculator.GetAllCanPutStonesIndex(activeStoneStates, activeStoneState);
                          if (canPutStonesIndex == null || canPutStonesIndex.Count == 0)
                          {
                              // 置けなくなったらゲーム終了
                              break;
                          }
                          // ランダムで置く
                          var randomIndex = random.Next(0, canPutStonesIndex.Count);
                          var selectStoneIndex = canPutStonesIndex[randomIndex];
                          activeStoneStates = StoneCalculator.GetPutStoneState(activeStoneStates, activeStoneState, selectStoneIndex.X, selectStoneIndex.Z);
                          // 処理負荷対策:一定回数ごとに1フレーム待つ
                          if (isSaveRunOption)
                          {
                              checkPutCount++;
                              if (checkPutCount >= 200) // この数値を上げると1フレームの処理負荷が上がる
                              {
                                  checkPutCount = 0; // クリア
                                  await UniTask.DelayFrame(1, cancellationToken: token);
                              }
                          }
                      }
                      // 勝利判定を行う
                      if (StoneCalculator.GetWinStoneState(activeStoneStates) == checkStoneState)
                      {
                          winCount++;
                      }
                  }
                  return winCount;
              }
      ↑一定回数石を置くごとに1フレーム待つ
      マイケル
      マイケル
      このようにすることで1フレーム内で行う処理が減り、
      結果として描画負荷を軽減させる
      ことができます。
      マイケル
      マイケル
      厳密には置いた回数より時間を計測した方が効率がいいとは思いますが、
      今回はこれでヨシとします・・・!!
      エレキベア
      エレキベア
      面倒臭かったクマね
      マイケル
      マイケル
      以上、3つの対策で無事WebGLでも動作するようになりました!
      エレキベア
      エレキベア
      やったクマ〜〜〜

      おわりに

      マイケル
      マイケル
      というわけで今回はWebGL対応した際のエラー対応でした!
      どうだったかな??
      エレキベア
      エレキベア
      前回はすんなりいったクマが今回は中々大変だったクマね
      マイケル
      マイケル
      まあスレッド周りは勉強になったけど大変だったね・・・
      マイケル
      マイケル
      みなさんもWebGL対応する際には描画周りとスレッドには気を付けましょう!!
      それでは今日はこの辺で!アデューー!!!
      エレキベア
      エレキベア
      クマ〜〜〜〜

      【Unity】WebGL対応した際に発生したエラーまとめ【WebGL】〜完〜


      UnityWebGL
      2022-10-13

      関連記事
      【Unity】Timeline × Excelでスライドショーを効率よく制作する
      2024-10-31
      【Unity】Boidsアルゴリズムを用いて魚の群集シミュレーションを実装する
      2024-05-28
      【Unity】GoでのランキングAPI実装とVPSへのデプロイ方法についてまとめる【Go言語】
      2024-04-14
      【Unity】第二回 Wwiseを使用したサウンド制御 〜インタラクティブミュージック編〜
      2024-03-30
      【Unity】第一回 Wwiseを使用したサウンド制御 〜基本動作編〜
      2024-03-30
      【Unity】第二回 CRI ADXを使用したサウンド制御 〜インタラクティブミュージック編〜
      2024-03-28
      【Unity】第一回 CRI ADXを使用したサウンド制御 〜基本動作、周波数解析編〜
      2024-03-28
      【Unity】サウンドミドルウェアに依存しない設計を考える【CRI ADX・Wwise】
      2024-03-27