20210607のUnityに関する記事は8件です。

GraphViewで削除可能なノードをすべて消す方法

GraphViewの資料が少ない(QiitaでもGraphViewタグの記事が4つしかない)ので些細な事でもメモしておきます。 全てのノードを消す方法がないかな?と探したところ、 GraphView.cs内のCollectDeletableGraphElements()がちょうど良い感じだったので、移植&一部修正して実装。 MyGraphView.csの一部 ///全てのDeletableなElementを消すボタン押下コールバック private void OnClickDeleteAllDeletableElements() { var elements = new HashSet<GraphElement>(); static bool DeletablePredicate(GraphElement e) => (e.capabilities & Capabilities.Deletable) == Capabilities.Deletable; CollectElements(graphElements, elements, DeletablePredicate); foreach (var graphElement in elements) { RemoveElement(graphElement); } } まとめてRootNode(非deletable)以外を消したいときに使えそうです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity] 画面キャプチャをドライブにアップロードする

概要 Unityエディタ上で画面をキャプチャして、それをファイル出力せずドライブにアップロードする 経緯 UI実装してデザイナーに確認する度にキャプチャをとることが増え、多少なりとも自動化できないかと思い至った 実装 GASでウェブアプリ作ってそれを叩くだけ function doPost(e) { var json = JSON.parse(e.postData.contents); var folder = DriveApp.getFolderById(json.folderId); var blob = Utilities.newBlob(json.data, json.mime, json.fileName); folder.createFile(blob); var text = "upload succeeded"; var output = ContentService.createTextOutput(text); output.setMimeType(ContentService.MimeType.TEXT); return output; } IEnumerator Co(string gasId, string folderId, Action<string> callback) { yield return new WaitForEndOfFrame(); var texture = ScreenCapture.CaptureScreenshotAsTexture(); var data = new PostData { folderId = folderId, fileName = DateTime.Now.ToString("yyyy/MM/dd/HH:mm:ss") + ".png", mime = "image/png", data = texture.EncodeToPNG(), }; var request = new UnityWebRequest( $"https://script.google.com/macros/s/{gasId}/exec", UnityWebRequest.kHttpVerbPOST, new DownloadHandlerBuffer(), new UploadHandlerRaw(Encoding.UTF8.GetBytes(JsonUtility.ToJson(data))) ); yield return request.SendWebRequest(); try { callback(request.downloadHandler.text); } catch (Exception e) { Debug.LogError(e); } } 何番煎じか分からないがとりあえず備忘録的な感じで 加えて細かい設定ができるようにエディタウィンドウ実装したり、フック作って通知したり
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

脱"Unity感" UE4ですか?と言わせるリンク集~ライティング編~

脱Unity=綺麗なライティング 綺麗なライティングとは? 短的に言うと、直接光と間接光を複合的に計算したライティングのことです。と勝手に定義しました。 "Unity感"とは間接光の計算のなさ、ライト強すぎ、などライティングから産まれやがるんや! ライティングの基礎 https://www.youtube.com/watch?v=Ek7vlUTKTNs&t=1976s まずこれを見てください。 概念をめちゃくちゃわかりやすく説明してくれてます。 以降この動画のまとめと補足みたいな感じです。 https://www.youtube.com/watch?v=sA7AQPbXdZ4&t=315s 次にこれを見てください。非常にわかりやすくライティングの実践的な解説があります。 これもお勧め https://www.youtube.com/watch?v=iWf-Y1rTSu0 以下は上記の動画たちのまとめみたいな感じです。 まず基本的にライトはざっくりと リアルタイムライト と 事前計算ライト 2つにわけられます。↓参照 https://docs.unity3d.com/ja/2018.4/Manual/LightingInUnity.html リアルタイムライト 動的だが反射しない (何!?) 事前計算ライト Staticなオブジェクトに対してGI(グローバルイルミネーション)を適用して、計算しておいた光 反射光も含むので綺麗 Staticなオブジェクト や Staticなライトのベイク  によって適用される つまりこいつで"Unity感"を消せそうちゃうか。。? この記事がかなりわかりやすいので詳しくはみてください↓ http://corevale.com/unity/2080 この記事の結論は GIが適用されるのは オブジェクトがStaticであり、リアルタイムGI or ライトのBake が適応されている場合であると言うことです。 グローバルイルミネーション(GI)とは グローバルイルミネーションとは、直接光だけでなく間接光なども考慮したシミュレーションの光。 (enlighten から引用) Progressive Lightmapperと言うもので計算される GIとは何か???という疑問を解決する神資料↓ここまでめちゃわかりやすいの意外とない https://light11.hatenadiary.com/entry/2019/01/27/235637 UnityにおけるGIの処理の流れ 主にリアルタイムGI と Probes と BakeGIの3つで別れる https://docs.unity3d.com/ja/2018.4/Manual/UsingPrecomputedLighting.html Unityにおけるライティングの基本的な処理の方法 一つのオブジェクトに対して、光源が近い順から、ライティングが行われる。 近さや順番によって計算方法が変わる より複雑な計算を求めると、ハイクオリティ設定になる↓ https://docs.unity3d.com/ja/2018.4/Manual/RenderTech-ForwardRendering.html 綺麗なライティングのための設定はどうすれば良いのか LightのBake ライトをBakeする方法と、オブジェクトを軽くする細かい設定↓ https://www.k-youhinten.com/post/lightmap_bake_mina 基本的に背景はStaticにしてGenerativeLightしないと損するや! ワイもしてないアプリを世に出したことあるで!今までの自分を恥じたらあかん。 LightMappingを使用 ライトマッピングは、シーンのサーフェスの明るさを事前計算し、チャートやライトマップに結果を保存して後で使用するための処理 ピンとこない人は、Scene Viewの設定で、GIの処理の1つ1つのフィルターがみれるのでみてみることをお勧めします。 オブジェクトに対するテクセルの大きさなどをみれます。 Progressive Lightmapper ビルド完了まで待たなくても、ある程度完成形が見える 見えていくところから優先して焼かれるGPUにも対応した優れものであるので選択すると良い(現段階ではPreview) 細かい設定などの詳細動画↓ https://www.youtube.com/watch?v=dflNkg0U454 細かい設定の資料↓ 軽くしたい時にみるといいかも https://light11.hatenadiary.com/entry/2019/04/07/214025 Indirect Samples:各テクセルから放たれるサンプル(パス)数。この設定により、プログレッシブライトマッパーが間接光の計算で計上するサンプルの数を制御します。一部のシーン(特に屋外のシーン)では、サンプル数は 100 で十分ですが、屋内のシーン(特に発光ジオメトリを使用している場合)では、より大きな値を指定する必要があります。サンプル数 512 くらいから始めて、最終結果のノイズが多すぎる場合にだけサンプル数を増やしてください。 Lightmap Resolution : こちらで定義したテクセル数が、この単位キューブの各辺に配置されます。 https://unity3d.com/profiles/unity3d/themes/unity/images/eloqua/article/Unity-progressive-lightmapper-optimizations-texel-numbers.jpg Bounces 反射光の跳ね返りの数の決定 Filter Gaussian か A-Trous を選択できる ↓比較画像  主に影に違いがある https://unity3d.com/profiles/unity3d/themes/unity/images/eloqua/article/Unity-progressive-lightmapper-optimizations-filters.jpg リアルタイムGIは、ベイクしたGI と比較して、処理が重い。まぁ当たり前 特定のライトで リアルタイム GI の効果を無効にするには Light ゲームオブジェクトを選択し、Light コンポーネントで Indirect Multiplier を 0 に設定します。 詳しくは↓こちらをみてください。非常にわかりやすくまとめてくれてます。 https://forpro.unity3d.jp/unity_pro_tips/2019/10/30/290/ Lightmap Padding ライトマップの RealTimeShadowColorの調整 リアルタイムに生成される影の色を調整する項目 詳しくはこちら⇩ https://someiyoshino.info/entry/2020/08/16/181046 RefrectionProbeの使用と設定 れfrectionProbeとは、ライトの反射 使い方はこちら⇩ https://light11.hatenadiary.com/entry/2018/07/10/231546 動画の解説はこちら https://www.youtube.com/watch?v=NIAG2QsLqsA LightのModeを選択する ・Modeの種類 RealTime 動的だが、直接光しか計算ができない (何!?) Mixed さまざまな種類がある 後で解説します。 Baked メリット ふわっとした影が作れる(味わいのあるいい感じの影) 間接光の影響でリアルタイムより空間の輝度が上がることもある →(indirect Multiplerを調整すると改善) CPU負荷が軽い 高解像度な影を作成すると必然定期にメモリは圧迫されます →影の品質はLight-Map Resolutionに強く依存しする デメリット 光源情報が失われるので光沢がなくなる(スペキュラーライトが表現できない) これはやばいで。"Unity感"エグくなるからめっちゃ気をつけるんや。 →RefrectionProbeで多少誤魔化せる ダイナミックなオブジェクトには影は落ちない まぁ当たり前 Mixedの種類 MixedLightingの設定の種類 ShadowMask メリット 一番高品質と言える スペキュラーライトも表現できる、ただしボケた影はできない デメリット 重い LightProbeで影響を与えて違和感を数なくすることはできる Distance Shadowmask 距離によって近い物だけに影をつける設定 デメリット 1つのオブジェクトに対して4つ以上の影響するライトがあると、5つ目からBakeされる LightOverlapでどれがBakeされるかは確認することができる(赤がBakeされるライト) BakedIndirect メリット 間接光のみをテクスチャにベイクできる デメリット 遠距離の影は表示できない うん。結局どういう時にどういう設定がいいのか・・?!という疑問に答えてくれる 神資料↓ https://light11.hatenadiary.com/entry/2019/02/03/225210 Shadowの設定 影の解像度 影は一枚のTextureとして処理されます。なので広範囲の影をつけるためにはカスケードを使用して距離に応じた優先順位をつけないといけない。 Shadowの設定項目 Resolution カスケード距離の修正 アーティファクトの修正 用途にあったライトの選択と数値の設定 ここの数値の設定は忘れがちや! ライトオブジェクトの種類 Spot Light 角度のみが影に影響 距離は関係ない 解像度は1で固定なので、広範囲にしすぎると、雑な影になります。 PointLight 距離で品質が変わる 角度は関係ない 6回描画する必要があるため、解像度は低く設定されている 太陽の代わりに使うと品質が落ちるので注意 DirectionalLight どこに位置していても光の強さは変わらない。設定した方向に均一に世界を照らします このライトの色とSkyBoxの色を合わせてないと"Unity感"が出るので注意や! Directional Light の Ambient Color の色を、空の色と同期するのは絶対必須で、よく忘れられるんや。 昼 オレンジの色 夜 濃い青色 にするのがおすすめやで〜 設定項目 DirectionalLightの色は設定しましたか? 光源が足りない場所に、AreaLightをBakeしましたか? Light Probeを配置する シーン内にある小さなオブジェクト(フェンス、電線、チューブ、小物などのテクセルをあまり必要としないオブジェクト)やサイズのわりに表面積が非常に大きいオブジェクト(特に樹木)を照らすには、ライトプローブの使用が有効なもの。 ライトマップがシーン内のサーフェスに当たるライトに関するライティング情報を保持するのに対し、ライトプローブはシーン内のスペースを通過するライトに関する情報を保持します。 主として、ライトプローブは、シーン内の動くオブジェクトに対して質の高いライティング(間接光を含む)を提供します。また、景観に Unity の LOD システムを使用する場合には静的な景観のライティング情報を提供します。 どうやって使ったらええんや? ・基本的にキャラクターの移動範囲全てに散りばめると良い Dynamicなオブジェクトは、間接光が計算されない。なのでそれを補う形でこれを使用する。 ・Light Mapでは表現できない細かいディテールのオブジェクトに使用する Light Probeの使い方はこちら⇩ https://light11.hatenadiary.com/entry/2019/04/08/221444 設定方法 http://tsubakit1.hateblo.jp/entry/2015/01/17/233000 LPPVを使う Light Probe Proxy Volume (LPPV) コンポーネントを使うと、ベイクしたライトマップを使う事が出来ない、大きくて動的なゲームオブジェクト(例えば、大きなパーティクルやスキンメッシュ等)に、ライティングインフォメーションを追加する事ができます。 なんと!Unity感を脱せそうな感じ MeshRendererの光の設定 光の当たり方を2種類を選択できる! GI or Refrection Probe を選ぶことができます。 詳細↓ https://dodagon.com/unity/meshrenderer1 後書き 正直理解がまだまだなので、間違ってる部分多いと思います。 もし僕の理解が間違っていたら訂正メッセージお願いいたします。即座に修正いたします。 今後の予定 カラーグレーディング編 LightProbe編 ポストプロセス編 Terrain編 リフレクションプローブ編 投影マッピング編 VFXGraph編 レンダリング編 を書いていく予定なので、温かい目で応援よろしく願いします。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

脱"Unity感" UE4ですか?と言わせる為の動画リンク集~ライティング編~

脱Unity感=綺麗なライティング 綺麗なライティングとは? 短的に言うと、直接光と間接光を複合的に計算したライティングのことです。と勝手に定義しました。 "Unity感"とは間接光の計算のなさ、ライト強すぎ、などライティングから産まれやがるんや! 異論はもちろん認めます。 読書対象者 Bakeしてない人 Directional LightのColorをいじったことがない人 RefrectionProbe?という人 Light Probe?という人 ライティングの基礎 まず基本的にライトはざっくりと リアルタイムライト と 事前計算ライト 2つにわけられます。↓参照 リアルタイムライト 動的だが反射しない (何!?) 事前計算ライト Staticなオブジェクトに対してGI(グローバルイルミネーション)を適用して、計算しておいた光 反射光も含むので綺麗 Staticなオブジェクト や Staticなライトのベイク  によって適用される つまりこいつで"Unity感"を消せそうちゃうか。。? この記事がかなりわかりやすいので詳しくはみてください↓ この記事の結論は GIが適用されるのは オブジェクトがStaticであり、リアルタイムGI or ライトのBake が適応されている場合であると言うことです。 これらの基礎をまとめて学習できる神動画 多分、ライティングにおいて2021年6月までに存在する日本語と英語の動画資料は全て目を通しました! でその中でも特に見やすかったのを紹介させていただきます。 ライティングのおさらい - Unity道場2019 3月 まずこれを見てください。 概念をめちゃくちゃわかりやすく説明してくれてます。 以降この動画のまとめと補足みたいな感じです。 ライトマップの基礎知識 #1 : リアルタイムライト | Unite Now 2020 次にこれを見てください。非常にわかりやすくライティングの実践的な解説があります。 [Unite 2016 Tokyo]Unityとアセットツールで学ぶ「絵づくり」の基礎(ライト、シェーダー、イメージエフェクト) これもお勧めです。 これは上記の2つをしっかりと覚えているかの確認に使えます! 以下は上記の動画たちのまとめと補足みたいな感じです! グローバルイルミネーション(GI)とは グローバルイルミネーションとは、直接光だけでなく間接光なども考慮したシミュレーションの光。 (enlighten から引用) Progressive Lightmapperと言うもので計算される GIとは何か???という疑問を解決する神資料↓ここまでめちゃわかりやすいの意外とない UnityにおけるGIの処理の流れ 主にリアルタイムGI と Probes と BakeGIの3つで別れる Unityにおけるライティングの基本的な処理の方法 一つのオブジェクトに対して、光源が近い順から、ライティングが行われる。 近さや順番によって計算方法が変わる より複雑な計算を求めると、ハイクオリティ設定になる↓ 綺麗なライティングのための設定はどうすれば良いのか LightのBake ライトをBakeする方法と、オブジェクトを軽くする細かい設定↓ 基本的に背景はStaticにしてGenerativeLightしないと損するや! ワイもしてないアプリを世に出したことあるで!今までの自分を恥じたらあかん。 LightMappingを使用 ライトマッピングは、シーンのサーフェスの明るさを事前計算し、チャートやライトマップに結果を保存して後で使用するための処理 ピンとこない人は、Scene Viewの設定で、GIの処理の1つ1つのフィルターがみれるのでみてみることをお勧めします。 オブジェクトに対するテクセルの大きさなどをみれます。 Progressive Lightmapper ビルド完了まで待たなくても、ある程度完成形が見える 見えていくところから優先して焼かれるGPUにも対応した優れものであるので選択すると良い(現段階ではPreview) 細かい設定などの詳細動画↓ 細かい設定の資料↓ 軽くしたい時にみるといいかも Indirect Samples:各テクセルから放たれるサンプル(パス)数。この設定により、プログレッシブライトマッパーが間接光の計算で計上するサンプルの数を制御します。一部のシーン(特に屋外のシーン)では、サンプル数は 100 で十分ですが、屋内のシーン(特に発光ジオメトリを使用している場合)では、より大きな値を指定する必要があります。サンプル数 512 くらいから始めて、最終結果のノイズが多すぎる場合にだけサンプル数を増やしてください。 Lightmap Resolution : こちらで定義したテクセル数が、この単位キューブの各辺に配置されます。 Bounces 反射光の跳ね返りの数の決定 Filter Gaussian か A-Trous を選択できる ↓比較画像  主に影に違いがある https://unity3d.com/profiles/unity3d/themes/unity/images/eloqua/article/Unity-progressive-lightmapper-optimizations-filters.jpg 詳しくは↓こちらをみてください。非常にわかりやすくまとめてくれてます。 RealTimeShadowColorの調整 リアルタイムに生成される影の色を調整する項目 詳しくはこちら⇩ RefrectionProbeの使用と設定 ざっくりいうとRefrectionProbeとは、水面やコップなどに環境を反射させるのに使えるものです。 使い方はこちら⇩ 動画の解説はこちら LightのModeを選択する ・Modeの種類 RealTime 動的だが、直接光しか計算ができない (何!?) Mixed さまざまな種類がある 後で解説します。 Baked メリット ふわっとした影が作れる(味わいのあるいい感じの影) 間接光の影響でリアルタイムより空間の輝度が上がることもある →(indirect Multiplerを調整すると改善) CPU負荷が軽い 高解像度な影を作成すると必然定期にメモリは圧迫されます →影の品質はLight-Map Resolutionに強く依存しする デメリット 光源情報が失われるので光沢がなくなる(スペキュラーライトが表現できない) これはやばいで。"Unity感"エグくなるからめっちゃ気をつけるんや。 →RefrectionProbeで多少誤魔化せる ダイナミックなオブジェクトには影は落ちない まぁ当たり前 Mixedの種類 MixedLightingの設定の種類 ShadowMask メリット 一番高品質と言える スペキュラーライトも表現できる、ただしボケた影はできない デメリット 重い LightProbeで影響を与えて違和感を数なくすることはできる Distance Shadowmask 距離によって近い物だけに影をつける設定 デメリット 1つのオブジェクトに対して4つ以上の影響するライトがあると、5つ目からBakeされる LightOverlapでどれがBakeされるかは確認することができる(赤がBakeされるライト) BakedIndirect メリット 間接光のみをテクスチャにベイクできる デメリット 遠距離の影は表示できない うん。結局どういう時にどういう設定がいいのか・・?!という疑問に答えてくれる 神資料↓ Shadowの設定 影の解像度 影は一枚のTextureとして処理されます。なので広範囲の影をつけるためにはカスケードを使用して距離に応じた優先順位をつけないといけない。 Shadowの設定項目 Resolution カスケード距離の修正 アーティファクトの修正 用途にあったライトの選択と数値の設定 ここの数値の設定は忘れがちや! ライトオブジェクトの種類 Spot Light 角度のみが影に影響 距離は関係ない 解像度は1で固定なので、広範囲にしすぎると、雑な影になります。 PointLight 距離で品質が変わる 角度は関係ない 6回描画する必要があるため、解像度は低く設定されている 太陽の代わりに使うと品質が落ちるので注意 DirectionalLight どこに位置していても光の強さは変わらない。設定した方向に均一に世界を照らします このライトの色とSkyBoxの色を合わせてないと"Unity感"が出るので注意や! Directional Light の Ambient Color の色を、空の色と同期するのは絶対必須で、よく忘れられるんや。 昼 オレンジの色 夜 濃い青色 にするのがおすすめやで〜 設定項目 DirectionalLightの色は設定しましたか? 光源が足りない場所に、AreaLightをBakeしましたか? Light Probeを配置する シーン内にある小さなオブジェクト(フェンス、電線、チューブ、小物などのテクセルをあまり必要としないオブジェクト)やサイズのわりに表面積が非常に大きいオブジェクト(特に樹木)を照らすには、ライトプローブの使用が有効なもの。 ライトマップがシーン内のサーフェスに当たるライトに関するライティング情報を保持するのに対し、ライトプローブはシーン内のスペースを通過するライトに関する情報を保持します。 主として、ライトプローブは、シーン内の動くオブジェクトに対して質の高いライティング(間接光を含む)を提供します。また、景観に Unity の LOD システムを使用する場合には静的な景観のライティング情報を提供します。 どうやって使ったらええんや? ・基本的にキャラクターの移動範囲全てに散りばめると良い Dynamicなオブジェクトは、間接光が計算されない。なのでそれを補う形でこれを使用する。 ・Light Mapでは表現できない細かいディテールのオブジェクトに使用する Light Probeの使い方はこちら⇩ 設定方法 LPPVを使う Light Probe Proxy Volume (LPPV) コンポーネントを使うと、ベイクしたライトマップを使う事が出来ない、大きくて動的なゲームオブジェクト(例えば、大きなパーティクルやスキンメッシュ等)に、ライティングインフォメーションを追加する事ができます。 なんと!Unity感を脱せそうな感じしますよね。 MeshRendererの光の設定 光の当たり方を2種類を選択できる! GI or Light Probe を選ぶことができます。 詳細↓ 後書き 正直理解がまだまだなので、間違ってる部分多いと思います。 もし僕の理解が間違っていたら訂正メッセージお願いいたします。即座に修正いたします。 今後の予定 カラーグレーディング編 LightProbe編 ポストプロセス編 Terrain編 リフレクションプローブ編 投影マッピング編 VFXGraph編 レンダリング編 を書いていく予定なので、温かい目で応援よろしく願いします。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Azure上でUnityWebGLとPlayCanvasを動かしてみた。

※深いお話は全く以て出てきません。予めご了承ください。 はじめに 普段はUnityクライアントサイドを担当しています。Webの知識ほぼゼロのペーペーです。 仕事の関係でWebGLを調べる事になったので、鶏の如く忘れてしまう自分の為にも、備忘録も兼ねてまとめておきたいと思います。 目的 とりあえずAzure App Service上で、ユーザの入力によりカメラが自由に動かせる、移動できる程度のゲームがWebGLで動いているのを確認できればヨシ。 Azureを選択した理由は特に無いのですが、以前先輩社員の方から少し教わったことがあるので、今回はAzureを利用します。 VisualStudioからポチポチするだけでも良いので便利便利! ところでWebGLとは? まずは、さらっと WebGL(Web Graphics Library) についておさらいしてみます。 前提知識としてWebGLには、土台となる OpenGL と呼ばれるライブラリがありますので、まずはそちらから。 OpenGLとは OpenGL(オープンジーエル、Open Graphics Library)は、クロノス・グループ (英: Khronos Group) が策定している、グラフィックスハードウェア向けの2次元/3次元コンピュータグラフィックスライブラリである。SGI社内で自社のCGワークステーション向けにクローズドに策定されたAPI仕様が改良されて公開され、後に大きなシェアを持つに至った。現在は多様な描画デバイスを包括するグラフィックスAPIのオープン標準規格として策定が行なわれている。1 グラフィックスハードウェアとは、GPUだと思って頂いてほぼ問題ないと思います。2 簡単に表すのであれば、「GPUを使う事で簡単に2D/3Dが描画できるライブラリ」と言った所でしょうか。 よくDirectXと比較されるライブラリなので、ご存知の方も多い事でしょう。 このOpenGLのサブセットとして、 OpenGL ES というモノもあります。 OpenGL ES とは OpenGL ES(OpenGL for Embedded Systems)は、主に携帯電話などの組み込みシステムで使用されている3次元コンピュータグラフィックス用 API である。OpenGL ESは、従来から存在する(主にデスクトップPCやワークステーション向けの)クロスプラットフォームなリアルタイム3DグラフィックスAPIである OpenGL のサブセットである。3 Embedとは「埋め込む、はめ込む」等の意味を持つ単語です。 OpenGL の for Embedded Systems (組み込みシステム用) という名前の通りのモノですね。 そして、OpenGL のサブセットである OpenGL ES から派生したのが WebGL です。 WebGLとは WebGL(ウェブジーエル、Web Graphics Libraryの略称)は、互換性のある任意のウェブブラウザ上で、プラグインを使用せずにインタラクティブな2次元および3次元のコンピュータグラフィックをレンダリングするためのJavaScript APIである。 4 さて、こちらも凄いザックリ要約すると、「ブラウザ上で2D/3Dを描画したい時に便利なライブラリ」という事ですね。ええ。そうでしょう。多分。 ブラウザ上で という事なので、ブラウザが対応してくれなければ、どうしようもありません。 そんな WebGL の最新版は2021年6月現在、Ver2.0となっており、主要なブラウザは基本的には対応済みのようです。 WebGL2.0の各ブラウザ対応状況をcaniuseで試しに調べた所はこんな感じです。(緑がsupportedとなります。) Safari on iOSの欄が非常に不安な赤色をしていますが、気持ちの問題です。 嘘です。リンゴでも齧りながら、対応される事を祈りましょう。 OpenGL・WebGLの詳細等はネット上で詳しく書いて下さってる方も沢山いらっしゃいますし、wikiにも結構な情報が載っているので気になる方は是非調べてみて下さい。 どうやって実現させるか WebGLを使うと一言で言っても手段が沢山あります。 軽く調べただけで下記の選択肢が見つかりました。 1. そのままゴリゴリ書く。 シェーダー自体はGLSL(OpenGL Shading Language)と呼ばれる言語を用います。 そこに JavaScript や HTML/CSS を合わせる事により、ブラウザ上で 2D/3D の描画を実現させます。 ワイはゴリゴリゴリラになるんや!という方はこちらのサイトのWebGL用ページが参考になると思います。 ゴリラにならない方でも非常に参考になります。 また、目的によってはこの方法がベストな時もあると思います。 2. Three.jsを使って書く WebGLをラップしたライブラリと言った所でしょうか。 WebGLをそのまま書くより断然手間が減っています。 Three.jsは日本語の情報が豊富という点も、非常に手を出しやすそうです。 すごい!偉大なる先人達の余沢。有難く使わせて頂くべきでしょう。 3. Unity等のゲームエンジンを用いてWebGL用にビルドする。 実は普段から使っているUnityでも、WebGLのビルドができるんです! また、同様にUnrealEngineでもWebGLのビルドが一応5 可能っぽい。 おぉ、コレは使い慣れてるUnityが早そうだ・・。 4. WebGL用のゲームエンジンを使う。 今回の目的は 簡単なゲームを動かす事なので、WebGL用のゲームエンジンを使うのが一番良いでしょう。 なんと、3Dに強くGUIがしっかり整備されている PLAYCANVAS というゲームエンジンがあるらしいではありませんか。 使う前から手っ取り早く目的を実現できる予感がビンビンします。 今回はWebGL初心者の私でも出来そうな、 3. Unity等のゲームエンジンを用いてWebGL用にビルドする。(今回はUnityを使用) 4. WebGL用のゲームエンジンを使う。(PlayCanvasを使用) の二つのアプローチを試してみようと思います。 実践 UnityWebGL (今回はUnity 2021.1.7f1を使用します。) まずはUnityHubからプロジェクトを作成しますが、注意点としてはHDRPはWebGLに対応していません。 UnityはBRPに変わる次の標準RPとしてURPを推しています。6 各Render Pipelineの詳細については割愛しますので、よくわからないという方はとりあえずURPを選択しましょう。 暫く待つとUnityEditorが開きます。 このサンプルシーンは既にキーボードとマウスの入力でカメラが動くように作られています。 試しにプレイボタンを押して確認してみましょう。 ウン。もういいわコレデ。 という事でビルドの準備をしましょう。 左上のメニューからFile > BuildSettingsを開きます。 Platformの欄からWebGLを選択します。 WebGLのモジュールが入ってない方はInstall with UnityHubというボタンを押し、UnityHubからWebGLのモジュールを入れましょう。 Switch Platformを押しましょう。 暫くするとSwitch Platformが終わります。 いよいよビルドです。 DevelopmentBuild この項目のチェックが外れていることを確認します。この項目にチェックがついている場合は、圧縮されません。つまりサイズがでかいです。開発を終えたらチェックを外してビルドしましょう。 CodeOptimization ビルド後のサイズ重視か速度重視かの選択だと思います。とりあえずSizeにでもしておきましょう。 また、左下の PlayerSettings... というボタンから、細かい設定が可能です。各設定項目についてはこちらを参照してください。(サイトの左上を見てUnityのVerが自分の環境と一致しているか確認を忘れずに!) Azureを利用する場合、レスポンスヘッダー見た限りだと多分デフォルトで良い感じにgzipの対応をしてくれてます。gzipエンコードが多重に起きる場合、PublishingSettings内のCompressionFormatをDisabledにすると良いかもしれません。 設定が終わった方はBuildSettingsからBuildAndRunボタンを押しましょう。ビルド完了後にwebGLの確認が出来ます。 注意ポイント Unityを使用する場合はWebGLとして公開するにあたっていくつかの注意するべき事があります。 当然ですがビルドサイズに応じて、コンテンツ開始までのロード時間が伸びます。 Unityの公式マニュアルにビルドサイズ削減のヒントと、WebGL用のコツが載っていますので是非確認してみて下さい。また、WebGLのパフォーマンスについてはこちらのページを参照してください。 通信が必要な場合はクロスドメイン制約7 に気を付ける必要があります。 適切なメモリ管理を行う為にはAssetBundleを使う必要があります。AssetBundleを使用しない場合、コンテンツ実行中は全てのリソースがブラウザの使用するメモリ空間に非圧縮の状態で展開されます。 これにてUnityでの作業は終了です。 次にPlayCanvasの作業をします。 実践 PlayCanvas 次にPlayCanvasで試してみましょう。 まずは公式サイトでアカウントを作成し、ログインします。 恐らくアカウントを作ったばかりの人は、My First Projectというプロジェクトが強制で作成され、 自動的にEditorページに遷移します。 MainSceneを選択しましょう。 この初期プロジェクトは、「キーボードの入力によりボールが板の上を転がる」だけなのですが、PlayCanvasの基礎を知るには丁度良いプロジェクトになっているので、初めての方は色々確認してみましょう。 基本的なGUIに関してはUnityと同じです。 とりあえずキーボード入力(Arrowキー)で動くので今回はこのままPublishしてみます。 Editor画面左上のPlayCanvasマークから、Publishingを選択します。(または、PlayCanvasマークの下にある矢印マークでも大丈夫です。) 今回はPublish To PlayCanvasを選択します。 するとゲームの設定をするウィンドウが開くので、 タイトルやVersion、ゲームの説明等諸々を設定したらPublishNowを押します Publishが終わったものは、Buildsの欄に登録されていると思います。 今回Publishした ビルドを押してみましょう。 ブラウザ上で先ほど公開したゲームが動いていることが確認できます。 注意ポイント PlayCanvasを使用するにあたり気を付けるポイント PlayCanvasEngineが使用するメモリ量はUnity等に比べて少ない8ですが、ビルドサイズの削減やメモリは意識しましょう。公式運営サイトでPlayCanvasBlogの記事を翻訳してくれています。様々なTips 9 が載っているので確認してみると良いかもしれません。 日本語の情報はまだそれほど多くないです。実践的なテクニックや詳しい内容はフォーラムで調べると良いかもしれません。 無料ライセンスの場合、合計ProjectSizeに制限があります。現在どれほど使用しているかは、ユーザページから確認できます。 これにてPlayCanvasでの作業は終了です。 最後にUnityWebGL製ゲームと、 PlayCanvas製ゲームをWeb上に載せてみます。 Azureの設定 ※他のクラウドサービスを使うよ!って方は飛ばしてください。 アカウントをお持ちでない方はMicrosoftAzure公式サイトから 無料アカウントを作りましょう。 次にVisualStudioを使い、Azure用のプロジェクトを作ります。 Visual Studio Installerを起動し、 ASP.NETとWeb開発、Azureの開発 のモジュールを選択し、VisualStudio2019 をインストールします。 インストール済みの方は変更ボタンから同様のモジュールをインストールします。 インストールが終わり次第、VisualStudio2019を起動します。 起動後、新しいプロジェクトの作成を選択し、ASP.NET Core Web アプリケーション を選びます。 見つからない場合は、プロジェクトの種類をクラウドにするとすぐに見つかります。 プロジェクト名などを決めたら、テンプレートの選択です。 今回は ASP.NET Core Web アプリ(Model View Controller) を選択します。 また、特にこだわりが無ければASP.NET Core 5.0にして作成を押します。 VisualStudioが開いたら、とりあえずWebサイトがどんなもんか確認してみましょう。 1. 公開ボタンを押す 2. 開始ボタンを押す 3. ターゲットAzureを選択し、次へ 特定のターゲットの選択で Azure App Service (Windows) を選択し次へ。 この画面が出たら右上から先ほど作ったAzure用の無料アカウントでサインインします。 (※Azure Portal上で既にAppServiceインスタンスを作っている方は飛ばしてください。) サブスクリプションが無料試用版である事を確認したら、AppServiceインスタンスの右側にある +ボタンを押しましょう インスタンス名をお好きな名前に変更し、 リソースグループの欄で新規を押します。するとリソースグループ名を入力するダイアログが出るので、好きなように命名して下さい。 ホスティングプランの欄でも新規を押します。先ほどと同じ様にホスティングプラン名を命名し、 場所を選択します。(今回は適当にJapanEastかJapanWestにしておけばイイトオモイマス。) サイズはFreeを選択します。Freeってなんやねんと不安になると思いますので、こちらで確認できます。少なからず私は不安になりました。 全て選択が終わったら、OKを押して閉じていきます。 先ほど作ったAppServiceインスタンス が選択出来ていることを確認したら、完了ボタンをおします。 これでVisualStudioとAppServiceの連携は完了しました。 発行ボタンを押して、デプロイしてみましょう。 正常にデプロイが完了した場合このようなサイトが表示されます。 最後にUnityWebGLとPlayCanvasを埋め込みます。 Azure上でUnityWebGLを動かす 実践UnityWebGLの欄で作成したビルド一式(Buildフォルダ、TempleteDataフォルダ、Index.html)をコピーし、VisualStudio上の任意のディレクトリ配下に置きます。 (今回は分かりやすさ重視でwwwroot直下にWebGLフォルダを作り、その中に置きます。) また、WebGLフォルダ内のindex.hetmlを分かりやすくする為に、unitywebgl.htmlという名前にリネームします。 また、Azureを利用する方でUnityWebGLビルド時にCompressionFormatをDisabledにした方は、WebGL\Build\bin.dataだけは手動でgzip化しておきましょう。(AzureAppServiceでもweb.configとかで自動でできるとは思うのですが...何方か詳しい方情報お待ちしております。) 手動でbin.dataのみをgzip化した場合はunitywebgl.htmlの61行目にあるbuildUrlのリテラルを変更する必要があります。 "/bin.data" → "/bin.data.gz" ソリューションエクスプローラーからwwwroot配下のcssフォルダを右クリックし、追加から新しい項目を選択します。 別ウィンドウが開くのでスタイルシートを選択し新しく作成したcssファイルをwebgl.cssにリネーム。 適当にiframeが中央に来るように書いておきます。 webgl.css .Unity-Webgl { height: 800px; display: flex; justify-content: center; } #unity-frame { height: 80%; width: 90%; border: 0; } 次にViews\Homeの下にあるindex.cshtmlを編集します。 index.html @{ ViewData["Title"] = "Home Page"; } <head> <link rel="stylesheet" href="~/css/webgl.css"> </head> <body> <div class="Unity-Webgl"> <iframe id="unity-frame" src="~/WebGL/unitywebgl.html"></iframe> </div> </body> index.htmlの編集が終わり次第、再度デプロイします。 ソリューションエクスプローラーからプロジェクト名を右クリックし、発行を選択します。 公開設定のタブが開くと思うので、再度発行を押せば、サイトに反映されます。 サイトURLへ飛んでみて確認しましょう。 ウン。動いてそう。 Azure上でPlayCanvasを動かす Views\Home内のindex.cshtmlを編集します。 PlayCanvas上でPublishしたゲームのURLをiframeの中に組み込むだけです。 index.cshtml @{ ViewData["Title"] = "Home Page"; } <head> <link rel="stylesheet" href="~/css/webgl.css"> </head> <body> <div class="PlayCanvas-Webgl"> <iframe id="playcanvas-frame" src="{PlayCanvasでpublishしたゲームの}"></iframe> </div> </body> 編集が終わったらUnityWebGLの時と同じ手順でデプロイし、サイトで確認してみます。 動いてる。むっちゃ簡単。しゅごい。 モバイルでも確認してみると良いかもしれまセン。 おわりに ということで無事、UnityWebGLとPlayCanvasを用いる事でAzure上で簡単なゲームがWebGLで動くのを確認できました。 初めてWebGLを触ってみましたが、何かしらのフレームワークを利用することで、特別新しい事を覚えなくても簡単にゲームをブラウザ上で動かす事が可能だと分かりました。 実務でやるとなれば、当然ゲームを作る過程や、メモリ管理やらビルドサイズ削減やらで非常に時間はかかってしまうと思います。 が、1からWebGLのみで3Dのゲームを作るよりは早いハズ。 ということで、使えるものはガンガン使っていきましょう。 長文を最後まで読んでいただき、ありがとうございました。 間違いのご指摘や、「ここはこうした方が良い」等ありましたら、コメント欄にてご教授・ご教示頂けると大変助かります。 余談 Azure無料アカウントを作成した方は 一応無料アカウントのFAQを読んでおくと良いかもしれません。 WebGLの技術は様々な事に使えそうですね。ブラウザ上で3dの地図を表示するCesium等、面白そうなものも沢山あります。 OpenGL Wikipediaより引用 ↩ 厳密にはGPUはグラフィックスハードウェアそのものを指す言葉ではありません。詳しくは GPU Wikipedia と 電子情報通信学会『知識の森』の 2群-3編-4章を参照してください。 ↩ OpenGL ES Wikipediaより引用 ↩ WebGL Wikipediaより引用 ↩ 公式ドキュメントを見ての通り、UEはWebGL専用の資料があまり用意されていない事から、対応が進んでいないように思えます。 ↩ Unityの次の標準レンダリングパイプライン "Universal Render Pipeline" は何がどう変わるのか より ↩ セキュリティの観点からドメインが二つ以上にまたがっている状態では制約が課されます。解決策はUnityの公式マニュアルを参照。 ↩ 公式サイト曰く、170kb ↩ テクスチャ圧縮話や、歴史話等もあります。 ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

(Unity)SimpleSQL使用時の「DllNotFoundException: sqlite3」エラー対応

UnityでSQLiteを使うに当たって、評価の高い「SimpleSQL」を使ってます。 これまでiOS向けにしかビルドを試していなかったので、Android向けにビルドしたところ以下のエラーが。。。 E/Unity: DllNotFoundException: sqlite3 ググったところ、Plubinsフォルダの配下に以下のフォルダを用意し、 libsqlite3.soを三つのフォルダそれぞれにいれる arm64-v8a armeabi-v7a x86 との先人の記事が出てきたため、試行しましたが上手くいかず。。。 そこでSimpleSQLのドキュメントをよく読むことに(当然ですね) 解決方法 メニューから、Tool > SimpleSQL > Option を選択 ここで、Optimize PlatformからAndroidを選択するとAssets直下に以下のフォルダが自動で作成され、 sqlite-android-328000が配置されます。 Plugin/Android/sqlite-android-3280000 これで解決します... 結論、ドキュメントをよく読めってことです。。。 ではでは。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity]Swift だけで作ったNative PluginでUnityにSendMessage

Swift だけで作った Native Plugin で Unity に SendMessage Swift だけで、Unity の iOS の Native Plugin を作る方法を紹介しました Swift から Unity へコールバックしたい場合がよくあります Unity の Native Plugin のドキュメントには、UnitySendMessage を使う方法が紹介されています UnitySendMessage を使うと、とても容易にコールバックを実装可能です ゲームオブジェクト名、スクリプト名、呼び出されたメソッドに渡す文字列を指定します UnitySendMessage("GameObjectName1", "MethodName1", "Message to send"); これを Swift だけで作った Native Plugin から呼び出す話です 今回のサンプル リポジトリはこちらです Swift だけで、Unity の iOS の Native Plugin を作る の内容を前提知識にしています 処理の流れ Unity で実行されるゲームオブジェクトとスクリプトを用意する == ここまで C# ここから Swift === Swift で、UnityFramework を読み込む UnityFramework を使って、UnitySendMessage を実行する Unity の実装 最終目標 "Cube" オブジェクトの "Sent" 関数に任意の文字を渡して実行することを目標とします public class Cube : MonoBehaviour { public void Sent(string message) { Debug.Log("Sent message -> " + message); } } これで UnitySendMessage からメッセージを受け取る事が可能です Swift の実装 やること UnityFramework.framework には、UnityFramework クラスが実装されています UnityFramework のシングルトンのインスタンスを利用します sendMessageToGO 関数を呼ぶと UnitySendMessage が実行されます let objectName = "Cube" as NSString let scriptName = "Sent" as NSString let message = "Hello" as NSString UnityFramework.getInstance() .sendMessageToGO(withName: objectName.utf8String, functionName: scriptName.utf8String, message: message.utf8String) 実装計画 Framework を事前にビルドする形だと、ビルド時に UnityFramework とリンクできません そのため、事前にビルドした Framework から名前を指定して実行します UnityFramework のシングルトンのインスタンスを取得する UnityFramework.framework の PrincipalClass として UnityFramework クラスが設定されているので利用します getInstance の値を名前を指定して取得します let bundlePath = Bundle.main.bundlePath.appending("/Frameworks/UnityFramework.framework") let bundle = Bundle(path: bundlePath)! let principalClass = bundle.principalClass as! NSObject.Type let unityFramework: NSObject = principalClass.value(forKey: "getInstance") as! NSObject これで、UnityFramework.getInstance() に相当する処理を実装できました sendMessageToGOWithName:functionName:message を実行する やりたいこと 上で取得した unityFramework インスタンスで sendMessageToGOWithName の関数を実行したいです この関数を名前を指定して実行します unityFramework.sendMessageToGO(withName: objectName.utf8String, functionName: scriptName.utf8String, message: message.utf8String) 文字列から関数を実行する class_getMethodImplementation で IMP を取得し、unsafeBitCast を使って、methodType にキャストして実行します sendMessageToGOWithName は引数として、char* を受け取るので、Swift で同等の UnsafePointer<CChar> として実行します private func callInstanceMethod<T: NSObject>(targetInstance: T, selector: Selector, argCStr1: UnsafePointer<CChar>, argCStr2: UnsafePointer<CChar>, argCStr3: UnsafePointer<CChar>) { typealias methodType = @convention(c) ( Any, Selector, // args UnsafePointer<CChar>, UnsafePointer<CChar>, UnsafePointer<CChar> ) -> Void let methodImplementation: IMP = class_getMethodImplementation(type(of: targetInstance), selector)! let methodInvocation = unsafeBitCast(methodImplementation, to: methodType.self) methodInvocation(targetInstance, selector, argCStr1, argCStr2, argCStr3) } 実行 sendMessageToGOWithName 関数のセレクタの sendMessageToGOWithNameSelector を作成します unityFramework のインスタンスで、sendMessageToGOWithNameSelector を実行します let sendMessageToGOWithNameSelector: Selector = NSSelectorFromString("sendMessageToGOWithName:functionName:message:") callInstanceMethod(targetInstance: unityFramework, selector: sendMessageToGOWithNameSelector, argCStr1: ("Cube" as NSString).utf8String!, argCStr2: ("Sent" as NSString).utf8String!, argCStr3: ("from send message" as NSString).utf8String!) Framework の出力と設定 こちらの記事の Framework でビルドする の章以降と同じ手順で実行ビルド可能です callInstanceMethod を実行したときに、Cube.Sent が指定した引数で実行されていることを確認します おわりに UnitySendMessage は Unity で複雑な実装をせずに、Swift から Unity へコールバックする事が可能です 1frame 遅れたり、文字列1つしか送れない、などが問題ない場合は十分に利用する事が可能だと思います Swift から Unity コールバックするのは、応用の幅が広いので、活用して行きたいです
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity(C#)】unityroomにカメラを使ったゲームを公開する

はじめに Unity1Weekという1週間ゲームジャムに参加し、 カメラを使ったゲームを開発しました。 一応、遊べるレベルまで完成しましたが、他の環境でもちゃんと動くのかが心配です?#unityroom #unity1week pic.twitter.com/1gwXC7Bf2M— KENTO⚽️XRエンジニア?Shader100記事マラソン挑戦中36/100 (@okprogramming) May 4, 2021 口を開けるとオジサンが笑いながらジャンプします。 前例が無い中、いろいろと問題を解決してようやく公開できたので 同じ苦労する人が減ることを願いメモします。 カメラへのアクセス unityroomでカメラを使ったゲームを公開できるかどうかの調査から行いました。 カメラのアクセスを試みるにあたって、 jsのプラグインを作ったりといろいろ検証してました。 結論、iframeで画面にWebGLを埋め込んでいる現時点(2021/06)の形式では こちらから何かしら手を加えてカメラにアクセスすることはできなかったです。 なので、運営の方に直接問い合わせて許可をいただき、 埋め込まれたリンクを直指定してWebGLを開く形式で対応しました。 概要欄に「ここから遊んでね!」みたいなのを書くというやり方です。 jsプラグイン カメラへのパーミッション要求はWebCamTextureを呼び出すなど、 カメラを必要とする関数に紐づいて勝手に要求処理が走るのですが、 せっかくなので勉強がてらjsのプラグインを作成してパーミッション要求を行ってみました。 以下C#側からjsを呼び出すサンプルです。 まず.jslibという拡張子のファイルを作成し、そこにjsの処理を記述します。 保存先ディレクトリはAssets/Plugins配下です。 カメラのパーミッション要求 mergeInto(LibraryManager.library, { CameraRequest: function () { var constraints = { audio: false, video: { width: 640, height: 480 } }; navigator.mediaDevices.getUserMedia(constraints) .then(function (mediaStream) { var video = document.querySelector('video'); video.srcObject = mediaStream; video.onloadedmetadata = function (e) { video.play(); }; }) .catch(function (err) { console.log(err.name + ": " + err.message); }); }, }); 次にC#側のコードです。クラス名がjsと一致していればOKです。 任意の箇所で呼び出し可能です。私はCameraRequest()をボタン押下時に呼び出すよう実装しました。 [DllImport("__Internal")] private static extern void CameraRequest(); 【参考リンク】:Unity2020でWebGLを試してみた! ~基本編~ OpenCV カメラの問題は片付きました。 次に、OpenCVで顔の認識を行うサンプルがWebGLで問題なく動作するか検証しました。 下記のサンプルをほぼそのまま流用しました。 【参考リンク】:FaceTracker Example ただ、結論から言うとFPSが安定しませんでした。 何か削れる処理や軽量化に繋がる画期的方法が無いか模索しましたが、 サンプルそのままでもさほど安定していなかったので限界と判断し早急に諦めました。 model及びcascadeの読み込み OpenCVではモデルデータと識別器(cascade)の読み込みが必要で、 WebGLの場合はStreamingAssetsとしての利用が可能な実装になっていました。 現時点でunityroomにおいてStreamingAssetsは使用できないため、 Gistにプライベート(リンクを知っている人のみアクセス可)で公開し、参照するようにしました。 【参考リンク】:UnityroomではStreaming Assetsは使えないのでしょうか? 工夫した点 顔の認識が確認できた以降の実装では キャラクターがジャンプする処理などを追加して挙動を確認していきました。 ステージがクリア不可能でないか等を動かしてデバッグする際に カメラを付けて口をパクパクして...というのが面倒だったので 入力機能をモジュール化してキー入力と顔入力を切り替えれるようにしました。 DIライブラリにはVContainerを使用しました。 おわりに unity1weekはエンジニアになって以来、 毎回新しいことに取り組む場として活用させていただいています。 1週間の中盤~終盤にかけて参加したことを後悔する(己の実装力に心が折れる)瞬間もありますが、 他の方の頑張りをSNS等で拝見して自分に鞭を打ちながら毎回走り切れています。(ほぼ遅刻) 運営の方はもちろんのこと、参加者の方、遊んでくれた方、みなさんありがとうございます。 次回も楽しみにしています。 参考リンク 「OpenCV for Unity」AssetのWebGL対応がやって来たヤァ!ヤァ!ヤァ!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む