勉強不足で至らんブログ

勉強不足ですが色々と書いていきます。

UnityのWebGLをVue.js使ってPWAに対応した表示してみた

自分のQiita転載でございます。

qiita.com

PWAを触ってみたかった

始めの動機はそんなもので、PWAというのがあるすごい!UnityはWebGLで吐ける!…いけるんじゃね? ってことでやってみました。

PWA for Unity Sample ezgif-5-edf42d3870eb.gif

はい結構適当ですが、UI Buttonを押してカウントアップするものです。

環境

UnityやVueのセットアップは他の記事を参考に行った方が良いと思うので今回は省きます。 Vueに関してはこちらを参考にさせて頂きました。 - Vue.jsで始めるPWA - VueコンポーネントでWindowサイズ変更検知&値取得

最初に言うとWeb畑の人間でないのでVue.jsとかの記述、設定諸々はよくわかってないです行き当たりばったりでやってるのでお手柔らかにお願いします。 Unity WebGLCSSの適応の仕方がわからなくて詰んで放り投げました。

以下が今回のプロジェクトリポジトリになります。 GitHub

一応、GitHub Pagesも試しましたが何故かAndroidで動かしたときにショートカットを追加とかの機能が動いてなかったぽいので今回はFirebase Hostingを使ってみました。

Unityの設定

設定もなにもWebGLでビルドできるようにコンポーネント追加してビルドするだけです。

ただ、ビルドする場所はVue.jsのstaticフォルダ配下にビルドするようにします。Vue.jsの静的なファイルを置くところらしいです。 個人的にはstaticフォルダ配下にUnityビルド用のフォルダを作ってまとめておくとよいと思います。

今回だとunityBuildというフォルダを作っています。

Vueの設定

UnityのWebGLの読み込みを自分で書いても良かったのですが既にライブラリがあったため使わせていただきました。 vue-unity-webgl

上記をインストールしてまずはindex.htmlのヘッダーに

<link rel="shortcut icon" href="<%= htmlWebpackPlugin.files.publicPath %>static/unitybuild/TemplateData/favicon.ico">
  <link rel="stylesheet" href="<%= htmlWebpackPlugin.files.publicPath %>static/unitybuild/TemplateData/style.css">
  <script src="<%= htmlWebpackPlugin.files.publicPath %>static/unitybuild/TemplateData/UnityProgress.js"></script>
  <script src="<%= htmlWebpackPlugin.files.publicPath %>static/unitybuild/Build/UnityLoader.js"></script>

を追加します。static配下のunitybuildフォルダ名は各自が命名したフォルダ名にしてください。

そして、App.vueを

<template>
  <div id="app">
    <header>
      <span>Vue.js PWA</span>
    </header>
    <main>
      <unity src="static/unityBuild/Build/unityBuild.json"
        v-bind="{ width: gameWidth, height: gameHeight }"
       unityLoader="static/unityBuild/Build/UnityLoader.js"></unity>
    </main>
  </div>
</template>

<script>
import unity from 'vue-unity-webgl'

export default {
  name: 'app',
  data: function () {
    return {
      gameWidth: window.innerWidth,
      gameHeight: window.innerHeight * 0.96 - 134 // 134はヘッダー等の値
    }
  },
  methods: {
    handleResize: function () {
      this.gameWidth = window.innerWidth
      this.gameHeight = window.innerHeight
    }
  },
  ready: function () {
    window.addEventListener('resize', this.handleResize)
  },
  beforeDestroy: function () {
    window.removeEventListener('resize', this.handleResize)
  },
  components: { unity }
}
</script>

/// <style>は初期状態のまま編集してないので略 ///

と編集することで、とりあえずはそれっぽくUnityのWebGLを表示できるかと思います。

PWAなのでモバイルでも動かすことを想定していますが、最初に出てくるアラートが鬱陶しい場合はテラシュールブログさんの 【Unity】WebGLとWebAssembly にあるモバイルで動作させるを参照してください。

Firebase

今回は静的ファイルばかりなのでhosting機能を使っています。 セットアップとデプロイに関しては公式のドキュメントで充分だと思います。 Firebase Hosting

所感

Vue.jsが楽… PWAなのでちゃんとホーム画面でインストールしたかのように扱えますし、オフライン動作部分を調整すればストアに出さなくてもゲームらしく出来るんじゃないか?と思います。 cssをきちんと適応させることはもちろんですが横画面にすることも考慮してできれば結構気楽にゲームなどをデプロイできる気がします あと、最近はPWAをWindows等の上でも動かせるのでデスクトップゲーム風とかもできるかもしれません。 本当はUnityでWebGLビルド時に勝手にVueProject作ってPWA環境にする!みたいなフレームワーク的なところまで妄想してましたが妄想で止まってしまいました。。

何かの参考になればと思います。

(GitHubのアラートはいつかなおすんだ…いつか…)

Vuforia Fusionを使った際に描画がおかしくなった

「はちゃめちゃAR らくがきらんど」というアプリの開発メンバーの1人として制作して起こった問題を書いておきます。

まず「はちゃめちゃAR らくがきらんど」がどういうアプリなのか下のツイートの動画にて大体の雰囲気がつかめると思います。

 

という、3Dオブジェクトを出してスプレーで塗れるARアプリになります。iOSでは現在リリース中のアプリです。

 

そして、ARKitを使っています!…が、現在Android版対応に伴いARKitオンリーを抜けてVuforia Fusionを使って開発を進めています!(Vuforia FusionはARCoreでもARKitでも対応端末であればマルチプラットフォームで良きに図らってくれるものです)

 

そこで問題となったのがカメラが異常にズームされる問題です。

 

いや、めっちゃ原因不明で焦りました。

Cameraの設定を見てもVuforiaにきちんとハンドリングされていて、それらしきエラーも出ないんですよ

 

そこで以下のSRDebuggerというAssetを導入して実機端末でDebug.Logとかを張ったんですが、めぼしいものはなく…途方に暮れていました…(SRDebuggerはめちゃ便利で実機で何かを確認するとき捗ります)

 

そんなところ、もう1人の開発メンバーが「ビルドオプションのMutithreaded Renderingの設定を外すと動くかも」と言ってくれて試したところ…

f:id:MakeTake:20180525092750p:plain

 

 

動くやんけ!!!

 

何てことはなかったです。原因さえわかれば…

Vuforiaでなくても、Androidで描画うまくいかない…コード見直してもわからないという場合には外してみるのもいいのかもしれません。

 

「はちゃめちゃAR らくがきらんど」のAndroid版は現在調整中ですがiOS版はリリースされているので気になった方は是非インストールして頂ければと思います!

 

はちゃめちゃAR!らくがきランド

はちゃめちゃAR!らくがきランド

  • Iwasa Kenta
  • ゲーム
  • ¥120

 

追記: Android版リリースされました!端末は限られますが是非インストールしてみてください!!

 

play.google.com

ScriptableObjectの入れ替えで振る舞いを変える

セルフQiita転載です。

qiita.com

はじめに

 ゲームを作っていて、必殺技の作成等を簡単に行えるようにできないだろうか?ということを考えたのが今回の発端です。そこで、ScriptableObjectにパラメーターとメソッドを定義して入れ替えるだけで挙動を変えれると簡単なのでは?と考えついて試してみたので備忘録として書きます。

最終的に、以下のようになります。 Sample1.gif

ScriptableObjectの入れ替えで振る舞いが変わります。

gifで動かしているプロジェクトは公開しているので、説明読むより触ってみたい!という方はご活用ください。 https://github.com/MizoTake/ChangeBehaviourWithScriptableObject

一連の流れ

 最初に、今回の処理がどういう流れで行われているのか書きます。

まず、gifにあったCubeはSpaceキーを押すとInspectorから代入されたScriptableObjectの振る舞いを実行します。 中身は以下のようになっています。 Cubeに貼られているスクリプトから

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

public class ControllerInput : MonoBehaviour
{
    [SerializeField]
    private Rigidbody _rigid;
    [SerializeField]
    private Behaviour _behaviour;

    public Rigidbody Rigid { get { return _rigid; } }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            _behaviour.Move(this);
        }
    }
}

SpaceKeyが押されるとBehaviourというクラスのMoveメソッドを実行します。 次に、そのBehaviourというクラスです。

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

public abstract class Behaviour : ScriptableObject
{
    public abstract void Move(ControllerInput input);
}

public static class BehaviourExtension
{
    public static void Init(this Behaviour behaviour)
    {
        Debug.Log("Initialize");
    }
}

これは、abstractを宣言しているので基底クラスです。継承先で振る舞いを書いて欲しいメソッドを定義しています。今回は、Moveメソッドになります。 そして、ScriptableObjectクラスを継承しているので継承先のクラスをScriptableObjectにできるようになります。 また、abstractクラスには、そのまま拡張メソッドを追加できるので共通で何かを行いたい場合等に使うと便利です。(今回はTips程度に書いています。)

次にgifの最初にJumpしていたクラスです。

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

public class Jump : Behaviour
{

    public int Power;

    public override void Move(ControllerInput input)
    {
        this.Init();
        input.Rigid.AddForce(Vector3.up * Power, ForceMode.Impulse);
    }
}

これはBehaviourを継承してMoveの振る舞いを定義しています。そのためgifでは、JumpクラスがInputControllerのInspectorに代入され、Moveが呼ばれるためジャンプをしていました。

ここで便利になるのはScriptableObjectを作成した後、Powerの値を変えることでジャンプの高さも変えることが容易になるという点です。

また、this.Init()で呼び出すことによりabstractの拡張メソッドであるInitが呼ばれます。

ここまでが基本的な一連の流れになります。

次からは+αで便利だと思った部分を書きます。

sample2.gif

これは最初のgifでバラバラに実行されていた、ジャンプの振る舞いと色を変える振る舞いを複合して実行しているものになります。

まず、色を変えるクラスです。

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

public class ChangeMaterial : Behaviour
{

    public Material Target;

    public override void Move(ControllerInput input)
    {
        this.Init();
        input.gameObject.GetComponent<MeshRenderer>().material = Target;
    }
}

ScriptableObjectにした後、InspectorでMaterialを代入しています。そして、Jump同様にInputControllerのInspctorに代入することで動作します。

次に複合させたクラスです。

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

public class Composite : Behaviour
{

    public Behaviour[] Behaviours;

    public override void Move(ControllerInput input)
    {
        this.Init();
        foreach (var behaviour in Behaviours)
        {
            behaviour.Move(input);
        }
    }
}

中身を見ると何てことはないと思います。配列をInspectorから入れて、for文で一気に実行するというものです。

ただ、Behaviourクラスがあるだけで振る舞いの複合やランダム実行などが簡単に定義でき、Compositeクラス自体もBehaviour継承クラスなので、InputControllerのInspectorに代入するだけで切り替えれるというのは便利だと思っています。

以上で今回の記事はすべてになります。 (…ScriptableObjectにメソッドが書けるのが個人的に驚きだった)

また、ScriptableObjectの作成に関しては、個人的に以下の記事がオススメです。 【UnityEditor】ScriptableObjectのアセットを右クリックから作れるようにするエディター拡張

右クリックから作れるようになるので簡単作成できるようになって便利でした!

LICENSEファイルの中身を一つにまとめてくれるEditor拡張

自分のQiita転載です

qiita.com

GitHub等からAssetsを持ってきて、アプリをリリースする時などにLICENSEファイルをまとめるのがめんどくさいなぁと思ったりしませんか?僕は数回やってめんどくさいと思いました。

なのでEditor拡張でAssets配下の"LICENSE"ファイルを検索して"Assets/USE_ASSETS_LICENSE"にまとめるようにしてみました。

これで、ライセンス表記をする際に"Assets/USE_ASSETS_LICENSE"からtextを読んでもいいですし、開いてコピペでもいいと思います。良しなに使っていただければと思います。

public static class CreateUseLicenseFile
    {

        private const string USE_LICENSE_FILE = "use_assets_license_file";
        private const string fileName = "USE_ASSETS_LICENSE";

        [MenuItem("Assets/Create/Used LICENSE File")]
        static void CreateUsedLICENSEFile()
        {
            System.Text.StringBuilder builder = new System.Text.StringBuilder();

            string[] files;
            string assetPath = Application.dataPath + "/" + fileName;

            AssetDatabase.MoveAssetToTrash(assetPath);

            files = AssetDatabase.FindAssets("LICENSE");
            foreach (var guid in files)
            {
                if (Path.GetFileName((AssetDatabase.GUIDToAssetPath(guid))) == "CreateUseLicenseFile.cs" ||
                    Path.GetFileName((AssetDatabase.GUIDToAssetPath(guid))) == fileName) continue;
                var path = AssetDatabase.GUIDToAssetPath(guid).Substring("Assets".Length);
                StreamReader reader = new StreamReader(Application.dataPath + path);
                builder.Append(reader.ReadToEnd()).AppendLine();
                reader.Close();
            }

            string text = builder.ToString();

            if (AssetDatabase.LoadAssetAtPath(assetPath, typeof(UnityEngine.Object)) != null && EditorPrefs.GetInt(USE_LICENSE_FILE, 0) == text.GetHashCode())
                return;

            System.IO.File.WriteAllText(assetPath, text);
            EditorPrefs.SetInt(USE_LICENSE_FILE, text.GetHashCode());
            AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
        }
    }

こういう拡張があったら二番煎じですみません。。。

最近、作り始めたフレームワークの中に入れています。もし、ご興味のある方は是非。 https://github.com/MizoTake/MomijiFramework/blob/master/Editor/CreateUseLicenseFile.cs

シンプルなアクションゲーム Reviver を公開しました!

 約4ヶ月ほどの開発を得て、ひとまず公開できるレベルになったので公開しました!

現在、Androidのみ対応です。片手でタップするだけでも遊べます。

 結構シンプルにまとめたつもりです。操作も簡単ですが、人によっての遊び方に幅が少しでも出るようにしたつもりです。是非、インストールしてください!

 

play.google.com

 

 ちなみに、これはゲームエンジン Unityで制作してます。

 今回、デザイナーと一緒にやらず1人でどこまでできるのか試すために作ったのですがキャラクターはCubeのままで公開まで行きました。開発途中でちょうどテラシュールブログの方で

tsubakit1.hateblo.jp

が公開されてタイミングがすごくよかったです。これを見て参考に実装しました。人間のようなキャラクターがなくてもCubeをアニメーションさせるだけで全然違いますね。

 

また、今回使用したAssetsは

UniRx

DoTween

Material UI

上記3つです。

Material UI はAssets Storeからではなく古いバージョンであればGitHubから使用できたので使用しました。

https://github.com/InvexGames/MaterialUI

 

 気になって買ったAssetsもあったんですが開発途中だったのもあり使用しませんでした。
 ・Arbor2

GUIで状態管理ができるようになるAssetsです。次回から使っていこうと思っています。 

 

また、アイコンに関してはGoogleが提供している

material.io

を使用することで1人で作っても、アプリっぽい見た目になったと思います。

 

音は

dova-s.jp

を利用させていただきました!結構、色々な雰囲気の音があってBGMもSEもここで見つけました。

 

 そして、ランキング機能があるのですが、Google Spread Sheetを使用したGoogle App Scriptで実装しています。なので、ランキングはアプリのプレイヤー全員が相手ということになります! 

 無料で使えて簡単にランキング等なら作れるのでおすすめです。

 

 今回、社会人になって初めて作ったのですが思ったよりも時間がとれなくて焦ってしまいました。学生のうちにサクサク作って、公開していればよかったとしみじみ思います……でも、作れる時に作ればいいので、これを皮ぎりに作っていこうと思います!

UnrealEngine4をGPD Pocketで動かしてみた

大八耐というイベントにGPD PocketでUnity動かして参加していました。

 

途中で、ふと疑問…UnrealEngine動かしたらどうなるんだ?

 

動かしました。

www.youtube.com

 

ついでにFPSを表示しています。平均20くらいですかね。

全く動かないわけではないです…軽いものであれば電車でUnrealEnigneも…?

大八耐2017 in 東京参加してました!

ちょくちょく記事に書いている八耐…の大きいやつ大八耐が10/7, 8であっていたのでゲーム作っていました。

 

Sphicと言います。

www.youtube.com

 

球を数珠のようにつなげて蛇にするのですが、あまりうまくいっておりません。

さらには対戦させたかったのですが間に合いませんでした。

チームで分担していたものの、うまく分担できてなかったような気もしてみます。

 

自分はゲームのメインロジックは触ってないので何ともです。精進せねば…

 

大八耐の他の方の作品は、面白いものから完成度の高いもの…料理…様々なものが作られていました!

福岡の記事ですが、雰囲気としてはこんな感じ…

大八耐2017 中間発表会が終わりました!|新着情報|大八耐

 

モノ作りの幅がないハッカソン…様々な作り手の方がいるので面白いです。。。

 

余談ですが、GPD Pocketで参加しておりました。

f:id:MakeTake:20171009012326j:plain

怖かったです。

なんとか復旧はしましたけど…

f:id:MakeTake:20171009012432j:plain