技術的なやつ

技術的なやつ

5.1 Unityで波形を表示する

というわけで、もう一つのブログに書いてあった通り、カラオケ採点機を作っていく。
春合宿での発表のためにも、こまめにノート(記事)を取っていくことにした。
記事内で扱う内容は赤文字、既に終わった内容は灰文字で表示する*1

  1. Unityを用いる
    1. C#について少し復習する
    2. Unityの2D描画について簡単に学ぶ
  2. Unityの音声制御
    1. MIDIを再生させる手段を見つける
    2. 音声のマイク入力手段を見つける
  3. 入力音声の解析
    1. UnityのFFTライブラリを触ってみる
    2. FFTされたデータから音程を確定させるアルゴリズムを考える
  4. MIDIの解析
    1. 第1トラックの楽譜を解析する
    2. MIDIの再生箇所を解析する手段を見つける
  5. 採点のための解析
    1. 全体の点数計算アルゴリズムを考える
    2. ビブラート判定アルゴリズムを考える
    3. しゃくり判定アルゴリズムを考える
    4. タイミング判定アルゴリズムを考える
    5. なめらかさ判定アルゴリズムを考える

Unity

たった一日しか触っていないので、かなり適当言ってる可能性があることをご了承ください。

Unityとは、最近流行っているゲーム製作エンジンである。公式サイトはここ
このエンジンの注目すべき特徴は以下の通り。

この中で、特にマルチプラットフォームであることが注目を浴びている。つまり、Unity上であるゲームを完成させれば、それをWindows用にもMac用にもLinux用にもAndroid用にもiOS用にもビルドできるということである。家庭用ゲーム用にもビルド出来るらしい。凄いですね。
使用するために、公式サイトから適当にファイルを落としてインストールしましょう。なんか登録が必要だった気がするのでメールアドレスを用意しましょう。有料版もありますが、無料版で十分だと思うので無料版をインストール。

以下、記事内容はWindows7上のUnity4.3.3f1を想定しています。

Unityでのゲーム製作

インストールできたら起動しましょう。
普通は3Dに飛びつきますが、今回は2Dで事足りるので2Dを選択してNewProjectをCreateしましょう。
f:id:ibako31:20140201231321j:plain
Projectフォルダを設定し、左下のやつを2Dに変えて、Createを押します。チェックボックスは特に何もつけなくて良いです。
f:id:ibako31:20140201231829j:plain
こんな感じの画面が出ると思います。なんか余計なウィンドウが出るかもしれないですが、消してください。
順番に説明しましょう。

Scene

左上のSceneっていう枠のこと。
Unityでは、Project(=ゲーム)はSceneの集まりとして扱う。つまり、爆幻をProjectとして例にすると、Sceneはタイトル画面・実際のゲーム画面、という感じになる。

Game

Sceneの下にあるGameという枠のこと。
実際のゲーム画面を表す。

Hierarchy

真ん中あたりのHierarchyという枠のこと。
現在のSceneに存在するGameObjectの一覧がある。GameObjectはUnityでのゲーム構成要素の末端要素のようなもの。爆幻でいうと、プレイヤーキャラであったりタイトルロゴであったりする。

Projects

Hierarchyの横にあるProjectsという枠のこと。

Favorites

私も何か知らない┐(└┌)┘

Assets

全Scene共通で使えるパーツのこと。画像素材であったり音楽素材であったり共通ソースであったりを突っ込むらしい。

Inspector

一番右にあるInspectorという枠のこと。
GameObjectをクリックすると、ここにその詳細(Components)が出てくる。

初めはMain CameraというGameObjectが存在します。クリックしてみると、以下の様な画面が出ると思います。
f:id:ibako31:20140201232948j:plain
この画面で、InspectorにはMain CameraのComponentsが表示されています。Transform・Camera・GUILayer・Flare Layer・Audio Listenerですね。それぞれに細かい要素があります。たとえば、Transformを見ると、Position・Rotation・Scaleですね。それぞれ、メインカメラの座標・回転・拡縮を表します。これらは、この画面で数値を変更することも可能ですし、C#/JavaScript/Booで書いたスクリプトによって制御することも可能です。今回はC#を使います。

まとめると、こんな感じです。

  • Project(ゲームそのもの)
    • Scene(ゲームの一場面)
      • GameObject(シーンの構成要素。キャラとかロゴとか)
        • Component(オブジェクトの構成要素。座標とか)

Hello World!

上のメニューからGameObject -> Create Empty。
f:id:ibako31:20140201233831j:plain
こんな感じで、空のGameObjectが出来ます。F2か右クリック -> RenameかInspectorから「Hello」にリネームしておきましょう。
Inspectorから「Add Component」を選びます。New Script -> LanguageをC SharpにしてCreate and add。
ここから、別エディタを使ってC#のコードを書いていきます。なんかよく分からんエディタがデフォルトになってるので、適当に使い慣れたエディタに設定変更しましょう。
上のメニューから、Edit -> Preferences -> External Tools -> External Script Editorを好きなものに変更しましょう。私はMicrosoft Visual Studioにしました。
エディタの設定が終わったら、AssetsにあるC#のコードをダブルクリック(または、クリックからInspectorのopen)。VS立ち上がりOSEEEEEE!!!!
f:id:ibako31:20140201234551j:plain
…とりあえず、こんな感じのコードが出るはずです。

using UnityEngine;
using System.Collections;

public class NewBehaviourScript : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

詳しいことは置いといて、メソッドの説明。と言っても、コード内にちゃんと英語で書いてあるのですが…。

void Start()

ゲームの起動時に一度だけ実行される内容。initみたいなもんですね。

void Update()

フレームごとに実行される内容。

というわけで、HelloWorldを書きます。

void Start () {
        Debug.Log("Hello World!");
}

書いたら保存して、Unityに戻ります。
f:id:ibako31:20140201235244j:plain
Inspectorの中身も更新されればOKです。上のメニューから、Window -> Consoleでコンソールウィンドウを出します。
f:id:ibako31:20140201235416j:plain
Clearでコンソールウィンドウの中身をクリアできます。しておきましょう。
Hierarchyの上の方にある再生/一時停止/1フレームごとに再生を表すボタンのうち、再生を押してみましょう。実行にはやや時間がかかります。
f:id:ibako31:20140201235751j:plain
こんな感じになればOK。

正弦波を描画する

まず、カメラを引いておきます。
HierarchyのMainCameraをクリックし、Sceneの上辺りにある十字のマーク(左から2番め)をクリック。Sceneの上でマウスホイールを下に回すと、カメラが引いていきます。
初め、グリッドは10刻みで表示されていますが、引きまくると100刻みになります。とりあえずx座標が-200~200まで入るようにしましょう。その後、真ん中の白い長方形の辺上にある点をドラッグし、カメラ範囲をx座標が-200~200まで入るようにします。
f:id:ibako31:20140202000440j:plain
GameObject -> Create Emptyで新しいGameObjectを作ります。名前はsinにでもしておきましょう。
コンポーネントとして、Effects -> LineRendererを追加します。
LineRendererは、指定した複数座標を直線で繋ぎ、描画します。今回だと正弦波の描画を担当します。
作ったコンポーネントのParametersを開き、Start ColorとEnd Colorに適当な色を設定します。
また、MaterialsのElement0をSprites Defaultにしておきましょう。横のラジオボタンみたいなのを押せばOK。
f:id:ibako31:20140202002547j:plain
こんな感じにしましょう。

コンポーネントとして、再びC#スクリプトを追加します。スクリプト名はsinにでもしておきましょう。
以下のようにコードを書いてください。

using UnityEngine;
using System.Collections;

public class sin : MonoBehaviour {
	public LineRenderer lr;
	private int theta;
	private int count;

	// Use this for initialization
	void Start () {
                theta = 0;
                count = 0;
                lr.SetVertexCount(count);
	}
	
	// Update is called once per frame
	void Update () {
                if(count > 400) count = 0;
                count++;
                lr.SetVertexCount(count);
                lr.SetPosition(count - 1, new Vector3(-200 + count, 80 * Mathf.Sin(theta * Mathf.PI / 180), 0));
                theta++;
	}
}

説明が必要そうなものだけ、順番に説明しましょう。

public LineRenderer lr;

publicにするとソース中で操るコンポーネントを指定することが出来ます。
このコードを保存した後、InspectorのSinを見てください。
f:id:ibako31:20140202003252j:plain
こんな感じで、lrにコンポーネントを指定することが出来ます。
この上に、先ほど作ったLineRendererのコンポーネントをドラッグしてみましょう。すると、それが割り当てられるはずです。
privateだと、この項目は出てきません。

private int theta;

描く正弦波のラジアンを表します。

private int count;

実行からの時間を表します。ただし、400フレーム周期です。

lr.SetVertexCount(int n);

LineRendererの頂点数を指定します。

lr.SetPosition(int index, Vector3 pos)

LineRendererの第index頂点の座標を設定します。

さて、再生してみましょう。以下の様な正弦波がループしていれば成功です。
f:id:ibako31:20140202003910j:plain

*1:C#の復習についてはパスします(時間ないので)