UNITYのWebGLコンテンツで3DコンテンツをWEBブラウザで稼働させ、そのコンテンツからパノラマ画像を生成し、ローカルPCに画像を保存する方法についてです。
目的はUNITYで作成したWebGLコンテンツをWEB上で公開するにあたり、ユーザーが自由にゲーム中のシーンのパノラマ画像を取得できるインターフェースを提供することです。
記事でのUNITYバージョンは2019.1.6f1、WebGL Build Supportとします。
また、環境はWindows10、ブラウザはChromeとします。
[File:Build Settings]を開きます。
[Platform]の項目からWebGLを選択します。
右下にある[Switch Platform]をクリックし切り替えます。
これでWebGLコンテンツのビルドができるようになります。
試しに素の状態でbuildができるか試してみます。
※結構時間がかかりますが、工程を進めてbuildできないということになるとダメージ大なので試してみることをお勧めします。
[File:Build and Run]を開きます。
現在のプロジェクトのフォルダが開きますので、例えば[build]というディレクトリを作成します。
[build]のディレクトリを選択し[フォルダーの選択]をクリックするとビルドが開始します。
PCのグレードによりますが、かなり待つとChromeでWebGLコンテンツが開きます。
素の状態なのでSkyBoxとダイレクトライト、Main Cameraしかありません。
したがって上記のような画像が表示されるだけです。
[Build and Run]でWebGLビルドを行うと初回だけなぜかChromeで実行できるのですが、二回目以降ではローカルのビルド成果物をChromeで実行できません。
動作確認を行うにはWebサーバーにアップロードしてChromeで確認しています。
パノラマ画像の作成ですが、「360-screenshot-capture」という無料アセットを使わせていただきます。
https://assetstore.unity.com/packages/tools/camera/360-screenshot-capture-112864
インポートします。
空のゲームオブジェクトを作成します。
適当に分かりやすい名前に変更します。
ここではEmptyGameObjectとします。
適当なアクセス可能なフォルダに”Panorama.cs”というスクリプトファイルを生成します。
今回はAssets/Plagin/Simple360Render配下に生成します。
“Panorama.cs” を以下のように編集します。
using System.IO;
using UnityEngine;
#if UNITY_WEBGL
using System.Runtime.InteropServices;
#endif
public class Panorama : MonoBehaviour
{
#if UNITY_WEBGL
[DllImport("__Internal")]
private static extern void FileDownLoad(byte[] bytes, int size, string filename);
#endif
public int imageWidth = 4096;
public string filename = "skyonsea_panorama.png";
private bool saveAsJPEG = false;
// LateUpdate is called once per frame
void LateUpdate()
{
if (Input.GetKeyDown(KeyCode.P))
{
byte[] bytes = I360Render.Capture(imageWidth, saveAsJPEG);
if (bytes != null)
{
#if UNITY_EDITOR
string path = Path.Combine(Application.persistentDataPath, filename);
File.WriteAllBytes(path, bytes);
Debug.Log(filename + " has been saved into " + path);
#elif UNITY_WEBGL
FileDownLoad(bytes, bytes.Length, filename);
#endif
}
}
}
}
Assets/Plugins/WebGL というディレクトリを作成し、以下のコードを “FileDownload.jslib” というファイルネームで保存します。
var FileDownloadPlugin = {
FileDownLoad: function(pImage , size, pStr) {
var mimeType = 'data:image/png;base64';
var filename = Pointer_stringify(pStr);
var binary = new ArrayBuffer(size);
var dv = new DataView(binary);
for (var i = 0; i < size; i++)
dv.setUint8(i, HEAPU8[pImage + i]);
var blob = new Blob([binary], {type : mimeType});
const a = document.createElement('a');
a.href = window.URL.createObjectURL(blob);
a.download = filename;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
}
mergeInto(LibraryManager.library, FileDownloadPlugin);
Panorama.csをEmpty EmptyGameObjectにアタッチします。
この状態でUnity Editorを再生すると[p]キーでパノラマキャプチャすることができます。
キャプチャされた画像の格納場所はUnity Editorの最下段にデバッグ情報として表示されます。
設定にもよりますが、以下のディレクトリにskyonsea_panorama.pngとして保存されると思います。
C:/Users/%USERNAME%/AppData/LocalLow/DefaultCompany/%PROJECTNAME%
画像は例えば以下のようなものです。
この画像はシーンのパノラマ画像です。
背後に有ったSkyBoxの太陽が見えます。
WebGLとしてビルドしたものをChromeで実行しても、同様にパノラマ画像をダウンロードすることができます。
左下をご確認ください。
ダウンロードディレクトリにパノラマ画像がダウンロードされていると思います。
さてこれでパノラマ画像をダウンロードする仕組みはできました。
後はシーンを作り上げていけば良いことになります。
以下は作例です。
この作例では以下の有料アセットを使っています。
aquas-water-river-set
massive-clouds-screen-space-volumetric-clouds
このWebGLコンテンツをクリック/マウスオーバーしてから[p]キーを押下してください。
Windows10のChromeならパノラマ画像がダウンロードできるかと思います。
如何でしょうか?
ゲーム等にパノラマ画像をダウンロードさせるインターフェースを簡単に設置できることがお分かり頂けたかと存じます。
ただし注意事項があります。
なんでもがパノラマ画像としてキャプチャされるわけではないようなのです。
WebGLとしてビルド可能であることは必須なのですが、例えWebGLとして表示できていたとしてもパノラマ画像としてキャプチャできない例に遭遇します。
例えば私はAQUASのアセットを持っていて、無料アップグレード特典で入手したAQUAS 2020も持っているわけです。
当然AQUAS 2020の方が高機能なのでAQUAS 2020を使ったWebGLコンテンツでパノラマ画像を取得したいのです。
しかしなぜかAQUAS2020のエフェクトがパノラマ画像に反映されません。
理由が分かる方、お教え頂けると助かります。
UNITYはひと時も同じ状態で留まりません。
バージョン毎の差分、アセットの対応バージョン、組み合わせなどが多すぎて上手くいかないことが多いと痛感します。
前はこれでできたから、と思って新作アセットと組み合わせようと思うと、意味不明のエラーメッセージが出力される。
やっとの思いで解決しても、最新のバージョンではまた別の問題に直面する。
その度にググり、ログを見て原因を探り、解決したり諦めたり。
最近では諦めることが多いです。
実を言うと今回の記事、Unity-Chan “Candy Rock Star”でやろうかなと思っていたのですが、 UNITY 2019のWebGLでBuildできず諦めています。
とは言え、簡単に背景を作ることとだけに着目するとそれほど大きな変化が無いので背景作成ツールとしては長いこと使い続けています。
この記事がだれかのお役に立てば幸いです。