tanaka's Programming Memo

プログラミングについてのメモ。

デジゲー博2020出展してきました

今年もデジゲー博にVoxelorer Birdを出展してきました。3年連続3回目!またもやリリースはできませんでしたが、今回はWebGLの体験版が配布できたので一歩前進。

f:id:am1tanaka:20201129103305j:plain

時間が経ってしまいましたが今後に向けて、振り返りや展示ブースの作り方の記録です。

目次

出展の目的

応募時は「スマホ版をリリースしてその告知」を目指していたのですが、あれこれあって最終的な出展の目的は以下になりました。

  • デジゲー博にお金を落とす
  • Web体験版の配布
  • スマホ版の進捗報告
  • (Looking Glass自慢)

お陰様でこれらすべて達成できました!

今回は新型コロナの影響で、なるべく接触の展示になるよう考えました。WebGLの体験版を用意したのは、来場者のスマホで手軽に体験できるものがあれば展示物に触らなくても体験できる、という思い付きからでした。それで展示の体裁は整うと考えて、スマホ版のリリースよりも面白い展示を優先しようとLooking Glassを引っ張り出すことにしました。

展示の成果

Web体験版

Web体験版を遊べるQRコードを印刷した名刺サイズのカードを配布しました。展示から時間も経ちましたし、ここで公開します!

VoxdlorerBird2020 Web体験版

Web Trial VoxelorerBird

手元のiPhoneSE, iPad Air, Pixel3aでの動作は確認していますが、性能が低かったり、古いスマホだと動作しないかも知れません。UnityのWebGLビルドで作成したもので、公式にスマホで動かないことはないが保証はしない」という技術のものです。動作しない場合はPCからアクセスしてみてください。PCでは問題なく動作すると思います。

カードは例年の経験から50枚もあれば足りるだろうと考えて、カラー50枚、テスト印刷の白黒10枚、併せて60枚用意しました。結果、残り1時間を残して配布完了しました。これは嬉しい誤算でした。あと10枚あったら少し余ったように感じるので、次回は80~100枚程度用意しようと考えています。

プレイ回数

会場での試遊回数が約50回、配布した体験版のページのアクセスが23回、合計70回程度、試遊していただけました。体験版の紹介ページへのアクセスは33回でした。

体験版のアクセスはほぼデジゲー博当日のもので、後日のアクセスは数回でした。延べ人数ではありますが、カードを受け取っていただいた方の30~50%が実際にアクセスしてくださったことになります。

改めまして、プレイして下さった皆様、興味を持っていただいた皆様、ありがとうございました!

広告協賛

今回の一番の目的の「デジゲー博の継続のためにお金を落とす」のために、広告協賛も初参加しました。デジゲー博さんのWebページの下の方に「(カ)アミューズワン」の協賛ロゴを掲載いただいてます。

digigame-expo.org

↓こんなやつですが、正方形なんだからもう一段折り返しておけばよかった^^;

f:id:am1tanaka:20201208120423p:plain

今後の反省とします。

設営

展示の配置

入手したばかりのiPhone12ProのLiDERの試運転がてら、ブースのモデルを撮影して作ってみました。

skfb.ly

撮影は3d Scanner Appというフリーのアプリで行い、それをiCloudで共有してObj形式で取り出して、Blenderで不要部分をトリミングして、Sketchfabにアップしました。

3d Scanner App™

3d Scanner App™

  • Laan Labs
  • ユーティリティ
  • 無料
apps.apple.com

展示台の下にスペースがあります。そこにWin10ノートPCとmac book airを置いてました。そこまで撮っとけばよかった。

展示グッズ

展示も3回目となり、道具もかなり揃ってきました。

底上げ棚

展示のスマホを机の上に直置きすると位置が低くて体験しづらいので、去年までは100円ショップの収納ボックスの上に発泡ボードを置いて簡易の棚を作って高さを稼いでいました。安くて軽いのが大きなメリットでしたが、強度がなくて潰れて事故りそうだったのと、下のスペースが使えないのが勿体なく感じて、今回は「押し入れ整理棚」を導入しました。

幅70~120cmで高さと奥行きが40cm弱ぐらいの何か、ということでニトリやらハンズをうろうろして、TV棚や机上棚など見て回った結果、「押入れ整理棚」というジャンルに行きつきました。サイズ感ばっちりで、重量も軽く強度があり、2つセットでお値段もお手頃と文句のないナイスな棚でした。

今回の展示なら2つ並べて180cmフルに嵩上げすることもできたのですが、2つ持っていくのは重いし、テーブルクロスの幅が足りない。ということで、棚1つで通常時の90cm幅で設営することにしました。

あと、滑り止めのために直径2cm程度のゴムを足の部分に取り付けました。これは去年の展示で別の目的でハンズで購入したものでしたが、サイズがぴったりだったので使いまわしました。サイズはわかりませんがこんなやつ。

hands.net

強度は安心できるし、去年無駄になっていた下のスペースにPCを2台置けました。これで台上からPCをなくすことができて、Looking Glassを置いてもゆったりめに展示ができました。荷物は増えましたが効果はテキメンでした。次回は、棚の袋の下にキャスターをくっつけて、持ち運びを楽にしようと目論んでます。

ポスタースタンド

去年導入したものを今年も利用。初年度は段ボールで無理くり作ったのですが、嵩張って仕方なかったのでこれをゲットしました。今年も大活躍!とても便利です。

タブレットスタンド

今年導入しました。去年は厚紙で自作したのですが、iPadの重量に耐えかねて午前中で潰れてしまいました。がっちりしていて安心して展示できました。

置いたままプレイできるのでスムーズに体験していただけました。スマホは自作の厚紙のまま展示しましたが、ヘタってきてたので次回に備えてスマホのも入手しておこうと考えてます。

カードの印刷

最近はコンビニのネットプリントを活用してます。

https://networkprint.ne.jp/Lite/start?lang=jajp

展示場の秋葉原UDXの5階にファミマがあるので、最悪、当日に印刷して間に合わせることができます。

配布カードはA4光沢紙にプリントして切り分けました。名刺サイズだと1ページ120円で10枚作れるので50枚で600円でした。速めに入稿すれば印刷サービスの方が安いかも知れませんが、枚数の自由度の高さと、何より当日でもなんとかなる気軽さが強いです。

光沢紙ではありませんがA3カラーも印刷できるので、大きめの案内パネルも印刷しました。こちらは1枚100円でした。

ポスター

2018年に作ったやつをそのまま利用^^; こちらはラクスルさんで印刷しました。

raksul.com

3年目ですがまだ使えてます。それがいいのか悪いのか・・・。次回は新しいやつを制作し直したいところです!

その他

他にも細々と。

  • 充電・電源ケーブル
  • アルコール消毒液、タオル
  • 名刺ヨコ置きホルダー
  • A3スチレンボード
  • テーブル布(90x90cm ハンズで買った黒い起毛のやつ)
  • スコッチテープ、ガムテープ、ポスターのり
  • ドライバー、はさみ
  • マスク
  • WiFiルーター

会場のWiFi

デジゲー博のものではないので展示には使えませんが、会場の秋葉原UDXではフリーのWiFiが使えます。メアドの登録が必要ですが、1度登録してログインすれば30分間インターネットに接続できます。

設営日、届いたばかりのiPhone12Proに携帯を変えたのですが、回線の設定ミスでネットに接続できないことに電車に乗ってから気づきました。ネット印刷のIDをGmailに下書きで記録していたので、ネットに接続しないと確認できません。印刷は展示当日の朝か~と覚悟したのですが、会場でこのWiFiの存在を知って事なきを得ました。都心、便利。

まとめ

新型コロナの影響で出展ブースも来場者数も例年よりも少なかったと思います。その分、ゆったり体験していただけたような気がします。個人的には人が多いのが苦手なので、今年ぐらいのんびりした雰囲気はとてもよかったです。が、運営サイドはそうも言ってられませんねf^^; 新型コロナが早く終息して、これまで以上の活気が戻ることを祈ります。

足を運んで下さったり、試遊していただいた皆様、本当にありがとうございました!また、この記事をお読みくださったみなさまも試遊していただければ幸いです!

VoxdlorerBird2020 Web体験版

Web Trial VoxelorerBird

おまけ

今回の展示で圧倒的な破壊力を発揮した立体ディスプレイのLooking Glass。

lookingglassfactory.com

「なんか立体の面白いディスプレイがある」という口コミで足を運んで下さった方が多数いらっしゃいました。そもそもLooking Glassを購入した最大の決め手がデジゲー博の展示で使えそうということだったので、ついに実現!という感じでした。そんな展示のすぐあとにLooking Glassの新型が来春に出ることが発表されました!!なんたる奇遇。2021年1月15日 (金曜) の10:30 UTC +09:00 までクラウドファンディングが行われています。

www.kickstarter.com

詳しくはMoguraVRさんのこちらの記事をどうぞ。記事中の$199のやつはもう終わっていますが、1/15までは$150引きで、3万円ちょっとで本体+キャリングケース付きがゲットできます。

私はすでに発注済みなので、次回は初代が故障していなければ立体2台体制の展示になるかもです。

参考・関連URL

Unity2020.1のWebGLでwasm streaming compile failedが出る

WebGLでビルドしたプロジェクトを実行しようとしたところ以下のようなエラーが出ました。

wasm streaming compile failed: TypeError: Failed to execute 'compile' on 'WebAssembly': Incorrect response MIME type. Expected 'application/wasm'

解決策

Unity側の不具合っぽいのですが、現状ではPlayer SettingsName Files As Hashesオプションを解除することで直せました。

  • EditメニューからProject Settingsを開いて、Playerを選びます
  • WebGL settingsタブのPublishing Settings欄にあるName Files As Hashesのチェックを外します

f:id:am1tanaka:20201107112414p:plain
Name Files As Hashesを外す

Unity Issue Trackerによると、Unity2020.2で解決予定だそうです。

Unity Issue Tracker - [WebGL] "wasm streaming compile failed" browser errors occur when launching any Unity project on a server

原因

Unity Issue Trackerによると、WebAssemblyモジュールにContent-Type: application/wasm .wasmJavaScriptフレームワークコードにContent-Type: application/javascript .jsをサーバーが返さないことが原因とのことです。

試しに.htaccessファイルで.wasmの設定を追加したらこのエラーは治ったのですが、他のエラーが出たので一先ず解決策の方法で対応しました。

Mirrorでプレイヤーごとに違うプレハブからプレイヤーオブジェクトを生成する

最新のMirrorでは動かなくなっているようです。改めて調査し直して方法がまとまったら更新します。公式ドキュメントの場所も以下に変わっていました。

mirror-networking.gitbook.io


Mirrorは、UNetをベースに設計された高評価のMMOスケールにも対応できるというネットワークAPIライブラリです。

mirror-networking.com

MirrorでデフォルトのNetworkManagerを使った場合、Player Prefab欄に設定されているプレハブをプレイヤー用のゲームオブジェクトとして自動的に生成します。NetworkManagerを継承すればプレイヤーごとに違うプレハブからプレイヤーを生成することができるという自分用のメモです。

目次

実行環境

  • Unity2019.3.15f1
  • Mirror16.1.1

ざっくり手順

プレイヤー用のプレハブを用意する

違いが分かるようにメッシュを変えたり動きを変えたプレイヤー用のプレハブをいくつか用意します。NetworkIdentityをアタッチしてあれば一先ず動きます。

プレイヤー定義用のScriptableObjectを作成

クライアントからどのプレハブを使うかを送る手段が考えつかなかったので、ちょっと乱暴ですがScriptableObjectにプレイヤー用のプレハブを配列で持たせて、そのインデックスで生成するオブジェクトを指定するようにします(ResourcesやAssetBundleを使えば、プレハブ名などでいけると思います)。

PlayerPrefabList.cs

配列の参照用のenumと、GameObjectの配列を持つScriptableObjectを宣言しています。PlayerTypeの内容は、用意するプレイヤー用プレハブに応じて書き換えてください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum PlayerType
{
    Green,
    Red
}

[CreateAssetMenu(menuName ="AM1Mirror/PlayerPrefabList")]
public class PlayerPrefabList : ScriptableObject
{
    public GameObject [] playerPrefs = null;
}

これができたら、ProjectウィンドウのCreateから AM1Mirror > PlayerPrefabList を選んでスクリプタブルオブジェクトを作成します。作成したら、enumの定義順に応じてプレイヤー用のプレハブをInspectorウィンドウから設定しておきます。

NetworkManagerのサブクラスを作成する

公式ガイドの以下をもとに、今回の要であるカスタムのNetworkManagerを作ります。

https://mirror-networking.com/docs/Guides/GameObjects/SpawnPlayerCustom.htmlmirror-networking.com

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;

public class NetworkManagerCP : NetworkManager
{
    PlayerType spawnPlayerType;

    [Tooltip("プレイヤープレハブリスト"), SerializeField]
    PlayerPrefabList playerPrefabList = null;

    public void SetPlayerType(PlayerType pt)
    {
        spawnPlayerType = pt;
    }

    /// <summary>
    /// サーバー開始時、プレイヤーキャラクターのメッセージを登録
    /// </summary>
    public override void OnStartServer()
    {
        base.OnStartServer();

        NetworkServer.RegisterHandler<CreateCharacterMessage>(OnCreateCharacter);
    }

    /// <summary>
    /// クライアント側で接続した時に、選択してあるプレイヤーのプレハブをメッセージで送信
    /// </summary>
    /// <param name="conn"></param>
    public override void OnClientConnect(NetworkConnection conn)
    {
        base.OnClientConnect(conn);

        CreateCharacterMessage ccm = new CreateCharacterMessage
        {
            playerType = spawnPlayerType
        };

        conn.Send(ccm);
    }

    /// <summary>
    /// メッセージがクライアントからサーバーに到着したら、届いたプレハブでプレイヤー生成
    /// </summary>
    /// <param name="conn"></param>
    /// <param name="messages"></param>
    void OnCreateCharacter(NetworkConnection conn, CreateCharacterMessage messages)
    {
        Transform tr = GetStartPosition();
        GameObject go = Instantiate(playerPrefabList.playerPrefs[(int)messages.playerType], tr.position, tr.rotation);
        NetworkServer.AddPlayerForConnection(conn, go);
    }

}

通信を開始する

通信を開始するためのクラスSimpleNetManを作成します。これはNetworkManagerCPに統合できるのですが、設定がNetworkManagerの設定に埋もれるのが見辛いので分けました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;

public class CreateCharacterMessage : MessageBase
{
    public PlayerType playerType;
}

public class SimpleNetMan : MonoBehaviour
{
    public enum ConnectType
    {
        Host,
        Client
    }

    [Tooltip("プレイヤーの種類"), SerializeField]
    PlayerType playerType = PlayerType.Green;
    [Tooltip("接続の種類"), SerializeField]
    ConnectType connectType = ConnectType.Host;
    [Tooltip("ホストのIPアドレス"), SerializeField]
    string ipAddress = "localhost";

    NetworkManagerCP networkManager = null;

    private void Awake()
    {
        networkManager = GetComponent<NetworkManagerCP>();
        networkManager.SetPlayerType(playerType);
        StartCoroutine(Online());
    }

    IEnumerator Online()
    {
        yield return null;  // 1フレーム待つ

        if (connectType == ConnectType.Host)
        {
            networkManager.StartHost();
        }
        else
        {
            networkManager.networkAddress = ipAddress;
            networkManager.StartClient();
        }
    }
}

IEnumeratorでやってるのは、なんとなく1フレーム待った方が初期化が終ってそうでいいかな、という雰囲気でやったことです。Awake()内でやってもいいかも。

仕上げ

作成したSimpleNetManNetworkManagerCPNetworkManagerのような名前のゲームオブジェクトに一緒にアタッチします。

SimpleNetManでは、生成したいプレイヤータイプを設定して、ホストかクライアントか選択して、ホストのIPアドレスを設定します。これらのパラメーターを設定するメニューを用意すれば実行時に変更できます。

NetworkManagerCPでは、下の方にあるPlayer Prefab List欄に、最初に作成したScriptableObjectをアタッチして、ScriptableObjectに設定したプレイヤー用のプレハブをRegistered Spawnable Prefabs欄に全て追加します。これをしないとプレイヤーオブジェクトがネットワーク上に生成できず、エラーになります。

まとめ

ざっくりですがこんな感じでできました。ScriptableObjectを利用するなど何らかの方法で、クライアントからホストへ生成したいプレイヤープレハブをNetworkMessageで送信して、それをもとにStartHost()やStartClient()が実行されたら、NetworkMessageを受け取って記録して、クライアントの生成の段階で指定されたプレハブからプレイヤーオブジェクトをInstantiateして、ネットワークに追加します。

この記事では、スクリプトが分かれていたり、Inspectorウィンドウでプレイヤーや接続の種類を設定する不自然な状態になっていますが、これは体験入学用に全員がUnityエディターで作業をすることを前提としているからです。通常の利用であれば、プレイヤーを選択するルームなどを作って、そこで選ばれたものをメッセージで送ってゲーム開始、という感じになると思います。

とりあえず、こんな流れで、こんな感じのコードで異なるプレハブからプレイヤーを生成できるという記事でした。

おまけ:Mirrorのイベントの発生順

重要なドキュメントですが、なんか下の方にあった...

https://mirror-networking.com/docs/Guides/Communications/NetworkManager.htmlmirror-networking.com

これを見ると、まずはStart()が呼ばれて、OnStartServer()OnStartHost()より後に呼ばれています。ということで、NetworkManagerのStartHost()やStartClient()で通信を開始します。

参考URL

Laravelのバージョン指定でプロジェクトを作る

Laravelの最新版を入れると7が入るけど、今は6.xを使いたいというとき、とりあえず以下でバージョン指定できる。

composer create-project --prefer-dist laravel/laravel blog "6.*"

参考URL

macのLaravelを5.xから最新版にアップデートする

PHPなどに問題がなければ、以下でいけました。

  • laravelをインストールした.composerフォルダーを開く
  • 以下を実行
composer global require laravel/installer
composer update

これでうまくいかない場合は、以下も参照。

brewあたりから更新

かなり苦戦したので、ざっくりやったこと。

brew update
brew upgrade
rm /usr/local/etc/php/7.1/conf.d/*
brew untap homebrew/php
atom ~/.composer/composer.json

Atomが開いたら、phpunitを以下に修正。

        "phpunit/phpunit": "~7.0",

以上で上書き保存してから、以下実行。

composer global update

以下で、利用できるphpを調べる。

brew search php

7.2を使うなら、

brew install php@7.2

これをリンクします。

brew link php72 --force

以下を実行して、パスを設定します。

echo 'export PATH="/usr/local/opt/php@7.2/bin:$PATH"' >> ~/.bash_profile
echo 'export PATH="/usr/local/opt/php@7.2/sbin:$PATH"' >> ~/.bash_profile

ターミナルを再起動します。

valetのを再インストールします。

valet stop
valet uninstall
composer global require laravel/valet
valet install
valet restart

以上で、動きました。どのあたりが決めてかはわからず、余計な物もあるかもしれませんが、ひとまずコマンドのメモということで。

参考URL

ラズパイ4の電源不安定

これまで問題なく動いていたラズパイ4が急に起動しなくなりました。TVにつなげるとリカバリーモードまでは行けるのですが、その先で画面が表示されずターミナルによる接続もできません。起動の際に雷マークが表示されたため、電圧不足であることが分かりました。雷マークについては以下のようなものです。

raspi.maruzonet.com

どうやらUSBケーブルによる電圧降下があって、推奨されている5V 3Aきっちりの電源だと電圧が足りなくなってしまうようです。参考↓

jsdkk.com

今調べると、ラズパイ4用の電源は殆どが5.1Vなのですね。アマゾンで5.1V 3Aのラズパイ4用とあったケーブルを購入して無事に解決しました。私が購入したものは品切れで紹介できないのですが、スイッチサイエンスさんの以下のやつとかは確実そうです。

www.switch-science.com

まとめ

比較的初期に千石電子さんでセットで購入したものに付属していた電源を使っていて、これまで問題なく使えていました。あれこれインストールしたからか、あるいは電源周りの汚れやらガタつきやらで状況が変わったからか、急に動かなくなったのが今回のきっかけでした。もし、同じように急に起動しなくなって、雷マークが表示されているようでしたら、電源を調べてみてください。

電源不足以外ですと、メモリカードの故障、TVモニターに映らなくなる、などが、ラズパイの突然起動しない問題の原因として挙げられていました。「ラズパイ 起動しない」などで検索して、自分の症状にあったものを見つけてみてください。

参考URL

BurstのBurstCompileがVisualStudioでエラー

Burstを触ってみようと思って以下のQuick Startを試してみました。

docs.unity3d.com

Unityでは動くものの、Visual Studio[BurstCompile(CompileSynchronously = true)]がエラーになる。

以下に「Visual StudioをUnity Game Packageから入れなおしたら直った」とありました。

https://forum.unity.com/threads/visual-studio-unity-mathematics-unity-burst-not-found.711215/

ということで、以下のことをごちゃごちゃやってたら直しました。

  • Visual Studio Installerを起動
  • Visual Studio Community 2019変更をクリック
  • Unityによるゲーム開発のチェックを外して、変更ボタンをクリックして、一旦Unityの拡張を解除
  • Unity Hubのインストールから、Unity2019.3.2モジュールの追加をクリックして、Microsoft Visual Studio Community 2019にチェックを入れて実行をクリック
  • インストールが完了したら、Visual Studio Installerに戻って、Unityによるゲーム開発にチェックを入れて、変更をクリック
  • Visual Studio Installerのトップに戻って、Visual Studio Community 2019詳細 > 修復をクリック
  • 修復が完了したら、指示に従ってPCを再起動

以上で直りました。どの段階で直ったか分からないので、やったこと全部書きました。

参考URL