tanaka's Programming Memo

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

Unityで簡易にBGMと効果音を鳴らす

UnityでささっとBGMや効果音を鳴らす方法です。

  • 音源データの書式の説明が古くなっていたので修正(2022/7/2)
  • 列挙子などの名前をパスカルケースに変更(2021/6/28)

目次

前提

Unityでとりあえず手っ取り早くBGMや効果音を鳴らしたい!というためのサンプルコードと手順です。機能は以下の通りです。

  • BGM
    • シーンごとに、設定したBGMを再生します
    • BGMをループ再生できます
    • 同じシーン内で曲は変えません
    • シーンを跨いだBGMの再生には対応しません
  • SE
    • 1つのオブジェクトですべての効果音を再生します
    • 3Dサウンドは使いません

プロジェクトの準備

Unity2019.1.5での実装例です。

  • Unityでプロジェクトを新規に作るか、音を鳴らしたいプロジェクトを開きます
  • 利用したい音源データ(oggmp3wavなど)を用意したら、Projectウィンドウの任意のフォルダーにドラッグ&ドロップしてインポートします
    • BGMをAudios/BGMフォルダー、SEをAudios/SEフォルダーにまとめた場合、以下のような感じになります

音源データのインポート

音データの種類

Unityでは色々な音声データが利用できます(オーディオファイル - Unity マニュアル)。それらのうち、主に利用するのはoggmp3wavの3種類かと思います。

oggmp3は録音したデータを圧縮したもので、やや音が劣化しますが容量が小さくなります。

(参考: oggとMP3の違いは何でしょうか?持ってるmp3の機械には対応して... - Yahoo!知恵袋)

wavは録音したデータをそのまま保存する形式です。同じ条件で録音した場合、oggmp3よりも容量が大きくなる代わりに音の劣化がありません。

Unityではプロジェクトに音源データを加えた時に内部形式に変換するので、どの形式の音源を使ってもビルドや実行時に違いはありません。

WebGL環境だとキンキンした音の最後にノイズが入ることがあります。特にwav形式で発生する印象があります。そのような場合は、以下のようなサイトで形式を変更したりすると直ることがあります。

Load Typeについて

読み込んだ音声データを選択した時にInspectorに表示される設定です。効果音やゲーム中のBGMの場合はデフォルトのままで大丈夫です。

タイトル画面やゲームオーバーなど、処理が多少重くなっても構わないようなシーンでは、Load TypeStreamingに変更すると音が鳴り始めるのが早くなる(はず)で、よさげです。

タイトルやゲームオーバー用の音源はStreamingにするとよいかも

BGMを鳴らす

BGMを鳴らします。

  • HierarchyウィンドウのCreateをクリックして、Create Emptyをクリックして空のゲームオブジェクトを作成して、名前をTinyAudioなどにします
  • InspectorウィンドウのAdd Componentをクリックして、Audio > Audio Sourceをクリックします
  • Projectウィンドウから、そのシーンで鳴らしたいBGMの音源ファイルをドラッグして、InspectorウィンドウのAudio Clip欄にドロップします

音源データをAudio Clip欄にドラッグ&ドロップ

  • BGMをループ再生したい場合は、InspectorウィンドウのLoop欄にチェックを入れます

Loop設定

以上で設定完了です。UnityをPlayするとBGMが再生されます。BGMはこれでOKです。

効果音を鳴らすためのクラスを作る

効果音はTinyAudioというクラスを作成して、スクリプトから呼び出して鳴らすようにします。

  • Hierarchyウィンドウから先ほど作成したTinyAudioオブジェクトをクリックして選択します
  • InspectorウィンドウのAdd Componentをクリックして、New scriptをクリックして、TinyAudioなどの名前でスクリプトを作ります
    • スクリプトは、Scriptsフォルダーなどを作って、そこにまとめておくのがオススメです
  • Projectウィンドウから作成したTinyAudioスクリプトをダブルクリックしてエディターで開きます
  • 以下のコードを入力、あるいはコピペします
using UnityEngine;

public class TinyAudio : MonoBehaviour
{
    public static TinyAudio Instance { get; private set; }

    /// <summary>
    /// seListに設定する効果音の種類を以下に定義します。
    /// </summary>
    public enum SE
    {
        Click,
        Hit,
        Magic
    }

    [Tooltip("効果音のAudio Clipを、SEの列挙子と同じ順番で設定してください。"), SerializeField]
    AudioClip[] seList;

    AudioSource audioSource;

    private void Awake()
    {
        Instance = this;
        audioSource = GetComponent<AudioSource>();
    }

    /// <summary>
    /// SEで指定した効果音を再生します。
    /// </summary>
    /// <param name="se">鳴らしたい効果音</param>
    public static void PlaySE(SE se)
    {
        Instance.audioSource.PlayOneShot(Instance.seList[(int)se]);
    }
}
  • 上書き保存したら、Unityに切り替えます
  • HierarchyウィンドウからTinyAudioオブジェクトをクリックして選択します
  • Projectウィンドウから効果音のファイルをドラッグして、InspectorウィンドウのSe List欄にドロップします
    • 設定する順番は、TinyAudioスクリプトSE列挙子に対応付けていきます。Clickはクリック音、Hitは攻撃音、Magicは魔法のような音ということで、その順番に設定します

AudioClipを設定

効果音を鳴らす

スクリプトからTinyAudio.PlaySE(TinyAudio.SE.Click);のように呼び出せば指定した効果音が鳴ります。TinyAudio.SE.Clickは、TinyAudio.csの10行目付近に宣言してあります。SE列挙子の最初(0番目)なので、Se ListElement 0に設定した音が鳴ります。

試しに、数字キーで効果音を鳴らす機能を実装します。

  • HierarchyウィンドウのCreateをクリックして、Create Emptyをクリックして、空のゲームオブジェクトを作成して、SETestなどの名前にします
  • InspectorウィンドウのAdd Componentをクリックして、New scriptを選択して、SETestなどの名前にします
    • SETestスクリプトは、Scriptsフォルダーに移動しておくとよいです
  • SETestスクリプトをダブルクリックして、以下のコードにします
using UnityEngine;

public class SETest : MonoBehaviour
{
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            TinyAudio.PlaySE(TinyAudio.SE.Click);
        }
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            TinyAudio.PlaySE(TinyAudio.SE.Hit);
        }
        if (Input.GetKeyDown(KeyCode.Alpha3))
        {
            TinyAudio.PlaySE(TinyAudio.SE.Magic);
        }
    }
}

以上で保存して、Unityに切り替えてPlayします。数字キーの123でそれぞれ効果音が鳴ります。

数字キーを連打すると、効果音が同時に鳴ることが確認できます。今回のように音に3D空間の効果を使わない場合は、1つのAudio SourceでBGMも効果音も鳴らせます。

シーン切り替えに対応する

他のシーンでもBGMを鳴らせるようにします。

  • HierarchyウィンドウからTinyAudioオブジェクトをドラッグして、Projectウィンドウにドロップしてプレハブ化します
    • プレハブは、Prefabsなどのフォルダーを作ってまとめておくのがおススメです
  • ついでにSETestオブジェクトのドラッグ&ドロップしてプレハブ化しておきます
  • [Ctrl]+[S]キーでシーンを保存します
  • 新しいシーンを作るか、既存の別のシーンに切り替えます
  • Projectウィンドウから、TinyAudioプレハブをドラッグして、Hierarchyウィンドウにドロップします
  • 必要に応じて、ProjectウィンドウからSETestプレハブをドラッグして、Hierarchyウィンドウにドロップします(効果音の再生テストが不要な場合は不要です)
  • HierarchyウィンドウのTinyAudioオブジェクトをクリックして選択します
  • 新しいシーン用のBGMをProjectウィンドウからドラッグして、InspectorウィンドウのAudioClip欄にドロップします

BGMの音源データを設定

  • BGMをループさせたいかどうかに応じて、InspectorウィンドウのLoop欄のチェックをつけるか、外します

ループ設定

以上で完了です。PlayするとBGMが鳴ります。SETestオブジェクトを設定してあれば、数字キーの123で効果音が鳴ります。

シーンを切り替えたら、そのシーンに設定したBGMが鳴り始めます。

効果音の増やし方や変え方

効果音を増やしたり変えるには、TinyAudioクラスのSE列挙子の宣言を変更して、それに合わせてTinyAudioオブジェクトに設定する効果音リストを更新します。

  • ProjectウィンドウからTinyAudioスクリプトをダブルクリックして、エディターで開きます
  • 使いたい効果音を全て列挙子SEに定義します。例えば食べる効果音を増やしたいなら、Eatなどの名前で定義を追加します

列挙子を増やす

  • 上書き保存したらUnityに切り替えます
  • ProjectウィンドウのTinyAudioプレハブをクリックして選択します

TinyAudioプレハブを選択する

  • Projectウィンドウから追加したい音データをドラッグして、InspectorウィンドウのSe List欄にドロップするか、Sizeを増やして該当するスロットにドロップします
    • 以下、matchstick-put-fire1を追加している例です

音を追加

以上で完了です。あとはスクリプトからTinyAudio.PlaySE(TinyAudio.SE.Eat);のように呼び出すことで、新しく追加した音を鳴らすことができます。

まとめ

シーン切り替え時に効果音が途切れたり、BGMがシーンを跨げないなど気になる部分はありますが、一先ずBGMと効果音を鳴らすことができました。2DゲームやUIのシステム音など、鳴っている場所の影響を受けない音はここで紹介した以下のような方法が効率よいです。

  • BGMは、Audio SourceAudio Clip欄に音データを設定して再生
  • SEは、PlayOneShot()で再生

3D対応させたり、最初に記載したような多様な機能を実装したい場合は以下のブログなどが役に立つと思います。

kan-kikuchi.hatenablog.com

qiita.com

参考URL

Addressableアセットシステムを使ってみる

Addressableアセットシステムは、テキストなどのデータファイルをそれを指定する文字列などのアドレスで読み込む仕組みです。手軽にコンテンツのデータの作成や配布をするのに役立ちます。

Addressableアセットシステムは、依存関係(Dependencies)の一覧を使って、様々な場所から非同期にデータを読み込むことができます。直接参照したり、これまでのAsset Bundleを使ったり、リソースフォルダーを使うこともできます。

以下の公式ドキュメントをざっくり読んで、Addressableアセットの設定、作成、スクリプトからの読み込みをしてみます。

docs.unity3d.com

目次

使う上での注意点

  • 対応するのは、Unity2018.2以降
  • Addressables System 0.5.3で動作確認
  • 2019/4/25の時点ではまだreview版なので、仕様変更や不具合が発生する場合があります。正規のプロジェクトで使うかどうかは慎重に
  • 一通りの設定を終えるまではエラーが発生する場合があります。とりあえずエラーが出ても、アセットを読み込むところまで進めてください

Addressableアセットの設定と作成

インストール

Addressableアセットパッケージは、Package Managerからインストールできます。Package ManagerからAddressables Systemをインストールします。

アセットをAddressableに設定する

2通りの方法があります。Package ManagerでAddressables Systemをインストールしたら、Addressableにしたいアセットを選択してInspectorAddressにチェックを入れるか、Addressablesウィンドウを表示して、そこにドラッグ&ドロップします。

Addressableウィンドウは、WindowメニューからAsset Management > Addressable Assetsを選択して開きます。AddressableにしたいアセットをProjectウィンドウからドラッグして、AddressablesウィンドウのAssetタブにドロップします。

設定したアセットのデフォルトアドレスはプロジェクトのAssetパスです。例えばAssets/images/myImage.pngのようになります。これはInspectorウィンドウや、Addressablesウィンドウでユニークな他の文字列に変更することができます。

Addressableアセットをはじめて設定した時は、プロジェクトフォルダーにAssets/AddressableAssetsDataフォルダーが作成されて、必要なデータが作成されるので、バージョン管理システムを利用している場合は管理に加えてください。

読み込みやAddressからのゲームオブジェクト生成

実行中に読み込みやアセットから生成ができます。Loadingアセットでは、アセットバンドルのデータも含む読み込みに必要なすべてのアセットをメモリーに読み込みます。必要になった時にアセットを読み込んで使うことができます。Instantiating loads the Asset(アセットの読み込みと生成)の場合は読み込んだと同時にシーンにアセットが生成されます。

Addressableアセットにアクセスするスクリプトでは、冒頭で以下を追加しておきます。

using UnityEngine.AddressableAssets;

データの読み込み、および、読み込みとInstantiateは以下のメソッドで実行します。

LoadAsset

Addressables.LoadAsset<GameObject>("AssetAddress");

InstantiateAsset

Addressables.Instantiate<GameObject>("AssetAddress");

上記のいずれも非同期なので、読み込み完了時に処理する場合は以下のようにコールバックを設定します。特に、LoadAssetの場合は、読み込み後にデータを利用することになるので、以下の仕組みが必要になるはずです。以下、testdata.csvというテキストアセットを読み込んで、完了したらログ表示する例です。テキストアセットのエンコードUTF8Nです。

using UnityEngine;
using UnityEngine.AddressableAssets;

public class AddressableLoader : MonoBehaviour {

    void Start () {
        Addressables.LoadAsset<TextAsset>("testdata.csv").Completed += onLoadDone;
    }

    void onLoadDone(UnityEngine.ResourceManagement.IAsyncOperation<TextAsset> obj)
    {
        Debug.Log(obj);
    }
}

以上で、Addressableアセットを作成して、スクリプトから利用することができます。

これ以降、以下の項目を必要に応じて進めるとよいでしょう。

参考URL

メッシュを変形するDeformを使ってみる

なんか凄いのがMITライセンスで公開されたのを知って、取り急ぎ使い方をば。メッシュを変形させるライブラリです。以下のようなことができます。

f:id:am1tanaka:20190406160924g:plain
Twist Deform

github.com

沢山種類があるので、詳しくは上記のGitHubリポジトリーで動画が見れます。

目次

要件

Unity2018.3以降が必要です。

インストール方法

依存関係を解決する必要があるので、リポジトリーのファイルをそのままプロジェクトに突っ込むだけでは動きません。以下のインストール手順に従います。

Deform/Installation.md at master · keenanwoodall/Deform · GitHub

  • Unityを閉じておきます
  • 組み込みたい2018.3以降のUnityのプロジェクトのPackagesフォルダーをエクスプローラーなどで開きます

f:id:am1tanaka:20190406161050p:plain
Packagesフォルダー

  • manifest.jsonを何らかのエディターで開きます

f:id:am1tanaka:20190406161103p:plain
manifest.jsonを開く

  • すでに書かれている部分はそのままにして、 "dependencies": {の下に以下の行を追加します
// :
"com.beans.deform": "https://github.com/keenanwoodall/Deform.git",

f:id:am1tanaka:20190406161121p:plain
dependenciesを追加

  • 上書き保存してエディターを閉じます

以上できたら、Unityを起動してプロジェクトを開きます。そうすると、自動的に依存関係も含めてDeformがインストールされます。

原文には、ZIPをダウンロードして組み込む手順も掲載されています。

変形させる

以下を参考に、Twistでキューブ(Cube)をねじってみます。

Deform/GettingStarted.md at master · keenanwoodall/Deform · GitHub

ねじるためのCubeを作成する

変形のための頂点が必要なので、通常のGame Objectから作成するCubeだとうまくいきません。Deformがそれ用のCubeを作ってくれますのでそれを使います

  • ToolメニューからDeform > Creatorを選択します

f:id:am1tanaka:20190406161220p:plain
Creatorウィンドウを開く

  • Creatorウィンドウが開きますので、Create Deformableボタンをクリックします

f:id:am1tanaka:20190406161255p:plain
Deformableの作成

Wireframeを表示してみると、以下のように1辺が16分割された立方体であることが確認できます。

f:id:am1tanaka:20190406161315p:plain
作成されたCubeの確認

ちなみに、普通に作ったCubeは以下の通りなので、辺の途中がねじれないのでうまくDeformできません。

f:id:am1tanaka:20190406161327p:plain
標準のCube。これだと複雑な変形ができない

  • Hierarchyウィンドウで、作成したDeformable Objectをクリックして選択したら、CreatorウィンドウのTwistボタンをクリックします

f:id:am1tanaka:20190406161421p:plain
Twistを追加

以上で、TwistDeformerが設定されました。

ネジってみる

  • 作成したCubeの子供に追加されたTwistオブジェクトを選択します
  • Cubeの上下にオレンジ色の円柱状のハンドルが表示されるので、それをドラッグするとCubeがねじれます!

f:id:am1tanaka:20190406161500p:plain
ねじる!

  • Twistの座標や回転、大きさを変化させると、ねじれ方が変わります

f:id:am1tanaka:20190406160924g:plain
Twist Deform

Cube以外のメッシュを変形させたい場合

既存のモデルに適用したい場合は、そのモデルを選択して、CreatorウィンドウのCreate DeformableボタンをクリックすればOKです。あとの作業は同じです。

スクリプトから使う

利用したいコードの先頭に以下を追加します。

using Deform;

Twistを制御したい場合は、TwistDeformerインスタンスInspectorGetComponent<TwistDeformer>()で取得して、StartAngleEndAngleプロパティーに値を設定すれば動きます。

using UnityEngine;
using Deform;

public class TwistTest : MonoBehaviour
{
    TwistDeformer twistDeformer;
    float now = 0;

    private void Awake()
    {
        twistDeformer = GetComponent<TwistDeformer>();
    }

    void Update()
    {
        now = Mathf.Repeat(now + Time.deltaTime * 360f, 360f);
        twistDeformer.StartAngle = now;
        twistDeformer.EndAngle = -now;
    }
}

上記のようなスクリプトを作成してTwistオブジェクトにアタッチすると自動的にねじれます。

詳細は...

英語ですが、以下の動画で操作が分かります。控えめに言って凄いです。

www.youtube.com

関連URL

github.com

Looking Glassの表示がずれる

Looking Glass(ルキグラス)を表示したら、以下のように微妙にずれるという時は、メインモニターの方の設定が原因かも知れません。

f:id:am1tanaka:20190405224303j:plain
LookingGlassの表示がずれる

Someluさんの以下のツイートをなんとなく覚えていて、LookingGlassの方だけではなく、メインモニターの倍率も100%じゃないといけないということで、無事直りました!

UnityでMissingのオブジェクトを検索する

以下書いたけど、Unity2018.3だとワーニングをダブルクリックすればどのオブジェクトか示してくれますね。ちょっと前に駄目だった気がしたのですが、気のせいだったかも・・・。一応なんかあった時の対処法ということで。


無料版のAssetを有料版に差し替える時やバージョンアップ時に、構造が変わってスクリプトMissingになってしまうことがあります。しかし、Missingなのは分かるけど、どれ・・・という時の解決策をUnity Communityで見つけました。

wiki.unity3d.com

実装手順

  • Editorフォルダーをプロジェクト内のどこかに作成します(すでにあればそれを利用すればよい)
  • Editorフォルダー内にFindMissingScriptsRecursivelyという名前でC#スクリプトを作成します

f:id:am1tanaka:20190401213247p:plain
スクリプト作成

f:id:am1tanaka:20190401213504p:plain
スクリプトをコピー

  • FindMissingScriptsRecursively.csに貼り付けます

f:id:am1tanaka:20190401213557p:plain
貼り付け

以上で設定完了です。

Missingを探す

  • 探したいシーンを開きます
  • Windowメニューから、FindMissingScriptsRecursivelyを選択して、検索ボタンのあるウィンドウを開きます

f:id:am1tanaka:20190401213818p:plain
検索メニュー表示

  • Hierarchyウィンドウでオブジェクトを全て選択します

f:id:am1tanaka:20190401213716p:plain
オブジェクトを選択

  • Find Missing Scripts in selected GameObjectsボタンをクリックします

f:id:am1tanaka:20190401214102p:plain
検索実行

検索結果は、Consoleウィンドウに表示されます。

f:id:am1tanaka:20190401214144p:plain
コンソール画面

  • ????? has an empty script attached in position: ?という行があったら、Missingを持ったゲームオブジェクトがあったということです。先頭の?????の部分にオブジェクトの名前が表示されます
  • 上記のコンソールの行をクリックすると、Hierarchyウィンドウで該当するゲームオブジェクトが黄色で示されます

f:id:am1tanaka:20190401214459p:plain
Missingのあるゲームオブジェクト

以上です。

Missingのあるプレハブを見つけるには

Hierarchyウィンドウで選択したのと同様に、Projectウィンドウで調べたいオブジェクトを選択して、検索ボタンを押せばプレハブからもMissingを見つけてくれます。

参考URL

Unity1週間ゲームジャム「つながる」参加ブログ

つながるというお題で、スタートからゴールに線を繋げる 跳ね玉 というゲームを作りました!unityroomにログインして遊んで評価を送信していただければ喜びます!

跳ね玉

跳ね玉 | フリーゲーム投稿サイト unityroom

企画から制作までの流れをメモがてら。

目次

企画ができるまで

最近では恒例になりました、秋葉原にあるコワーキングスペースWeeybleさんにおいてニムさん主催で開催されましたUnity1週間ゲームジャム準備会に参加するところからスタート。

今回も勢いをつけるためにライトニングトーク(LT)枠での参加。いつもはネットランキングやツイート方法、フレームワークの参考など技術的なことをお話していたのですが、ゲームデザインについて自分が調べたことを発表しました。3/9に資料作成した模様。

資料は以下で公開してます。

docs.google.com

準備会ではLT後、Looking Glassを持って行っていたのでどっちかというとそっちで遊んでいたような...。3/10の作業は以下のような感じでした。

  • Trelloで作業用ボード作成
  • Unityのプロジェクト作成、基本設定、ビルド、unityroomへの仮登録

一人企画会議

準備会から帰ったあとは一人企画会議です。Trelloのカードに以下のようにざっくりとテーマを書き出しました。

  • タイミング一発的なシンプルなルール
  • プリミティブな形をかっこよく見せる -> PPSを利用
  • 高さなどの眩暈要素 -> CameraPlayの波紋
  • ネットランキングとツイートでSNS要素を入れる

以下のような案が最初の方向性でした。

  • タイミングワンキー
  • 左右を選ぶ
  • ロープ
  • 棒高跳び的な
  • スポットライトに当たり続ける or 逃げる

ただ、この段階で具体的なイメージはまとまらず。次に、最近気になっていたPhysics.Simulate()による物理の先読みネタを考え始めました。テラシュールブログさんの以下のブログのやつです。

tsubakit1.hateblo.jp

そして日曜日の21時半ごろに以下をツイート。

この時に考えていたのが、跳ね玉のほぼそのままの企画です。

ついでにこんなことつぶやいていた。これは深入りしなくてよかった^^;

  • カジュアルゲームなら高さによるめまい要素を入れたり演出に時間をかけられる
  • パズルならPhysics.Simulate()を使えて、めまい要素は減るけどCameraPlayで揺らすのはできる

という2択。LT通りにやるならカジュアルゲーだけど、パズルの方がイメージがしっかりと固まっていて「つながる」のテーマも満たしている。Physics.Simulate()と念願のCameraPlayも使えそう。ということで、やりたいことができるパズル企画を選びました。

この後の開発の流れは後半にて。

学生さん作品

Sāya君. Bird Tree Life

前回、デビュー作のカードジャンゴーでいいねを沢山もらった狼幼女改めSāya君が今回も参加。

unityroom.com

画面が奇麗でずんずん成長してます。前作もそうですが、文字がなくてもストーリー性が出せるのが強い。サウンドや雰囲気でランクインしたり、おすすめや週間ランキングにも登場。お見事!!

f:id:am1tanaka:20190326185313p:plain
週間ランキング

f:id:am1tanaka:20190326185336p:plain
音楽

Alesta_WSさん. MicroChip

こちらも連続参加。ロシアからの留学生のAlesta_WSさんの作品。

unityroom.com

歯ごたえのあるパズルゲームです。説明が少ないのと音がなくて評価を落としてしまったのが残念。面白いゲームですが、元ネタはあるのだろうか。学校がはじまったら聞いてみよう。休みの期間で自力で完成させて公開しているのでえらいです!!

ゲームジャムを終えて

全体的によいコメントや評価をいただけて、頑張った甲斐がありました。評価ランキングでは、3/25までの最高順位で8位に入ることができました!!

f:id:am1tanaka:20190325223552p:plain
評価総合ランキング

僅差なのでいつまで持ちこたえられるか分からないので記念のスクショ。

今回から変更になった評価形式やランキングによって、多くの作品が並びますし、項目ごとに評価が分かって次回作への反省材料になります。unityroomがさらに進化!naichiさん、いつも本当にありがとうございます。

次回に向けて

参加された皆さんの作品を拝見するのもとても得るものが多いです。今回は特に以下のようなこと。

  • ゲームがシンプルでも強いものは強い
  • 画面は明るめに(地が黒くてもエフェクトで半分以上明るくなるとか、画面全体が暗くならないように)
  • キャラクター性、ストーリー性、作家性のいずれかがあるものは強い
  • ドット絵強い(これは自分には無理なのでプリミティブ方面を追う)

今回は時間を沢山使えましたが次回は時期的に難しいはず。上記を踏まえてコンパクトなものに挑戦したいと考えています。が、企画は水物なのでどうなるか。画面の明るさ問題は「絵作り」で結果が出たのでちょっと悩みどころなのですが、ビュー数を伸ばす手段として試す価値はありそうだと考えています。

naichiさん、素敵なサイトと1週間ゲームジャムをありがとうございます。今回も多くの収穫がありました。Weeybleさんで準備会や追い込み会でご一緒した皆様、また是非ご一緒できればうれしいです!今回も楽しい実況プレイをしてくださったぱふもどきさん、お疲れさまでした。沢山のゲーム、特にオンラインゲームを楽しめました。1週間ゲームに参加された皆様、遊んでくださって評価してくださった皆様、お疲れさまでした&ありがとうございました!

引き続き、開発ログです。

開発ログ

初日:3/11(月)

テーマが発表されてすぐにモックアップの作成を開始しました。フォントはデザインの要の一つなので早めに選びます。今回の1週間ゲームジャムでは、フォントワークスさんが2か月間の無償ライセンスをご提供くださっていたので使おうとしたのですが、サイトを探してもやり方が見つかりません...。インストールフォルダってどこだ。どうやって探すんだ。ライセンスの内容もどうにも要領を得ず、知りたいことが分かりません。これはキビしい...。ということで、仕様ライセンスの解約とアンインストール。

そして、いつも通りフリーフォント探しの旅に出ました。いつもお世話になっているColissさんが2019年度版のフリーフォント総まとめを出して下さってました!!

この中から、今回のゲームにぴったりのかっこいいフォントが見つかりました。ありがたやありがたや。

ということで、解像度などを確定して、タイトル画面を作って0日目終わり。

作業再開は昼過ぎから、ゲーム画面のモックアップ作りを開始。PostProcessの設定をしたり、プレイヤーの玉やバウンドさせるやつの形を作ったり、アニメーションを作ったりで終了。

作業をしつつステージの構成についても検討。ガンズターンアプリ研究所さんの作品「WHEEL OF FORTUNE」のエンディング演出が素晴らしかったので、ステージ全体で何かを表現できないか考えました。

unityroom.com

ステージ全体が鳥のおもちゃの中で、電線を繋いでいってエンディングで羽ばたかせるのはどうだ、とか考えてました。アセットも探していたのですがよさそうなのが見つからず、方針を転換して今回のアイディアにしました。

f:id:am1tanaka:20190325002227j:plain
つなぐ

6ステージ分の基本的な形がまとめてできたので、ステージ作りは楽にできました。

2日目:3/12(火)

この日も昼過ぎから。

Sleek Renderは速度が速いのだけど、滑らかに形に合わせたBloomが出ないのですよね。ということで、公式PPSに変更することにしました。その後、玉の軌道予測と移動に取り掛かりました。

こんな感じで方針転換。ざっくりとしたものはこの日にできましたが、まだまだ不具合を抱えている状態でした。

また、バウンドさせる丸いのの地味さを解決するために、Pro Builderでエッジを作ってそこを発光させるようにしたりして画面はおおよそ整いました。

3日目:3/13(水)

評価順位の発表までずっとこう思ってました。が、評価ランキングでは絵作りが一番順位が高く、自己判断ってあてにならないなと思った次第^^; ご意見聞くの大事。

以前から使いたかったCamera Play - Asset Storeの演出をようやく入れることができました!いくつもコメントいただきましたし、間違いなく絵作りの評価が高かった理由の一つだと思います。満足^^

4日目:3/14(木)

ゲームの大枠をおおよそ実装。

ここに書いてある「Physics.SimulateがFixedUpdateを呼び出してしまう」というのは勘違いで、これが最終日まで問題がもつれる原因になりました。椿さんのブログに「FixedUpdateは呼ばれない」とちゃんと書いてあったのを誤読していたという...。国語力大事。

5日目:3/15(金)

5日目にして問題発生!

1つ順番が狂えばシミュレーションと実行結果が変わってしまうので苦戦しました。FixedUpdate()が不規則に呼ばれると勘違いしていたことで、余計にこんがらがってました。19時過ぎにようやくひと段落。

クリアのフローを作ったりと残りの作業をばばばばばっと。

6日目:3/16(土)

あと2日しかないし...。クリアが入ったので、残りのステージ作りに取り掛かりました。また、Stage4以降に出る紫のやつも作成。朝から作業を開始して、Stage6まで完了して以下をツイート。

ここからは怒涛の作業。バウンドするやつを壊せるようにしたり、仮エンディング、チュートリアル、ランキングをどどどっと実装しました。

チュートリアルの制作は2時間ぐらい。メッセージと説明用のオブジェクトを、ページごとのゲームオブジェクトの子供にして作っておいて、それをSetActive()で切り替えるというシンプルな方法で実装しました。

画面の変化は殆どないので画像無し。安心できない感じで最終日を迎えました。

最終日:3/17(日)

朝から仕上げの作業。やまださんのimgur版の画像ツイートと仮のエンディングを実装してお昼。Weeybleさんの追い込み会に出発!

weeyble-game.connpass.com

Weeybleさんでは、ラスボスである玉がバウンドさせるやつを抜けてしまうバグ退治。ここにきてようやくPhysics.Simulate()の振る舞いをDebug.Log()で追って、問題を突き止めました。原因はシミュレート自体ではなく、とあるフラグの初期化のタイミングでした。

17時半に解決したのであとは楽勝だと思ってたのですが、ここからラスボスの第2形態が...。初期化でコケるという超初歩的なバグが発生。初期化の流れが今一つ良くなくて、これの解決に20時ギリギリまでかかってしまいました。バウンドさせると消えるのがうまくいかず、最終ステージの仕掛けを一部省いたりしましたが、なんとかアップロード!!

ぴったりなスクショも取れまして。

これにて、公開完了となりました。めでたしめでたし。

その後のバージョンアップ

バウンドさせるやつが消える時の処理や、Stage2のバランス、この企画の冒頭で考えていたエンディングの演出の実装などを終えて、3/19の夜に最終版が仕上がりました!

以上、今回の「跳ね玉」の開発の流れでした。

参考URL

Leap Motionでマウス的な操作をする LeapMotionPointer

Leap Motionを使って、マウスと同じようにスクリーン上の場所を指定する操作を実装しました。以下は、開発中のVoxelorer Birdに組み込んだ作例です。

以下のリポジトリーで公開しています。

github.com

使い方を紹介します。

f:id:am1tanaka:20190217005740g:plain
動作例

目次

前提

動作確認をしたのは以下の環境です。

  • Windows10
  • Unity2017.4.20と2018.3.2
  • Leap Motion Orion 4.0.0
  • Unity Core Assets 4.4.0

WebGLについて

Unity2017.4ではビルドできませんでした。Unity2018.1にして、Unsafe Codeを許可するとビルドはできましたが、実行時にエラーが出て動きませんでした。WebGLでの動かし方は分かっていません。

環境設定

Leap MotionをUnityで使えるようにする手順はこちらの公式ページで説明されています。すでに環境を構築済みでしたら、飛ばして構いません。

  • 公式ページを開きます
  • DOWNLOAD ORION BETAのボタンをクリックして、Leap Motion Orionの最新版をダウンロードしてインストールします
  • 公式のこちらを開きます
  • DOWNLOAD UNITY CORE ASSETS X.X.Xのボタンをクリックして、Unity Core Assetsをダウンロードします

以上で下準備完了です。

デモを動かす

デモの実行方法です。

Leap Motion用のアセットがないので、以下のようなエラーが出ます。次の手順で消えますので作業を進めてください。

f:id:am1tanaka:20190217010038p:plain
エラーが出ても構わず進めて良い

  • 上の手順でダウンロードしたUnity Core Assetsをプロジェクトにインポートします

f:id:am1tanaka:20190217010102p:plain
インポート

これでエラーが消えます。

  • Projectウィンドウから、LeapMotionPointer > Demoフォルダーを開いて、Demoシーンをダブルクリックして開きます

以上でデモ用のシーンが開きます。Playするとデモが動きます。

f:id:am1tanaka:20190217010115p:plain
デモの画面

操作方法

手を水平に開いておくのが基本姿勢です。以下のように、Leap Motionの上に手を開いて、水平にかざします。

f:id:am1tanaka:20190216211447j:plain
基本姿勢

手のひらを水平にしたまま、上下左右に手を動かして画面にカーソルが表示される場所を探してください。Leap Motionから少し奥で、30cmぐらい上の位置ぐらいで表示されると思います。

左手でも操作できます。

左右移動

手を左右に動かします。

f:id:am1tanaka:20190217010155g:plain
左右操作

上下移動

手を上下、あるいは前後に動かします。

f:id:am1tanaka:20190217010233g:plain
上下操作

上下、前後のどちらも、カーソルは上下移動と見なします。

クリック

クリックは、人差し指を下げます。

f:id:am1tanaka:20190216211523j:plain
クリック

人差し指薬指の高さの違いでクリック判定をしています。中指は見ていないので、曲げても曲げなくてもどちらでも楽な方で。

手のひらが人差し指側に傾いていると誤クリックが発生しやすくなり、操作が安定しません。

f:id:am1tanaka:20190216211546j:plain
誤クリックが増える

小指側に傾けておく方が安定した操作ができます。

f:id:am1tanaka:20190216211538j:plain
小指側に傾けると安定する

丸いのをドラッグしたり、左上のボタンをクリックしたりしてみてください。

f:id:am1tanaka:20190217005740g:plain
動作例

手のひらを小指側に傾けておけば、適当に操作してもそれっぽく動きます。

手の認識がうまくいっていないと動作が不安定になります(結構頻繁に起きます)。反対側に動いたり、クリックがおかしかったり、震えたりする場合は、手をLeap Motionの視野から一旦外してから、手を認識しなおしてください。

プロジェクトに組み込む

組み込みたいプロジェクトをUnity2017.4以降で開いてから、以下の作業をします。

必要なアセットをインポート

  • ダウンロードしてあるUnity Core Assets(Leap_Motion_Core_Assets_ x.x.x.unitypackage)をインポートします
  • LeapMotionPointerリポジトリーのReleasesを開いて、最新版のLeapMotionPointerX.X.X.unitypackageをダウンロードして、プロジェクトにインポートします
  • LeapMotionを使いたいシーンを開きます
  • Projectウィンドウで、LeapMotionPointer > Prefabsフォルダーを開きます
  • LeapMotionPointerプレハブをドラッグして、Hierarchyウィンドウにドロップします

これで準備完了です。ついでに、動作確認のためにデモ用のCanvasを配置しておくと楽です。

  • ProjectウィンドウのLeapMotionPointer > Demo > Prefabsフォルダーを開いて、DemoCanvasプレハブをHierarchyウィンドウにドロップします
  • EventSystemがシーンにない場合は、HierarchyウィンドウのCreateボタンをクリックして、UI > Event Systemを選択して追加します

f:id:am1tanaka:20190217010456p:plain
Hierarchyの様子

これでLeapMotionを使ってカーソルを操作できます。カーソルは、DemoCanavsの子供のCursorオブジェクトです。これの画像を差し替えればオリジナルのものに差し替えることができます。

f:id:am1tanaka:20190217010526p:plain
DemoCanvas

スクリプトで情報を得る

情報は、LeapMotionManagerExクラスのstaticプロパティーで得られます。

利用したいスクリプトの冒頭に、以下のusingを追加します。

// :
using AM1.LeapMotionPointer;

bool LeapMotionManagerEx.isEnable

Leap Motionで手を確認している時にtrueになります。

Vector3 LeapMotionManagerEx.screenPoint

Leap Motionが指している画面座標を返します。

// :
Debug.Log(LeapMotionManagerEx.screenPoint);

補足

デフォルトの設定では、Camera.mainのスクリーン座標を返します。Main Cameraタグが未設定だった場合など、Camera.mainが取得できない状態の時はscreenPointは無効な値を返します。

カメラを指定するには、シーンに配置したLeapMotionPointerオブジェクトのTarget Cameraプロパティーに目的のカメラを設定します。

f:id:am1tanaka:20190217010543p:plain
カメラを設定する場所

Vector3 LeapMotionManagerEx.viewportPosition

Leap Motionが指している場所をビューポート座標で返します。

bool LeapMotionManagerEx.isPressDown

クリックを開始した時にtrueになります。

// :
if (LeapMotionManagerEx.isPressDown) {
    Debug.Log("クリック!");
}

bool LeapMotionManagerEx.isPress

クリック状態の時、ずっとtrueになります。ドラッグを判定したい場合などに利用します。

// :
if (LeapMotionManagerEx.isPress) {
    Debug.Log("押し続けている");
}

bool LeapMotionManagerEx.isPressUp

クリックが解除された時にtrueになります。

// :
if (LeapMotionManagerEx.isPressUp) {
    Debug.Log("クリック終了");
}

UIのボタン

UIのボタンは、クリック時に自動的に押すようにしてあります。何もしなくても反応します。

パラメーター

LeapMotionPointerの調整用パラメーターは以下の通りです。

f:id:am1tanaka:20190217012026p:plain
LeapMotionPointerのインスペクター

  • Leap Provider
  • Model Pool
    • 手のモデルを表示したい時に利用します。本プロジェクトでは設定不要です
  • Target Camera
    • LeapMotionManagerEx.screenPointを計算する時に使うカメラを指定します。未設定の時は、Camera.mainの値を使います。Camera.mainnullの時は、LeapMotionManagerEx.screenPointの値が設定されません
  • Move Rate
    • 手の動きと、カーソルの動きを対応させる係数です。この値を大きくすると、手の動きに対して、カーソルの動きが速くなります
  • Visible Under
    • 手の低さの下限値です。この値を小さくすると、低い位置で手を認識するようになります。小さくしすぎると指の動きが認識できなくなるので、0.15程度が下限です
  • Click Threshold
    • クリックを判別する人差し指と薬指の高さの差です。この値を大きくすると、クリックの誤動作は減りますが、クリックの反応が鈍くなります
  • Bank Limit
    • 手首の傾きがこの値よりも大きくなったら、誤動作を避けるためにクリック判定を無視します。0は傾き無し。0.5が90度です
  • Viewport Click Limit
    • 画面端でクリックを無視する範囲です。特に不要な場合は0のままで構いません
  • Flat Rate
    • 手の震えを止めるための平均係数です。この値を小さくすると反応はよくなりますが、Leap Motionの誤差による震えが出やすくなります

特に調整する必要はないと思います。手を認識する場所を下げたい時に、Visible Underを設定するぐらいだと思います。

今後について

現在、UIのボタンは無理やりButtonコンポーネントを取得して、クリック時のイベントを実行するようにしています。レイヤーの指定などができず、他の要素のクリックもできないので、将来的にはEvent Systemに対応させることを考えています。

人差し指と薬指の高さ判定に手首の回転を考慮していませんが、試しに実装したら動作が不安定になったので削除した経緯があります。よい方法があればご教示いただければ幸いです。

プルリク歓迎です。

github.com

ライセンス

MITライセンス

参考URL

www.leapmotion.com