Music engineadx
- 19. Tips1: Timing & Section
class Timing
• int bar; //何小節目の
• int beat; //何拍目の
• int unit; //16分音符何個目
Note: (0,0,0)からスタート。4拍子で16分音符で4小節の曲の最後は (3,3,3) になる。
class Music.Section
• int mtBeat_=4; //何mtで1拍とするか
• int mtBar_=16; //何mtで1小節とするか
• int Tempo_=120; //テンポ(=拍数/1分)
Note: 例えば7拍子を使いたい場合は、mtBeat=4ならmtBar=14にすれば良い。
- 25. Tips2: Just & Now
Music.Just : 拍がちょうどに来てから切り替わる
Music.Now : 「最も近い拍」を示すように(拍と拍の間で)切り替わる
Note: 何か「この拍になる直前に処理しておきたい!」という時とかにIsNowChanged系を使うと便利。
- 36. Unity版との違い
(ADXの機能で)ブロック再生が Music.SettNextBlock( blockName or index ) で使える
• 曲をブロックという単位で分けて、ブロック間をサンプルレベルで音楽に同期させて遷移できる。
(ADXの機能で)Aisacが Music.SetAisac( index, value ) を呼び出すことで操作可能
• トラックごとの様々なパラメータを1つの値で同時に変化させることができる。
ブロック名を指定して途中から再生開始 Music.Play( MusicName, firstBlockName ) が可能
セクションという概念が無い(ブロックが変化するだけ)。
タイミングはすべてブロック中で何小節目か、を指す
• 例えば、introブロックの最初も次のブロックの最初も、Music.CurrentBlockが違うだけで
タイミングはどちらも(0,0,0)になる。
Seek関数が使えない(ブロック再生を使おう)。
Notes de l'éditeur
- さて、いよいよ僕が新しい音楽ゲームを生み出し続けている力の源と言えるこのMusicEngineについて、紹介させていただきます。
Geekdrumsともうします、よろしくお願いします。
まぁ、主にプログラマ向けの内容になりますが、こういったゲームを作る上での工夫とかも紹介していきますので、参考にしていただければと思います。
- で、解説に入る前にまずは、このエンジンで一体どんなことができるか、採用事例を紹介していきたいと思います。
このエンジン自体は古くはXNAの頃から開発していたものなんですが、現在はUnityに移植して長年使っているという感じで、
今から紹介するのはすべてUnityとこのエンジンを使って開発しています。
- まずはオクス。クオーターは仮タイトルでまだ正式タイトルが未定なんですが、鋭意開発中です。
これはCRIさんのADX2LEも組み込んで使わせて頂いています。
実はこのエンジン、Unity版とADX版あるんですが、前は1つのコードにしていたんですが整理する過程でやっぱり2つに分けたので、ADX版は近日公開予定です。
中身はほとんど同じ機能ですが、それにプラスしてADXの機能もアクセスしやすいように、という風になっています。
- そして本日解説する予定のMusicPong。
こちらはプロジェクトファイルごと全部MusicEngineのサンプルの中に入っていますので、どなたでもご覧いただけます。
ちなみに、使っている素材は音楽1つと効果音1つのみです。なんかこういうミニマルなのが最近得意になってきました。
- さらにSpace to go、この作品はLudumDareというオンラインゲームジャムにて2日間で1人で作成しました。
そしてありがたいことにAudio部門で1位を獲得できたわけですが、まぁこのゲームジャムは非常にレベルが高くてですね、
ほとんどの参加者が個人戦で1人で作ってて、どれも信じられないくらい出来がいい。このゲームも総合だと26位とかです。
一体どうやってそんなクオリティを出すにはどうするかというと、
- やっぱりそれには、速さが命です。
もちろん、スタートダッシュを決めるにはまずどんなゲームが作りたいかというネタは常に考えておく必要がありますが、
とにかくさっさと作らないと、脳内で動いている神ゲーが消えてしまわないうちに作るスピードが必要になってくるんですね。
まぁオクスみたいにめっちゃ長く作ってるのも自分はよくあるので何言ってんだってかんじですが、
それでも何か思いついた時に、いかに素早く実装できるか、という環境を作っておくことが非常に大切です。
なので
- 本題ですが、ライブラリを知って、使って、まぁ一番いいのは自分で作って、
自分のスタイルというものを作っていきましょうということです。
ゲームエンジンもそうですが、ライブラリを使うということはその哲学までも踏襲するという事になります。
なので、このMusicnEngineの使い方と一緒に、自分の音楽ゲームへの考え方も少しお伝えできればなと思います。
- さてそれでは中身なんですが、非常にシンプルで、ソースコード1つになっています。クラスはMusicとTimingの2つなんですがまとめちゃいました。
これを入れるだけでもう使えます。他の準備は一切いりません。
じゃあこれを使うと何ができるのか?はっきりいって、技術的にそんなに凄いことはできません。やればできるけど、
例えば、今何小節目の何拍目のどこなのか?まぁ計算すれば誰でもはじき出せます。でもこれが、テンポを指定するだけで簡単に取得できる。
同じように、そういった情報からアニメーションに必要な情報を簡単に取り出すことができる。
ゲームの進行の判定に使って音楽に合わせて動かすことも簡単。そんな感じです。
もし違うことがやりたければ、
例えば波形の情報をうまく使ってかっこよく動かしたい!という人はvjkitとか、あとはUnity標準でついてるGetSpectrumDataとか使えばいいと思います。
または、ゲームに合わせて音楽を変える、すなわちゲームの側は音楽の事を気にしないで、音楽の方が合わせて欲しい、のであればADX2LEなんかがいいと思います。
もちろんこれらは併用可能ですが、そうじゃなくて、
- 音楽を軸にして、音楽に合わせてゲームを作る
なら
めっちゃ速く作れる
というのがこのライブラリの最大の特徴です。
まぁもちろん、全部を音楽に合わせる必要はないので、クオンタイズだけ使うとか、簡単な部分だけ使うことはできますし、
そういう工夫がぱぱっとできる、というのがウリです。
- では早速DLしてみましょう。
ExamplesにはMusicPongが入ってますが、自分でやる分にはコード1つでOKです。
- はい、それで、使うにあたっていくつか前提条件というか、前提知識というか。
まず1つ目、音楽は自分で用意しましょう、またはテンポや拍子は自分で調べましょう。市販の曲とかどっかから引っ張ってきた曲に勝手に合わせてくれるわけではありません。
自動検出なんて夢の技術が手近になれば話は違うかもしれませんが、現状は自分で作るなり調べるなりして、それを設定してください。
そして2つ目、音楽は常に一つだけ流れている、という前提です。まぁ言われてみればアタリマエではあるんですが、この前提を立てておくことで、
基本的にメンバーにはすべてMusic.なんとか、というStaticメンバでアクセスできるようにしてあります。速度最重視。クロスフェードなんて甘えです。
音楽が混ざるなんてことはぶれている証拠です。とも言ってられないのでそのうち実装するかもしれませんが。
そして3つ目、取得できる音楽情報はすべて16分音符が基準になっています。といっても、デフォルトがこれってだけで、
いつでも、曲中でも8分音符とか3連付とか6連付に変更できます。これをMusicalTimeの略でmtと呼んでいるんですが、
時間とかisJustChangedのフラグとか、このmtを基準に切り替わっています。
- それでは、MusicPongの作り方を見て行きましょう。
サンプルゲームということで、できるだけ簡単に作れるものをー、と思ったんですが、ちょっとライブコーディングではムリな感じになってしまいました。
- まずは企画を考えます。クオンタイズが使えてかつ進行を音楽に同期できて……とか、見せたいがために色々制約はあったんですが、
いろんなシンプルゲームを音楽に同期していくなかで、マインスイーパーとかブロック崩しはやったけど、まだPongやってなかったなってことで、
Pongを題材にしてみました。
- ということで、Pongを作ります。まぁプログラマなら一瞬ですね。ぽんっとできますね。
画像素材も1つも使っていません。UnityのPlaneを引き伸ばしただけですね。
- さてそして、今回のゲーム性も考慮して音楽を作ります。さくっと、と言いながら3日位悩んでました。
やっぱり、完全に音楽を主軸でゲームを作る場合、音楽がレベルデザインとか開始演出とかクリア演出すべてを包含していなければいけないので、
それを考えながら音楽を作るというのが、やっぱり何度やっても難しいです。
ちなみにちょっと曲のプロジェクトファイルも見てみましょうか。
まぁ開幕演出はこの棒が伸びてくるのやりたかったので決まってたんですが、
レベルデザインがですね……最初は徐々に驚かせながらパターンを増やしていく感じで、途中弾を速くしたいとも思っていたんで、
そこは一旦弾幕薄めにして、最後に変拍子を入れたいとも思ってたんで、あとは勢いですね。ちなみに、クリア演出の後にはゲームオーバーも一緒に入っています。
ゲームオーバーしたときはここに飛ばしているだけなんですね。
- さぁそして、曲ができてしまえばこっちのもの、あと5ステップくらいで完成します。めっちゃはやい。間違いない。
ということでいきましょう。
UnityとMusicEngineダウンロードしてある人は、Pongでは無いですが似たようなことは試せるので立ち上げてみましょう。
- Unity開いたら、あたためておいた音楽にMusic.csをふりかけます。
同時にやっている方は、サンプルの中にオクスのタイトル曲が入っているのでそれを使ってみてください。
すると、デフォルトのセクション情報が挿入されます。テンポ120の場合はこのままでOKです。
それで、あとは曲に応じて、テンポの他に拍子とか、セクションが変化する場合はセクションの情報を追加してほしいんですが、→一旦次のスライドに
→戻ってきて
こんな感じで、1曲を設定すればOKです。
複数の曲を使いたい場合は、PlayOnAwakeがついてるものには自動でアクセスできるようになるので、
その後曲を変更する場合はMusic.Playから変更してください。そうすると同様にその曲の情報にアクセスできます。
あと、基本的にないと思いたいですが、一応1サンプル目から曲が始まらないような、録音されたものとか使いたい場合は始まるタイミングをStartTimeSamplesに指定してください。
セクション内にもStartTimeSamplesってのがあるんですが、これはセクション情報入れたら自動計算されるので、気にする必要はありません
- ここでとても重要な基本クラスであるタイミングとセクションについて簡単に説明しておきます。
タイミングっていうのは、前提で言ったとおり16分音符が1つの単位になってるわけですが、内部の情報としてはこのように
何小節目の何拍目のいくつ目か、という情報になっています。Musicからこの情報を取ることもできますし、
自分でインスタンスを作ってこのタイミングで何をして、とか、さっきのセクションがここから始まります、という情報にも使います。
プログラマの方にはわかりやすいと思うのですが、すべて0スタートになっているので、最初は000で始まって、例えば4小節の最後は333になっています。
DAWを見ながら小節数打ち込む場合はちょっと注意という感じですかね。
次に、セクション情報ですが、要は拍子とテンポですね。これが一定の場合はセクションは1つで充分です。
まぁでも、セクションを判定に使いたい場合は同じ設定で開始タイミングを変えて自由にセクション情報を入れてもらって構いません。
最初のmtBeatっていうのが、1拍にいくつmtを入れるかという所なので、まぁ16ビートなら4ですね。3連符系であれば3とか6にしてもいいと思います。
まぁ1拍をどうとらえるかは人によるわけなので、テンポが指定しやすいように考えればいいと思います。
mtBarは1小節にmtがいくつ入るか、なので、mtBeatが4の場合、16にしたら4拍子、12にしたら3拍子になりますね。
変拍子はここを変えることで対応できて、例えば7拍子なら14にしておけば、最後の拍が半拍で終わって次の小節に行くような挙動になります。
データ的には必ず最後の拍が削られる感じになるので、4433で分けたいと思ってもそこは脳内変換でカバーしてください。
- これで準備OKです。さぁ
- じゃあ次に、とりあえずクオンタイズさせてみましょう。これだけでゲームが音楽的に、気持ちよくなります。
やり方は簡単で、audio.Playを呼ぶ代わりにMusic.QuantizePlayに渡すだけです。
これで自動的にmtに合わせて再生されます。あと急遽今回のゲームのために音程変更も入れました。
ただこれは短い音だと気にならないんですが、このオーディオソースのピッチをそのままいじってるので、多分長い音を連続でやると途中から音程が変わっちゃうかもしれない……
ですがまぁ、お手軽な方法としてお使いください。
Unity開いてる人は、pi.wavをダウンロードしてきて、鳴らしてみましょう。
効果音をつけたオブジェクトに、
if( Input.GetMouseButtonDown( 0 ) )
{
Music.QuantizePlay(audio);}
ってやってみると、クオンタイズのできあがりです。もしよければ音程変更も試してみましょう。
MusicPongではボールの音をクオンタイズしてますね。あと、地味に壁、天井、パドルで音程を変えています。
そのままだとドの音なので、天井は7半音上げてソにしています。
- という感じで、これだけで気持ちよくなりました。
まぁ、Pongはあまり連続してたくさん鳴るわけじゃないんで、これだけじゃ盛り上がらないんですけど、
それにしてもやっぱり、インタラクティブミュージックは低コストで効率いいなぁと思います。
- さてじゃあ次は、演出を音楽に同期させてみましょう。そこでめっちゃ使えるのが、このIsJustChanged系です。
一番よく使います。このためのライブラリだと言っても過言ではない。これは任意のタイミング、小節頭とか、拍とか、直接指定したり、Predicateを指定したりもできます。
MusicPongでは、例えば背景の色を切り替えたりしていますね。色は調整しましたが、わりとランダムに変えても楽しいです。
Unity開いてる人は、カメラに適当なスクリプトをつけて、
if( Music.IsJustChangedBar() ){
camera.backgroundColor = new Color( Random.Range(0.0f,1.0f), Random.Range(0.0f,1.0f), Random.Range(0.0f,1.0f) );
}
とかやってみましょう。
MusicPongではこれを使って背景をバリバリ変えたりしてます。
あと、ボールからビームが出た瞬間にボールを一瞬止めてますが、これも音楽時間で管理してます。
別にここまで合わせなくてもいいんですが、整数で管理できるので割と楽です。
- こんな感じで、演出を音楽に合わせることができます。背景色変えるのは楽にかっこよくできてオススメ。
- ちなみに、さっきJustとか出てきましたが、実はMusicエンジンには2種類のタイミング情報が同時にあってですね、
Justともう一つ、Nowというのがあります。どういうことかというと、
Justはその名の通り、ジャストに来てから切り替わるんですが、
Nowは常に、一番近いタイミング、を指すようになっています。
図にするとこんな感じ。
音ゲー的なタイミング判定には必要かなーとか、あとは元々Justに処理が集中するのが怖かったので分散のために作ったんですが、
ちょうどこの拍に来てしまう前に登録しておきたい!とか、そういう時に使ったりしています。
まぁでも、基本的にJustで事足ります。
- そしてやはり、ゲームをかっこよく見せるのはアニメーションです。これがあるだけでグッとクオリティが上がりますし、音楽に合っているとさらにかっこいい。
そのために、MusicalTimeという値が取れるようになっています。これはまぁ、言ってしまえば時間を音楽時間に変換したものってだけなんですが、
タイミングを指定してこのタイミングから、またはこのタイミングまでどれくらい、っていう取り方もできます。mt基準なので、1小節で16増える、という感じですね。
MusicPongでも、開幕から棒が伸びるのをブオーンという音と一緒にやってますよね。ただ伸ばしてるだけなんですけど。あれ別にスキップできるんですけど、
あれがやりたくてPongを作ったと言っても過言ではない。あれがあると無いとでは天と地のさがあるんです。それこそPRESS STARTが点滅してるかしてないかの違いです。
あとは、ビームのアニメーションもshotTimingの前後1拍、4mt分の時間をスケールに使ってアニメーションしています。
まぁこの式は……僕のセンスの塊なのであまり解説はできませんが……
こんな感じで、もう完全にオリジナルのオシャレな音楽ゲームって感じになるわけですね。
- さて、そして最後は!音楽に合わせたシーン遷移です。
まぁ、普通にゲーム作ってもクリアジングルとかゲームオーバージングルとかシーンって必要になりますよね。
どうせなら音楽に合わせちゃったほうが楽じゃないですか。いや、本当に楽なんですよ。
ということで、音楽をシークする機能もつけました。セクションを作っておけば名前ですぐそのセクションに飛ぶこともできます。
MusicPongでは、ボールが下についたらGameOverにシークしているだけです。
おいしいのはですね、普通シーン遷移って面倒で、これを色んな所に通知しないとゲームがちゃんと動かないわけですが、
この場合音楽が全部のマスタータイマーになってくれるので、音楽の状態を見るだけで、フィールドの状態とか全部を簡単に制御できるんですね。
このスイッチ一発で処理を分けるだけ。
というわけで
- できた!
なんかサンプルゲームのつもりが、意外とリスクとリターンがあって、ゲーム性の変化もあって、パーフェクトプレイ目指すのは意外と難しいという、面白いものができました。
- でも実際、普通にこういう演出入れてPongを作ることを考えたら、音楽に合わせるだけで大分楽に、カッコイイものができたなと思います。
ゲームデザイン的な制約は生まれますが、それをうまく使えばこんなに楽にゲームって作れるんですねー。
- 最後にもう一つTIPSを。
Justとかのデータが実際どういう挙動をしているのか、入力したセクションが正しく反映されているかは、デバッグテキストを指定することで確かめられます。
あの、もしなんかバグっぽかった場合もここで確かめてください。大体取ったはずですが……なんかアクロバットをすると何かが起こらないとは言えないので、、
ちなみに、Unityでピッチを下げたりしても正常に見れるので、ゆっくり見ることも可能です。一応逆再生でも動いていますが、もちろん保証はできませんw
- あと、今日は紹介しきれなかった機能も色々あります。
Music.isFormerHalfはブリンクアニメーションなどでよく使ってますね。ダメージ食らった時とか。
lagUnitはそのまま音ゲーとかの判定にも使えます。クオンタイズにも使ってますね。
あとは、JustChangedはPredicateも使えるので、条件に合ったタイミングだけど抜き出すことができます。
Timingはオペレーターを実装しているので、比較や引き算ができます。足し算はいらないというかセクションまたいだ時に定義不能なのでやめました。
なんか他にも使いやすくなるのがあれば、適宜実装していきたいなーと思います。オープンにしてありますので、是非みなさんのリクエストやコミットをお待ちしております。
- ということで、ありがとうございました。皆音楽ゲーム作りましょう!