tanaka's Programming Memo

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

UI BuilderによるEditorWindowのデザインと新規シーンを作るエディタ拡張

エディタ拡張機能を使うと手軽にUnityエディタに機能を追加することができます。エディタのウィンドウはUI Builderというビジュアルエディタで手軽に作ることができます。UI Builderを利用した簡単なエディタ拡張の導入と、新規シーンの作成に少々手間取ったのでその方法をまとめます。

UI Toolkitによるエディタ拡張の導入については以下のマニュアルが分かりやすいです。

docs.unity3d.com

目次

動作環境

このブログはUnity2021.3.4f1で操作しています。UI Builderは2019.4にはあったので、Unity2019.4.x以降のバージョンならおおよそ動くと思います。

やりたいこと

名前を指定してシーンを作成して、そのシーンにシーン名+Behaviourの名前のオブジェクトを作成します。シーンの作成先のフォルダーはダイアログを表示して選択できるようにします。

エディタウィンドウは、Toolsメニューから AM1 > Create New Scene を選択して表示するようにします。

エディタウィンドウにはシーン名の入力欄と Create ボタンを置きます。Createボタンはシーン名が入力されるまでは押せないようにします。

作りたいエディタウィンドウ

以上のようにエディタを拡張します.

エディタウィンドウに必要なファイルを生成

エディタウィンドウのためのC#スクリプトとUXMLファイルを作成します。

  • Projectウィンドウの + から UI Toolkit > EditorWindowを選択します

C#, UXML, USSの3種類のファイルを同時に作成することができます。UXMLはエディタウィンドウの構造、USSはスタイルを定義するものです。UXMLはHTML、USSはCSSと位置づけが近いものです。

EditorWindow作成ダイアログ

  • 今回はUSSは利用しないのでチェックを外します
  • C#欄にNewSceneEditorWindowと入力します。UXML欄も自動的に設定されます
  • Confirmボタンを押して、ファイルが作成されるまでしばらく待ちます

以上でEditorフォルダーが作成されて、その中に指定のファイル名でC#スクリプトとUXMLファイルが出力されます。

作成されたエディタスクリプトとUXML

作成されたC#スクリプトには確認用にメニュー呼び出しが実装されています。メニューで以下を選べば新規作成したエディタウィンドウを呼び出せます。

  • Windowメニュー > UI Toolkit > NewSceneEditorWindow

デフォルトのエディタウィンドウ

ウィンドウには、C#スクリプトで追加されたラベルとUXMLファイルで追加されたラベルが表示されます。

エディタウィンドウのデザイン

UI Builderでウィンドウのレイアウトを作ります。

  • ProjectウィンドウのEditorフォルダーからアイコンが</>になっている方のNewSceneEditorWindowをダブルクリックします

UXMLファイルをダブルクリックするとUI Builderウィンドウが開きます。Visual C#のようにデザインを確認しながらウィンドウを作ることができます。

UI Builderウィンドウ

エディタ機能を有効にする

UI Toolkitはランタイムでも使えて、エディタとは使える機能が違います。今回はエディタとして使うのでそのための設定をします。

  • UI Builderの左のHierarchyで NewSceneEditorWindow.uxml をクリックして選択します
  • UI Builderの右のInspectorの表示が NewSceneEditorWindow のものになるので、 Editor Extension Authoring 欄にチェックを入れます

「これ以降はこのウィンドウはエディタモードでしか実行できません」というような警告が表示されますが問題ないのでそのまま進めます。この設定をすることで、ウィンドウ左下のLibraryにエディタで使えるコントロールが追加されます。

画面を編集する

最初のラベルは不要なので消します。

  • Viewportで「Hello World! From UXML」と書いてあるラベルをクリックして選択します
  • Deleteキーを押して削除します

次にシーン名の入力欄を追加して設定します。

  • ウィンドウ左下のLibraryから Text Field をダブルクリックします。Viewport上にテキストボックスが追加されます
  • Inspectorで以下を設定します
    • Name欄にSceneNameと入力します
    • Label欄にシーン名と入力します
    • Value欄とText欄に入力されている文字を消して空欄にします

SceneName欄

これでシーン名の入力欄はできあがりです。同様にCreateボタンを作ります。

  • Library欄からButtonをダブルクリックして追加します
  • Inspectorで以下を設定します
    • Name欄にCreateButtonと入力します
    • Text欄にCreateと入力します

以上でエディタウィンドウは完成です。Ctrl + Sキーを押して保存したら、UI Builderウィンドウは閉じて構いません。

コントロールに機能を仕込む

Visual C#のようにUI Builderから直に機能を仕込むことはできません。先に作成したC#スクリプトを開いて実装します。

呼び出しメニューの設定

呼び出すメニューを予定の場所に変更します。

  • Projectウィンドウの Assets > Editorフォルダー内の NewSceneEditorWindowC#スクリプトをダブルクリックして開きます
  • メニューはMenuItem属性で編集できます。ShowExample()メソッドの上にある Window/UI Toolkit/NewSceneEditorWindow を呼び出しているMenuItemを変更します。ついでに ShowExample() という名前をShowNewSceneWindow()に変更します
    // 9:
    [MenuItem("Tools/AM1/Create New Scene")]
    public static void ShowNewSceneWindow()

上書き保存してUnityに戻ると、先ほどあった Windowメニューの UI Toolkit > NewSceneEditorWindow メニューが消えています。代わりに Tools メニューが追加されて、 AM1 > Create New Scene と選べるようになります。Create New Sceneを選べば UI Builder で作成したエディタウィンドウが表示されます。

エディタウィンドウの呼び出し

コントロールの状態管理とイベント登録

シーン名が入力されていない時はCreateボタンを無効にしたり、Createボタンを押した時にCreateScene()メソッドを呼び出すようにスクリプトを追加します。追加先はCreateGUI()メソッドです。

サンプルが用意したラベルを追加する以下の3行は不要なので消します。

// 21:
        // VisualElements objects can contain other VisualElement following a tree hierarchy.
        VisualElement label = new Label("Hello World! From C#");
        root.Add(label);

管理しやすいようにコントロールインスタンスを取得しておきます。9行目付近にインスタンス変数として以下を定義します。

// 9:
    TextField sceneNameText;
    Button createButton;

CreateGUI()メソッドの最後にあるroot.Add(labelFromUXML);の下に以下を追加します。

// 29:
        // コントロールのインスタンスを取得
        sceneNameText = root.Query<TextField>("SceneName").First();
        createButton = root.Query<Button>("CreateButton").First();

rootVisualElementのインスタンスからQueryを使ってコントロールインスタンスを取得することができます。このメソッドは結果をリストで返すので、最初の1つだけ取り出すために最後にFirst()を付けています。

NewSceneEditorWindowクラス内に以下のメソッドを追加します。

// 34:
    /// <summary>
    /// コントロールの状態を更新。
    /// </summary>
    void UpdateControl(InputEvent ievt)
    {
        createButton.SetEnabled(!string.IsNullOrEmpty(sceneNameText.text));
    }

    /// <summary>
    /// 新規シーンの作成
    /// </summary>
    void CreateScene(ClickEvent cevt)
    {
        Debug.Log($"シーン{sceneNameText.text}を作成する予定");
    }

UpdateControl()メソッドは、シーン名が未入力かどうかでCreateボタンの有効か無効化を切り替える処理です。CreateScene()メソッドにはあとでシーンの作成処理を実装することにして、とりあえずログにメッセージを表示しておきます。

メソッドができたらそれらを登録します。CreateGUI()メソッドに追加したインスタンスを取得するコードの下に以下を追加します。

// 33:
        // コントロールの状態を更新
        UpdateControl(null);

        // 処理を登録
        sceneNameText.RegisterCallback<InputEvent>(UpdateControl);
        createButton.RegisterCallback<ClickEvent>(CreateScene);

以上できたら上書きしてUnityへ切り替えます。NewSceneEditorWindowを表示するとCreateボタンが無効になります。シーン名を入力するとCreateボタンが押せるようになり、ボタンを押すとログにメッセージが表示されるようになります。

イベント登録

以上でウィンドウの動きが実装できました。

コントロールごとのRegisterCallbackで使えるイベントについて

UI Toolkitには様々なコントロールがありますが、各コントロールでどのイベントが登録できるかをどこで調べればよいかが分かりませんでした。

困った時はChangeEvent<>に扱う型をジェネリックで渡せばよさそうです。EnumFieldの変更を受け取りたい時に、ChangeEvent<System.Enum>とすることで登録することができました。

どこかに資料がまとまっていたらご教示いただけると助かります。

シーン作成

本丸であるシーン作成をCreateScene()メソッドに実装します。

保存先のフォルダーを選択

シーンの保存先のフォルダーを選択します。フォルダーの選択にはEditorUtility.SaveFolderPanel()を使います。フォルダーを選択すると選択したパスが文字列で返され、キャンセルしたら空文字が返されます。空文字が返されたら何も処理せずに戻るようにしておきます。

先に追加したCreateScene()メソッド内のDebug.Log()を削除して、以下のコードを追加します。

// 52:
            // フォルダー選択
            string folder = EditorUtility.SaveFolderPanel("保存先フォルダー", "" , "");
            if (string.IsNullOrEmpty(folder)) return;
            createButton.SetEnabled(false);

オブジェクトやシーンの作成中にアセットの再読み込みなどが発生するため、ボタンが押せる状態のままだと何かと問題が起きがちです。処理を始める前にボタンを無効にしています。

Unityのエディター拡張で新規シーンを保存しようとするとエラーが出る

シーン作成の時に苦戦したのがこの部分でした。当初は保存先とシーン名を指定するためにEditorUtility.SaveFilePanel()EditorUtility.SaveFilePanelInProject()を試したのですが、保存先を指定すると書き込み権限がないというようなエラーが出ることがあり、動作が不安定になりました。作成するシーン名は予め入力しているので、保存先のフォルダーさえ分かればいいということでSaveFolderPanel()に変更してSaveScene()メソッドで保存することで安定して動くようになりました。

新規シーンの作成

新規シーンはEditorSceneManager.NewScene()メソッドで作成できます。このメソッドを利用するためにスクリプトファイルの上の方に以下のusingを追加します。

// 5:
using UnityEditor.SceneManagement;

フォルダーの選択処理に続けて以下を追加します。

// 57:
            // 新しいシーンを作成
            var newScene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Additive);

空のシーンを追加シーンとして作成するコードです。引数でデフォルトオブジェクトを配置したり、現在のシーンを解放して作成したシーンのみを開くこともできます。作成したシーンのインスタンスは保存時に使うのでnewSceneに代入しておきます。

テンプレートからシーンを作成する方法はコガネブログさんの以下の記事が分かりやすいです。

baba-s.hatenablog.com

オブジェクトの作成

オブジェクトを作成します。上のコードに続けて以下を追加します。

// 60:
        // オブジェクト作成
        var go = new GameObject();
        go.name = sceneNameText.text+"Behaviour";
        Undo.RegisterCreatedObjectUndo(go, $"Created {go.name} Object.");

new GameObject();を実行すると、空のゲームオブジェクトがアクティブシーンに作られます。先にNewScene()で作成したシーンは自動的にアクティブシーンになっているので、このままで新しく作成したシーンに作ったゲームオブジェクトが配置されます。

オブジェクトを作成したことをUndoのシステムに登録するためにUndo.RegisterCreatedObjectUndo()を呼び出します。これによりオブジェクトの作成をUndoしたり、シーンが更新されたことをシステムが把握できます。

新規にオブジェクトを作成するのではなく、プレハブを読み込んで配置する場合はおもちゃラボさんの以下のブログをご覧ください。

nn-hokuson.hatenablog.com

シーンの保存

作成したゲームオブジェクトにAddComponent()で必要なコンポーネントをアタッチしたり、その他のオブジェクトやプレハブを配置してシーンを完成させたら保存します。シーンはEditorSceneManager.SaveScene()で保存します。保存先のフォルダーは作成済みである必要があります。またフォルダーはプロジェクトフォルダーからの相対パスで指定します。

Pathを利用するためにスクリプトファイルの上の方に以下のusingを追加します。

// 6:
using System.IO;

オブジェクトの作成後に以下を追加します。

// 66:
        // シーンの保存
        string scenePath = Path.Combine(folder, sceneNameText.text + ".unity");
        var relPath = "Assets/" + Path.GetRelativePath(Application.dataPath, scenePath);
        var path = AssetDatabase.GenerateUniqueAssetPath(relPath);
        EditorSceneManager.SaveScene(newScene, path);
        AssetDatabase.Refresh();

        sceneNameText.value = "";

選択したフォルダーとシーン名に.unity拡張子をくっつけて保存先のパスをscenePathに代入します。SaveScene()はプロジェクトフォルダーからの相対パスを指定しますが、scenePath絶対パスなのでApplication.dataPathからの相対パスを取得して、先頭にAssets/をくっつけた相対パスrelPathに代入します。シーン名が重なっていても問題が起きないようにAssetDatabase.GenerateUniqueAssetPath()を使ってファイル名を調整した後、シーンのインスタンスと作成したパスを指定してシーンを保存しています。最後に作成したシーンをエディタに認識させるためにAssetDatabase.Refresh()を実行して、シーン名を空にして完了です。

保存してUnityに切り替えれば作成したエディタ拡張が動作します。

まとめ

UI Builderでエディタウィンドウを作成して、UI ToolkitのC#スクリプトで機能を実装しました。また、保存先のフォルダーを選択して自動で新規シーンを作成してオブジェクトを配置するコードを紹介しました。

エディタ拡張については以下のドキュメントでざっと基本は把握しました。

docs.unity3d.com

UI Builderの始め方やコードでの呼び出し方、シーンの保存など、ドキュメントを探すのに時間がかかったあたりをこの記事でまとめました。現在、これらを使って自家用フレームワークを手軽に組み込めるエディタ拡張を開発しています。

参考・関連URL

今回作成したコード

GDevelop Game Jam #2に参加しました!

7月末の早朝、 itch.io さんのリツイートが目にとまりました。

ゲームジャムと言う目標があると張り合いがあるし、1週間ぐらいなら夏休みの自由研究として丁度良さそう。ということで取り組んだ成果物が以下のゲームです。

キーボードとマウス操作で、WASDキーか矢印キーで移動、マウスでエサを投げます。お墓を舞台にしたボコスカウォーズ的なシュール系シューティングゲームです。評価期間は日本時間の8/13(土) AM4時までなので間に合わないかもしれませんが、遊んで評価を投稿いただけると嬉しいです!!

itch.io

勉強の仕方や開発の流れ、GDevelopを使ってみての感想などをまとめてみました。

目次

はじまり

冒頭のツイートを見た7/30はちょこっとサイトを覗いたりチュートリアルを眺めたぐらいで別のことをしてたと思います。実際に触り始めたのは7/31の午前。

無料で簡単なゲーム制作アプリ | GDevelop

オンラインで試せる!!

オンラインで試せるのはめっちゃ楽!「チュートリアルをフォロー」から How To Make a Platformer のチュートリアル動画を見ながらブラウザー上で試してみました。

俺はPlatformerで行く!!

動画は3本で合計20分程度。動画を見ながら1時間足らずでプラットフォーマーゲームが作れてしまいました。GDevelopのチュートリアル動画は充実していて、1本あたりの長さが数分にまとめられているのでとても見やすいです。英語ですが操作は動画を見れば分かるので問題ない気がします。

GDEVELOPER WIKIチュートリアルなら日本語化されています。内容が少し違うので、こちらのプラットフォーマーチュートリアルも試してみました。

wiki.gdevelop.io

GDevelopのデスクトップ版向けの内容でしたがWebブラウザ上でやりました。Webブラウザーだと画像のアップロードが少々面倒なのでチュートリアルで紹介されていた素材は使わず、アニメーションの画像追加時に利用できるアセットストアからそれっぽい画像を選んで利用しました。アセットストアで手軽に素材が探せるのも大きな魅力です。チュートリアルは、アクション名などが実際のツールと異なっていたり、オブジェクト名やアニメ名が日本語だとエラーになるなど一部読み替える必要はありましたが、大きな問題はなく無事に完了できました。

Webブラウザー版での保存は、プロジェクトのjsonファイルをGoogleドライブにアップロードするか、エクスポートしてダウンロードすることになります。GoogleドライブのUIは暫定的な感じで指定がしにくかったのでエクスポートしました。が、エクスポートしたものはどのように読めばいいのか・・・。この辺りがWeb版で作業する限界そうです。ここまでで問題なさそうならデスクトップ版をインストールしちゃいましょう。このインストールがまたお手軽で、自分だけインストールを選べば管理者権限が不要です!!Webブラウザー上でエディターが動くことと、管理者権限がなくてもインストールができるのは最高です。

これから先の開発はデスクトップ版で行いましたが、ちょっと機能を試したり実動サンプルを見たりする時にWebブラウザー版は便利で今も活用しています。

GDevelopの使い方や簡単なゲームの作り方を把握するには午前だけで十分でした。ちなみにWikiの基本事項はこの時点ではまだ読んでません。開発するゲームによって必要な機能が異なるため、まずはGDevelopが得意そうなジャンルを確認して、企画を決めてから必要そうな機能をみつけて勉強していくようにしました。

企画検討

7/31の就寝前に軽く企画を考えました。考えたのは以下の2案です。

Is that your pet? (それはあなたのペットですか?)

1対1で動物と対峙して、相手の攻撃を防いだりエサを投げたりして手懐けられたらステージクリアです。

Is that your pet?案

勝ったら「Yes! That is your pet!! (そうです。それはあなたのペットです!!) 」、負けたら「You were a bait... (あなたはエサでした) 」とか表示するとか。タイトルや結果のテキストはよさそうに感じましたが、バリエーションを用意するのがしんどそうなのと、ゲームの動かし方のイメージがまとめきれなかったので保留しました。カードゲームとかサイコロゲームにする方向性もありそうでしたが、いずれにせよ素材の用意が大変なのでボツでした。

Haunted Animals in The Cemetery (墓場のお化け動物たち)

2案目が完成させたゲームの案です。

Haunted Animals in The Cemetery案

ハイパーカジュアルでよくみる数字が増えていくブロック崩しとか仲間が増えていく系です。敵にエサを食べさせて手懐けるのがなんとなく今回の自分的なコアだったので、体当たりではなくシューティング要素を導入しました。こちらはプレイヤー、敵1種類、ペット1種類、エサ、背景、墓ぐらいでいけそうで、ゲーム内容も具体的に思い浮かびます。翌日に改めて検討することにして就寝しました。

企画の整理と調査

8/1、前夜に考えた案のざっくりイメージから。

ゲーム画面は360x640の縦画面にして、黄色がプレイヤー、赤がエサ、白が敵、灰色が墓石です。ハイパーカジュアルのゲームを思い浮かべてキャラは小さめにして、キャラが沢山出てくるようにという狙いです。この落書きからキャラを24x24ピクセル、墓石を32x32ピクセルの大きさに決めました。

操作方法や基本的な動き方をNotionでまとめたあとは技術調査です。プレイヤーの移動はGDevelopが最初から用意してくれているトップダウンビヘイビアで行けそうです。画面切り替え方法、シーンの初期化、マウスを狙った弾の撃ち方、演出、スクロールなどなどを調べていきました。今回のゲームの基礎は The Conviction of GUN DUDE のチュートリアルに詰まってました!

夕方ぐらいまでチュートリアルを(遊んだり)見まくったりしながらTodoリストやら仕様やらを作成。それからGitHubリポジトリー登録して開発を開始しました。

開発進行

開発については書き始めると長くなりそうなので別記事ということにして流れだけまとめます。

7/30(0日目)

  • 早朝
    • GDevelopとそのゲームジャムが開催されることを知って興味を持つ

7/31(1日目)

  • 午前
  • 就寝前
    • アイディア出し

8/1(2日目)

  • 日中
    • 仕様まとめと状態遷移、マウス操作などの技術調査、Todoリスト作成

8/2(3日目)

  • 午前
    • 状態遷移の実装

  • 午後以降
    • 外部関数やビヘイビアの調査、フェードの改良、スコア管理、リーダーボードの組み込み開始

8/3(4日目)

  • 午前
    • リーダーボードなどを含むゲームループ完了
  • 午後
    • 音周り実装、プレイヤー操作、カーソル操作、仮アニメ、1つエサ投げ

8/4(5日目)

  • 午前
    • エサ投げ続き
  • 午後
    • 出講のため作業無し

8/5(6日目)

  • 午前
    • スクロール関連
  • 午後

8/6(7日目)

8/7(8日目)

  • 午前

  • 午後
    • 東京ゲームダンジョンに遊びに行く。元気を得て帰宅
  • 21:35
    • 演出を入れて、最小版をゲームジャムに提出!
  • 26:00
    • **今回のプロジェクト、完了!

GDevelopの良い点、気になった点・不明点

1週間使ってみてのGDevelopへの感想です。

良い点

沢山あるのでざっと思いついたところを。

  • インストール不要のWebブラウザ版エディターで機能が一通り試せる
  • デスクトップ版が管理者権限なしでインストールできるお手軽さ
  • HTML5ビルドのみなら制約なく無料で使える
    • 他のビルドはお値段によって1日の回数制限があります
    • 無料だとデバッガー使う時などにちょいちょいお支払い確認のダイアログが表示されます
  • プラットフォーマートップダウン系のゲームを開発するための便利機能が揃っていてすぐ作れる
  • アセットストアで簡単に素材を入手できる
  • チュートリアルが充実
  • 物理エンジン、Tween、パーティクル、ブルームを含む画面エフェクトなど、予想以上に表現力が高く、また手軽に使える
  • HTML5ビルドが超速。下手すると1秒程度で終わる
  • Liluoにはツールからアップして公開ができる。itch.ioへの公開も楽

コントリビュート案

GDevelopはオープンソースなので、不満は言うものではなくコントリビュートするものだ!ということで、気になった部分を改善・解消できそうな機能案です。コミュニティを全然把握していませんし、本気でやることを検討しているのではなく、ちょっと思いました程度のものです。

  • テキストオブジェクトのAlignを幅基準に変更
  • 日本語モードでも英語のコマンド検索を有効にする
    • 日本語にわざわざ変換して「変数」とか検索するのが辛いので....
  • Tweenの時間の単位設定の追加
    • 他は秒が基本なのに、Tweenだけミリ秒指定で何回もハマったため
  • 式エディター内でのネストした構造体や配列の補完
  • 構造体の要素変数の並び順の設定(変数は自由に並び替えできました。2022/8/18追記)
    • 自動的にアルファベット順位並び替えるのをやめてほしい。構造体の要素変数の並び方は自分で選びたい
  • 繰り返しの設定を条件にも入れる
    • 今はイベントを右クリックして、他を追加 から選ぶようになっていますが、条件内にあっていいと思うもので
  • 変数にコメント欄を追加
    • 変数にコメントは必要だと思っているのですがそうでもないですかね
  • イベントエディターで、オブジェクトが全てのオブジェクトなのか、条件に合致したオブジェクトなのか、インスタンスごとなのかを表示したい
  • アニメーションをPiskelで編集する際、既存の画像を他から指定したものを保存する時、上書き保存ではなく名前を付けて保存ダイアログを出す
  • シーンエディターのプロパティの拡充
    • 色や透過度、非表示、センタリングなどのデザインまわりはシーンエディターで完結できるようにしたい
  • ベクトルと行列の拡張
    • ベクトル好きとしてはGDevelopにベクトルがないことに愕然としました。2Dだってベクトルがあった方が遥かに楽です。XとYを別々に宣言するとか面倒で嫌な訳です
  • 各種座標指定の強化
    • 中心座標、当たり判定バウンディングなどを条件やアクション、式の中で自由に使いたい

Tweenの時間の単位設定などの実際にできそうなものから、シーンエディターのプロパティとかは無理っぽいものまであれこれ書きました。まずはコミュニティをROMったり、リポジトリーをクローンして眺めたりして実現できそうか見極めてみます。

気になった点

その他、気になった点です。

閉じたイベントが見にくい

デフォルトのテーマであるGDevelop default Darkの時のイベントの閉じているアイコンの見え方は以下の通りです。

GDevelop default Darkだと閉じたアイコンが見えない!

赤で囲まれた部分はイベントを畳んでいるのですが、アイコンが全然見えません。危うく「ここ空っぽじゃん」と思って消そうとしたり、「あの処理は一体どこに書いたっけ・・・」と行方不明になることが何度かありました。一通り確認してみたのですが、畳んだ状態が見やすいのはGDevelop default Lightのみでした。

これなら見える

ダークの方が目に優しいので、色のカスタマイズ方法を探してみるつもりです。

変数とコードが分かれているのが面倒

処理を書きながら必要な変数に気づいた時に変数ウィンドウを開くのが地味に面倒でした。全エディター画面がフローティングウィンドウならめちゃくちゃ便利なのですが流石にそれは贅沢がすぎる望みですね。素直にショートカットを覚えます。

定義しない変数が使える

変数を定義せずに使えるのは手軽な反面、タイプミスをしてもエラーにならないので問題の発見に時間がかかります。これはJavaScriptの仕様なのでやむを得ず。理解して気を付けるしかありません。

PiskelのUndo

「塗るの失敗しちゃった。Undoしよ」とやったらGDevelopごと落ちました。検索しても問題になってなさそうなのでうちのPCの問題っぽいですが、何回か発生したのでUndoは封印しました。

次回に向けて

濃厚な一週間で収穫が盛り沢山でした。他の参加者の皆さんの作品を遊んで感じたことや、終盤でようやく気付いた機能など、次回に向けて書き残しておきます。

Bloomを使う

最初の技術調査で見落としていて今回はBloomが使えない想定で画面を検討していました。Bloomが使えるならデザインが違っていたと思います。次回はBloomを使ったプリミティブなデザインを試してみたいところです。やっぱドット絵を描くのは辛い・・・

フレームワークは開始前に作っておく

1週間のうち3日程度はフレームワークに費やしていました。ハイスコアを一度登録しのがすと再度の登録ができないようなまずい仕様になっているのに気づかなかったりしましたし、この辺りは事前に整備しておきたいところです。

変数は構造体でまとめる or 命名規則でなんとかする or ビヘイビアを活用する

チュートリアル程度だとそれほど変数が多くないのでシーンやらオブジェクトにぼこぼこ変数を追加していたのですが、定数なんかも変数に定義しておきたいよね~とやっていったらかなりの数になって探すのが面倒に^^;

プレイヤーの変数。1画面で納まりきらず

この辺りの運用はもう少し検討が必要そうですが、ビヘイビアをちゃんと勉強するのが正解な気がしています。

画面レイアウト

PCで公開するなら、ゲーム画面が縦画面でも基本レイアウトは横サイズで作った方がよかったです。 Liluo だと画面をセンタリングしてくれないのでかっこ悪い・・・。操作説明を余白に表示するなどの活用もできます。

スクリーンショットに動画をつける

前回のWall Walkerではちゃんとプレイ動画をアップしていたのですが、今回は作っていたにも関わらずアップし忘れ。一目でどんなゲームか分かった方が遊びやすいと思うので動画は必須だった気がします。

公開後はすぐに他の人の作品を遊んでおく

作品数が多いのでこちらから遊びにいかないと全く遊ばれません!(Unity1週間ゲームジャムの遊ばれ方が異常)。遊べばちゃんと遊び返してもらえるので、目に付きやすい初期に遊びまわってコメントを残しておくのが吉でした。

最後に

GDevelopは2Dに特化したゲームエンジンで、導入コストの低さが印象的でした。Webブラウザーで試せて、インストールも管理者権限が不要、サンプルの素材がアセットストアですぐに見つけることができ、スプライトエディターや効果音エディターが組み込まれています。プラットフォーマートップダウンに必要な処理は予め用意されており、物理エンジン、Bloom、パーティクルといった各種機能も揃っています。2Dゲームを作るなら選択肢に入れて損はないゲームエンジンだと感じました。

GDevelopが良いゲームエンジンであり、使い方や今後の方針も把握できました。勉強しはじめて1週間でゲームジャムにゲームを投稿できることの実証もできました。ゲームジャムの成績がどうあれ、すでに十分以上に成果を得られたゲームジャムへの参加でした!!

参考・関連URL

itch.io

Unity2021LTSでAndroidビルドのエラー

Voxelorer BirdをUnity2021LTSにバージョンアップしてAndroidでビルドしてみたのですが諸々エラー。Cross Platform Native Pluginsを入れるとエラーになるのですが、原因はUnityがインストールしたAndroid SDKのライセンスが通ってないという感じでした。

Android Studioを起動して、SDK Managerで以下をインストール。

上記をインストールした先のパスを、UnityのPreferencesのExternal ToolsのSDKパスとして設定しました。詳しくは以下の通り。

youdoyou-motto.com

エラー

発生したエラーは以下のような感じでした。

1つ目

Starting a Gradle Daemon, 1 incompatible and 6 stopped Daemons could not be reused, use --status for details

> Configure project :launcher
WARNING: The option setting 'android.enableR8=false' is deprecated.
It will be removed in version 5.0 of the Android Gradle plugin.
You will no longer be able to disable R8
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\build-tools\30.0.2\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-29\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-30\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\build-tools\30.0.2\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-29\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-30\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\build-tools\30.0.2\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-29\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-30\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\tools\package.xml. Probably the SDK is read-only
File C:\Users\YuTanaka\.android\repositories.cfg could not be loaded.
Checking the license for package Android SDK Build-Tools 29.0.2 in C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\licenses
Warning: License for package Android SDK Build-Tools 29.0.2 not accepted.
Checking the license for package Android SDK Platform 31 in C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\licenses
Warning: License for package Android SDK Platform 31 not accepted.

UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

2つ目

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':unityLibrary:com.voxelbusters.essentialkit.androidlib:compileReleaseAidl'.
> Failed to install the following Android SDK packages as some licences have not been accepted.
     platforms;android-31 Android SDK Platform 31
     build-tools;29.0.2 Android SDK Build-Tools 29.0.2
  To build this project, accept the SDK license agreements and install the missing components using the Android Studio SDK Manager.
  Alternatively, to transfer the license agreements from one workstation to another, see http://d.android.com/r/studio-ui/export-licenses.html
  
  Using Android SDK: C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 10s
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8

UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

3つ目

CommandInvokationFailure: Gradle build failed. 
C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\OpenJDK\bin\java.exe -classpath "C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\Tools\gradle\lib\gradle-launcher-6.1.1.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease"

stderr[

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':unityLibrary:com.voxelbusters.essentialkit.androidlib:compileReleaseAidl'.
> Failed to install the following Android SDK packages as some licences have not been accepted.
     platforms;android-31 Android SDK Platform 31
     build-tools;29.0.2 Android SDK Build-Tools 29.0.2
  To build this project, accept the SDK license agreements and install the missing components using the Android Studio SDK Manager.
  Alternatively, to transfer the license agreements from one workstation to another, see http://d.android.com/r/studio-ui/export-licenses.html
  
  Using Android SDK: C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 10s
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
]
stdout[
Starting a Gradle Daemon, 1 incompatible and 6 stopped Daemons could not be reused, use --status for details

> Configure project :launcher
WARNING: The option setting 'android.enableR8=false' is deprecated.
It will be removed in version 5.0 of the Android Gradle plugin.
You will no longer be able to disable R8
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\build-tools\30.0.2\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-29\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-30\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\build-tools\30.0.2\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-29\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-30\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\build-tools\30.0.2\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-29\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-30\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\tools\package.xml. Probably the SDK is read-only
File C:\Users\YuTanaka\.android\repositories.cfg could not be loaded.
Checking the license for package Android SDK Build-Tools 29.0.2 in C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\licenses
Warning: License for package Android SDK Build-Tools 29.0.2 not accepted.
Checking the license for package Android SDK Platform 31 in C:\Program Files\Unity\Hub\Editor\2021.3.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\licenses
Warning: License for package Android SDK Platform 31 not accepted.
]
exit code: 1
UnityEditor.Android.Command.WaitForProgramToRun (UnityEditor.Utils.Program p, UnityEditor.Android.Command+WaitingForProcessToExit waitingForProcessToExit, System.String errorMsg) (at <089eca9a0a77417a901dda0093fda7f3>:0)
UnityEditor.Android.Command.Run (System.Diagnostics.ProcessStartInfo psi, UnityEditor.Android.Command+WaitingForProcessToExit waitingForProcessToExit, System.String errorMsg) (at <089eca9a0a77417a901dda0093fda7f3>:0)
UnityEditor.Android.Command.Run (System.String command, System.String args, System.String workingdir, UnityEditor.Android.Command+WaitingForProcessToExit waitingForProcessToExit, System.String errorMsg) (at <089eca9a0a77417a901dda0093fda7f3>:0)
UnityEditor.Android.AndroidJavaTools.RunJava (System.String args, System.String workingdir, System.Action`1[T] progress, System.String error) (at <089eca9a0a77417a901dda0093fda7f3>:0)
UnityEditor.Android.GradleWrapper.Run (UnityEditor.Android.AndroidJavaTools javaTools, Unity.Android.Gradle.AndroidGradle androidGradle, System.String workingdir, System.String task, System.Action`1[T] progress) (at <089eca9a0a77417a901dda0093fda7f3>:0)
Rethrow as GradleInvokationException: Gradle build failed
UnityEditor.Android.GradleWrapper.Run (UnityEditor.Android.AndroidJavaTools javaTools, Unity.Android.Gradle.AndroidGradle androidGradle, System.String workingdir, System.String task, System.Action`1[T] progress) (at <089eca9a0a77417a901dda0093fda7f3>:0)
UnityEditor.Android.PostProcessor.Tasks.BuildGradleProject.Execute (UnityEditor.Android.PostProcessor.PostProcessorContext context) (at <089eca9a0a77417a901dda0093fda7f3>:0)
UnityEditor.Android.PostProcessor.PostProcessRunner.RunAllTasks (UnityEditor.Android.PostProcessor.PostProcessorContext context) (at <089eca9a0a77417a901dda0093fda7f3>:0)
Rethrow as BuildFailedException: Exception of type 'UnityEditor.Build.BuildFailedException' was thrown.
UnityEditor.Android.PostProcessor.CancelPostProcess.AbortBuild (System.String title, System.String message, System.Exception ex) (at <089eca9a0a77417a901dda0093fda7f3>:0)
UnityEditor.Android.PostProcessor.PostProcessRunner.RunAllTasks (UnityEditor.Android.PostProcessor.PostProcessorContext context) (at <089eca9a0a77417a901dda0093fda7f3>:0)
UnityEditor.Android.PostProcessAndroidPlayer.PostProcess (UnityEditor.Modules.BuildPostProcessArgs args, AndroidPlayerBuildProgram.Data.AndroidPlayerBuildProgramOutput buildProgramOutput) (at <089eca9a0a77417a901dda0093fda7f3>:0)
UnityEditor.Android.AndroidBuildPostprocessor.PostProcess (UnityEditor.Modules.BuildPostProcessArgs args, UnityEditor.BuildProperties& outProperties) (at <089eca9a0a77417a901dda0093fda7f3>:0)
UnityEditor.PostprocessBuildPlayer.Postprocess (UnityEditor.BuildTargetGroup targetGroup, UnityEditor.BuildTarget target, System.Int32 subtarget, System.String installPath, System.String companyName, System.String productName, System.Int32 width, System.Int32 height, UnityEditor.BuildOptions options, UnityEditor.RuntimeClassRegistry usedClassRegistry, UnityEditor.Build.Reporting.BuildReport report) (at <31b86d204baf45de8328f2d1261a79f7>:0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)

参考URL

ぺんそろ~Unity1週間ゲームジャム「そろえる」

ぺんそろ

ぺんそろ | フリーゲーム投稿サイト unityroom

unityroom.com

2022年05月02日(月) 00:00〜2022年05月08日(日)のGW中に開催されたUnity1週間ゲームジャム「そろえる」に参加しました。完成作品はこちらの「ぺんそろ」です。

ざっくり振り返りです。

目次

評価や結果

まずは終わったばかりで感覚を忘れないうちに結果から。いただいた評価は以下の通りでした。

みんなの評価

  • 楽しさ 3.952
  • 絵作り 4.048
  • サウンド 3.476
  • 操作性 3.571
  • 雰囲気 3.905
  • 斬新さ 3.714

楽しさ、絵作り、雰囲気が良い感じで、だ氏さんの参加の効果が発揮されています!!コメントでも「あぶな~い!!」システムが好評でした^^楽しさで44位にランクインできました。

楽しさ44位!!

遊んで評価を入力してくださったり、コメントいただいた皆様、ありがとうございました!!

今回の自分のテーマ

今回も開発関連のテーマ主体でした。

  • オブジェクト指向や設計、インターフェースの練習
  • URPとShaderGraphをいじる
  • アイテムなどにバリエーションを作る
  • 共同制作

自己完結できるテーマなので一通り達成できて収穫がありました。このあたりはまた別ブログで。

企画の振り返り

インターフェースを使ったり拡張性が出せそうなもので、苦手としているカードゲームや3マッチゲームのアレンジ辺りから考えてみたのですがまとめられず。共同制作だから確実に完成させられるように、床の高さを揃えてキャラクターを先に進める案で進めることにしました。これなら2~3日ぐらいでゲームは動くかな?と思ったのですが甘かったです^^;

クライマックス要素を入れたくて無敵アイテムで床まで壊しまくれるように考えました。発動すると面白いのですが、狙ってできないし、発生頻度も低いので不発だった気がします。

無敵!!

その代わりにお助けシステムが救済になりました。これによってキャラクター性が出せて、これまでの自分の作品にはない味わいが出ました。

あぶなーい!!

折角縦画面で作ったのでスマホアプリ化もなんとなく検討しています。が、スクロール型でいいのかとか、メイン要素が足りない気がするとか、検討中です。

次回に向けて

強そうな企画案が思い浮かばなかったので今回も開発練習が主体になりましたが、思い浮かびさえすれば企画主導のものも作ってみたいというのがあります。参加者の皆様の作品を見て感じたこと、自分でも試みてみたいことを次回に向けて挙げておきます。

  • 1画面にメインゲームを収める
  • 非リアルタイムで疲れない、癒し
  • 操作で変わった体験ができる
  • 操作やタイミングを失敗に直結させない
  • ランキングは最初に名前登録して自動送信(ただしランキングは無くても大丈夫)
  • (なんちゃって)リアルタイム順位表示
  • 動画撮影時は効果音のみにして、BGMは動画編集で入れる

今回も実り多い1週間ゲームジャムでした。ちゃんと収穫しないと・・・

参加の皆様、お疲れさまでした。遊んで下さった皆様、ありがとうございました!また次回の1週間ゲームジャムで!!

ジェネリッククラスの継承。抽象、インターフェイスも添えて

ジェネリッククラスを継承するための定義の書き方で難儀したのでメモ。

以下、簡易シングルトンをジェネリックで扱いつつ、それを更に解消しつつ、インターフェイスも実装。

    public abstract class ResqueActionBase<T> : SimpleSingleton<T> where T : IResqueAction, new()
    {
        // ...
    }

whereを継承元側に書くのか。未だにジェネリックは書き方を見慣れていないので難儀する。

インターフェイスを親に実装したら、子側にも実装を書く必要があるので注意。改めて考えれば当たり前だけど忘れてたので・・・。

参考URL

docs.microsoft.com

ClusterGAMEJAME 2022 in SPRINGに参加した48時間

天翔ける腕輪

天翔ける腕輪|メタバースプラットフォーム cluster(クラスター)

 

Cluster GAMEJAM 2022 Springの参加記念メダルが届きました!!

参加記念メダル

書かねば書かねばと思いつつなかなか手が付けられず開催から1ヶ月以上過ぎてしまいましたが、テーマ発表から公開までの48時間の記録です。

 

目次

 

一人企画会議(3/18 20:30-25:00)

開会式への参加からスタート!

テーマは「かける」!!翔ける、架ける、掛けるなど色々解釈ができて楽しそうなお題です。ちなみにこの時はデフォルトアバターでの参加でした。

 

テーマが判明した21時ごろから一人企画会議の開始です。Notionに思いついたことを箇条書きしたり、iPadのメモ帳に落書きしながら企画を模索しました。

  • 虹を動かす、あるいは発生させて橋をかけて、ワールドを巡ってスタンプ帳を完成させる
  • クレーンで橋を操作する
  • アイテムを使って橋を出現させる

準備段階で考えていた巨大ロボを動かしたいとか、ステージを大きく動かすところから着想。他のプレイヤーごと、ステージの地形をごっそり動かしたいとか、俯瞰でステージを見たいとか、ざっくりとしたイメージは沸くのですが、今ひとつ形にならず。引き続きアイディア出し。

  •  雨雲を操作して、雨が去ったら虹の橋がかかるので、それを歩いてゴールを目指す
  • クマを操作して、木を倒して橋をかけて移動する
  • クレーンを操作して、クレーンの先に吊り下げられているやかんからステージに置いてあるカップ麺や、他のプレイヤーにお湯をかけるというインパクト系のやつ

最終形までイメージが広がらないし、プレイヤーが移動している状態と何かを操作している状態の2つの状態があるとプレイ感が散漫になりそうです。乗り物に乗っている状態だけで完結することを考えて、靴を乗り物にする 案が出ました。

天翔ける腕輪の最初のイメージ

スタート地点から夜空を見上げると、他のプレイヤーが跳んでいる靴からパーティクルとトレイルが放たれて虹がかかっているように見える、そんなイメージです。操作方法、やること、見せたい画面のイメージがハッキリと思い浮かびました。この案はいけそうです。

 

当初は奇抜で驚けて笑えるものにしたかったのですが、アイディアが降ってこないのでは仕方ありません。それはまたの機会ということで、降りてきてくれたこの案を48時間で形にします!!

 

仮タイトルを「天翔ける靴」として、Notionに全作業を書き出して、大項目をツイート。

18日の21時から25時の4時間で企画と作業リストを作成して、少しUnityのプロジェクトの整理などをして初日を終えました。

制作1日目 3/19

画面作り -9:20

画面作りから制作開始です。予め調査していたPureNatureの岩のプレハブをシーンに配置して足場を作ります。

assetstore.unity.com

パーティクルやトレイルを奇麗に見せるために夜のステージにしたかったので、以下のようなアセットからよさげな星空を探しました。

PureNatureの空はデフォルトのSkyboxに雲のシェーダーで構成されていました。上空の設定なので星空が欲しいので不可です。Clusterのサンプルの星空も良い味わいなのですがディテールが合わなかったので不採用。Space Graphics Planetsは星そのものを作るのがメインのアセットでした。星空もあったのですがスクリプトが必要でClusterと相性が悪そうだったので不採用。ということで、最後はいつものFantasy Skybox | 2D Sky | Unity Asset Storeに落ち着きました。以前見た時より表現が増えていてかっこよくなってました!

assetstore.unity.com

 

いい感じの夜空と舞台ができました!

画面作り完了

プレイヤーのアニメ作成、音探し、BGM再生 9:20-13:50

プレイヤーを動かすのに必要な跳ぶ時のアニメーションを作成します。作業に取り掛かったところで、Clusterの乗り物に乗った時の足の位置は、乗り物に設定したアニメから変えられないことに気づきました。跳ねる時に足が動かないのは寂しいです。制御できるのは座る位置と腕の位置。ということで、飛ぶためのギミックは足ではなく、腕につけることに変更して「天翔ける腕輪」になりました。

 

腕輪をProBuilderで作成して、乗り物としてClusterのギミックをアタッチします。腕輪を拾ったり、置いたり、浮遊、加速、というアニメを腕輪や手の位置のオブジェクトの移動で作っていきます。腕輪の位置の調整は、Unity Editor上だとアバターが表示されないので、ビルドとClusterへのアップロードを繰り返して行いました。

 

昼食を食べながらBGMと効果音探し。今回は音楽の卵さんの曲でぴったりなものが見つかりました。

ontama-m.com

 

効果音はお世話になりまくっているUniversal Sound FXです。 

assetstore.unity.com

 

14時ちょっと前にBGMを鳴らして一段落です。

 

星モデル、スタンプカードの組み込み、クレジット表示 13:50-17:10

本体の開発に入る前に、準備済みのスタンプカードの組み込みとクレジット表示を実装しました。集める星のモデルをVoxelorerBirdから持ってきたり、スタンプ欄を7つに増やしたり、カードのデザインをしたり、クレジットを書いておくUIを設置したりして17:10ぐらいに完了しました。

星とスタンプ実装

夕方になってまだゲーム本体に手がついてません^^;

 

買い出し

リフレッシュを兼ねて買い出しへ。ご飯を作る時間を節約するために弁当やおにぎり、あとは景気づけのおやつをゲット。帰宅してご飯食べて作業再開。

 

ジャンプの実装 -25:24

日没後からようやくギミック作りです。まずはジャンプから。着地している時と空中にいる時で方向キーとスペースキーの操作が変わります。Is Grounded Character Item Triggerを使えば簡単に実装できると見込んでいたのですが、着地判定が甘くて飛べないことが頻発。Clusterのポニーのギミックをカンニングすると、着地判定はタイマーを使ったりして複雑なことをやってました。

まだできたばかりの機能なのでやむなし。今後の改善を願いつつ、ポニーの着地判定を参考にして必要な動きができました。

 

次は方向キーが押された時の前後左右への加速ギミックです。この時点では、左右は旋回ではなく直に移動でした。24:00ぐらいに作業完了です。

初日終わり

Clusterは内部の値が分からないので、左上にデバッグ用に文字列を表示していました。この辺りがInspectorに表示されるようになると、より開発がしやすくなりそうです。

 

移動周りの効果音を組み込んで開発1日目終わり。残りの作業量から睡眠時間を計算して就寝しました。

 

制作2日目(最終日) 3/20

操作の実装の続き 5:00-9:35

5:00頃から作業再開。前日は左右は直移動でしたが、マウスでカメラを旋回させてもプレイヤーの向きはそのままというのに気づいて、左右キーをプレイヤーの旋回に変更します。2時間ぐらいで対応完了。

 

トレイルとパーティクルを加えて、操作が一通りできるようになったよ報告ツイート。

 

企画の狙いだった軌跡で夜空に虹をかけるがいい感じで実現できてます。企画の筋が良さそうだと感じることができました^^ 

 

ジャンプの動きやジャンプ時にパーティクルを沢山出すとか演出を調整して、寝る前に考えた想定から30分ほど早い9:35に操作の実装を完了しました。

 

星の収集からエンディングの発動、リセット 9:35-12:40

星と星の収集、収集完了後のリセットです。以下のような感じでテストステージに星を並べて、色やアニメを付けたり、スタンプ帳へ反映させたり、全て取った時にクリアのタイムラインを開始したり、状態を元に戻すギミックを作ったり。

星のギミックの開発の様子

マップ作り 12:40-16:50

前日に購入していたおにぎりを食べながらマップ作りに取り掛かります。この段階まで想定より20分早くたどり着きましたが、余裕があるのはここまででした。

 

当初の予定は、スタートの地面があって、そこから上空に向かってところどころに地面が浮いていて、星も浮いていて、スタート地点から他のプレイヤーを含めてステージ全体が見上げられる、という感じでした。しかし実際に跳んでみると、近くにオブジェクトが無いと浮遊感を感じません。ということで、浮いている岩の間を抜けながら星を集めていくという方針に変更しました。

 

7つの星をどのように配置しようか。星が7つ > 7つの傷を持つ男 > 北斗...七星...。という電波を受信。ネットで北斗七星の画像を探して、真上から見てざっくり同じような形に星を配置しました。高さや岩の配置は後回しにして、星を並べた状態で跳んでみてステージの広さを確認しました。最初は1Kmぐらい必要かな?と予想していたのですが、飛んでみたら星まで遠い^^; 調整の結果、スタートからゴールまで250mぐらいになりました。

真上から見た星の配置

広さが決まったら、岩を並べたり、星の高さで緩急をつけたり、外に出られないように見えない壁で囲ったり、PureNatureによさげな雪のパーティクルがあったのでゴール付近に配置したり、ちょっとシロクマ隠したりして、16:47頃にマップの初期版が完成しました。

 

遊んでいるとなかなか面白いし、シロクマなどの予定になかったことをしたため、ここで2時間ほど予定オーバー!ゲーム説明やアップロードにかなり多めの時間を割り当てたり、20時に完了するような余裕を持たせた見積もりだったのでまだ間に合いますが、ここからは時間との勝負です!

 

クリア演出 16:50-17:50

全ての星を取り終えた時のクリアの演出の作成です。タイムラインを使って空に星を流そうと考えていたのですが、Playerの状態を反映させられるのはPlayer UIだけ、ということに作り始めてから気付きました^^; Canvas上でアニメするか・・・とも考えたのですが、時間がありません。ここはメッセージだけ!と割り切って、それっぽいメッセージをPanelで表示する演出をして、あとはスタートに戻るワープを作って、見込み通り1時間で完了させました。

この「どうでもいい演出案」が、クリア時に星をアニメさせるとか、シロクマに乗るとか、動く星があるとか、敵がいるとか、そういったものです。無くても成立するものは省いて公開に向けて集中です。

 

ハイスコアと仕上げ 17:50-20:20

自分の記録は保存できるので、クリアまでの時間がこれまでの最短だったら記録更新を称える機能を付けました。これで予定していた最低限の機能が揃いました。まだバランス調整に使える時間が残っていたので仕上げに入ります。

 

繰り返し遊んでみて、マップの配置を調整したり、ちょっと印象的なものが欲しくなってストーンヘンジみたいなのを配置しました。また、当初からあった案の一つである動く星を1つだけ実装。

 

まだバグが残っていましたが、時間内に解決できるか分かりません。一先ず、バグの内容をスタートの後ろのパネルに操作説明と一緒に書いておいて、バンカー版として公開することにしました。

 

ラストスパート 20:20-21:00

少し時間を残して応募ができました。あとは時間が許す限り、開始時に腕輪を置く音が同時に鳴ってうるさかったり、腕輪を置いて30秒するとスタート地点に強制的に戻されるバグを潰していきました。

 

20:46

 

20:55

 

バグ修正版のアップロードが完了したのは20:59でした。応募締め切りはサーバーの負荷が大変なことになっていたと思いますが、Clusterさんのサーバーは見事持ちこたえてくれました。素晴らしい環境です。

 

21:22

 

以上で「天翔ける腕輪」の応募が完了し、Cluster GAMEJAM 2022 Springを完走しました!!

 

今後のテーマ

今回の参加の目的の一つは、自分に足りないところを知り、これから取り組むテーマを見つけることでした。以下が挙がりました。

  • 「奇抜」「驚き」「笑い」の企画を考えるための入力とイメトレ
  • 他のワールドで圧倒された演出やギミックを観察して、ノウハウを増やす

他に取り組んでいることがあれこれあってこの一ヶ月で早速できていませんが^^;

これを書きながら思い出しました。振り返り大切。

 

最後に

結果は、お陰様で乗り物部門の大賞をいただくことができました!!

 

名前が呼ばれるまでは、他の受賞者の皆さんの作品を眺めて一人反省会をしていました。参加の目的だった今後のテーマを得ることや、実際にワールドを作る経験を得ること、応募作品数を1つでも増やして大会を盛り上げることは達成することができました。これでよし!と思っていたところで受賞というボーナスが加わりました。全力で取り組んで公開すると、時々、想定していなかった良いことがあると改めて感じました。参加すること大切

 

この後、念願だったシロクマに乗れるようにしたり、操作性を調整したりしたものが、現在公開されているものです。実は、当初の目的であった他のプレイヤーの飛ぶ姿を見る、というのが叶っていません。是非、お誘いあわせの上、大勢で星を巡ってみてください!!

cluster.mu

 

授賞式の時は、MagicaVoxelで作ったボクセルキャラクターをオリジナルアバターにしました。作成手順はこちら。

am1tanaka.hatenablog.com

 

使用アセット

AssetStore以外の素材

github.com

なにはなくとも。このプロジェクトを整理して作り始めました。乗り物をはじめ、様々なギミックの応用例が見れる有用な作例の塊です。

 

ontama-m.com

プレイ中、クリア時のBGMはこちらから。ワールドの雰囲気を作り出してくれました。

 

kenney.nl

スタンプ帳の星などちょっとした素材に利用しました。CC0で一通りの素材が見つかるので重宝してます。

 

freefonts.jp

日本語用のフォントアセットはこのフォントから作成しました。

 

fonts.google.com

等幅フォントはこちらから。

 

www.mixamo.com

リング装着中の基本姿勢などはこちらから。

 

Asset Store 

assetstore.unity.com

背景の足場や構造物、雪のエフェクトに利用しました。

 

assetstore.unity.com

夜空に利用しました。空で迷ったら大抵これに行き着きます。

 

assetstore.unity.com

効果音はいつもお世話になっている自分的定番アセットです。

 

assetstore.unity.com

スタート付近のリセットゾーンや、ゴールの先にあるワープゾーンはこのパーティクルから。

 

assetstore.unity.com

シロクマ親子のモデルとアニメモーションはこちらから。本当はここから沢山動物出したかったのですが間に合わず。またの機会に。

 

assetstore.unity.com

Mixamoで入手したモーションの編集に利用しました。

 

assetstore.unity.com

星のボクセルモデルの読み込みに利用しました。作品内ではありませんが、Cluster用のカスタムアバター作成でも利用しました。

 

 

GitHub Desktopをアップデートしたら外付けドライブのリポジトリが読めなくなった

表題の通りなのですが、GitHub DesktopをアップデートしたらPCの内蔵ドライブのリポジトリは問題ないのですが、外付けドライブのものが開けなくなりました。

解決策

4/14にアップデートが出て、外付けドライブのリポジトリを開こうとすると以下のような警告が表示されるようになりました。

f:id:am1tanaka:20220414202803p:plain
警告

これのadd an exception for this directoryのリンクをクリックすると、安全なディレクトリとして指定する設定が書き込まれて開けるようになりました。

原因

原因はGitのセキュリティ設定の影響だったようです。詳しくは以下の通り。

stackoverflow.com

内蔵ドライブのリポジトリフォルダーのセキュリティ設定が、Windowsにログインしたユーザーのものであれば問題なく開けるということです。外付けドライブはFATフォーマットでフォルダーの所有設定がないため、何らかの方法で設定ファイルに安全なフォルダーとして指定を加えないとgitで管理できなくなったわけです。外付けでなくても、同様にリポジトリフォルダーや.gitフォルダーがログインユーザーのアクセスが未設定だと、設定が必要になるようです。

設定

先に示したリンクのクリックを押さなくても、直にGitの設定ファイルにリポジトリのパスを加えればアクセスできるようになるようです。

gitのグローバル設定が~/.gitconifgにあるので、そのファイルを開いて、[safe]を書き加えて、その下の行にリポジトリディレクトリーを追加します。E:/ProjectFolders/Repoフォルダーなら下の通りです。

[safe]
    directory = E:/ProjectFolders/Repo