ChroMapperを使った作譜
どうも。姚明(やおみん)と申します。
今年5月からBeat Saberを始めました。というよりVRゲーム自体Beat Saberが初でした。
始めたての頃はカスタム譜面で、好きな曲の譜面や有名な譜面をプレイしているだけでしたが、7月頃から自分で譜面を作るという事を始め、8月からは変な譜面の作成にも手を出し始めてしまいました。
視点が上下左右に動いたり…
(CubeCommunityの動画)
ノーツが急停止したり…
(ふぇふぃーさんの動画)
ライトが眩しかったり…
(みたらしさんの配信クリップ)
色々譜面を作って来ました。
そこで、この記事ではこういった特殊譜面の作り方やそのためのエディターについて話していこうと思います。
仕組みさえ分かってしまえば結構簡単に作れちゃうので、記事を読んで作ってみたいな~と思ったら是非チャレンジしてみてください。
この記事はBeat Saber Advent Calendar 2020の15日目の記事となります。
■ChroMapperとは?
上に挙げた3つの譜面は、どれもChroMapperという3Dエディターで作っています。
ChroMapperでは基本的な作譜に加えて、ノーツにアニメーションを付ける等出来るNoodleExtensions(以下Noodle)、オブジェクトの色を自由に設定等出来るChroma2.0(以下Chroma)を扱う事が出来ます。
またMappingExtensions、360度/90度のレベルにも対応していて、現状では最も多機能なエディターと言っていいでしょう。
しかし、どれだけ多機能と言っても使い方を知らなければ使えませんし、何が出来るのか分からないですよね。
まずは、実際にどんな画面で操作するのか見てみましょう。
Chromapperを起動して見ました。
何か色々並んでますね……。今見ているのは、譜面選択画面です。曲名の右側にEditボタンがあり、それを押すと譜面の情報を見る事が出来ます。
1つ譜面を選んでみました。
曲名やBPM、難易度など、MediocreMapAssistant2(以下MMA2)でお馴染みの情報がありますね。
さて譜面編集に入ってみましょう。
グリッド線が引いてあって、左側にノーツやボムを配置する場所、右側にライトを置く場所があります。
画面上のタブでは赤ノーツ、青ノーツ、爆弾、壁、ゴミ箱等のアイコンがありますね。対応するキーを押すか、アイコンをクリックする事でオブジェクトを配置出来るようになります。
MMA2に慣れている方ならすぐ順応出来るでしょう。
■Noodleでオブジェクトを動かしてみよう
Noodleのアニメーションドキュメントを基に書いています。
ノーツが活きの良い動きをする譜面を作る時間です。
とりあえずチュートリアルも兼ねて、でかいノーツを作ってみましょう。
ノーツを1つ選択して、その状態でNキーを押してみると……
何か変なウィンドウが出てきました。これはノードエディターというもので、選択したオブジェクトの記述を見たり、変えたりする機能です。
書いてある内容を見てみましょう。
{
"_time" : 4,
"_lineIndex" : 2,
"_lineLayer" : 0,
"_type" : 1,
"_cutDirection" : 1
}
色々書いてありますね。このままでは何が何を指しているか分からないので、説明を加えます。
{
"_time" : 4, #何ビート目にあるか
"_lineIndex" : 2, #どのレーンにあるか
"_lineLayer" : 0, #どの高さにあるか
"_type" : 1, #オブジェクトの種類
"_cutDirection" : 1 #斬る向き
}
だいぶ分かりやすくなったのでは無いでしょうか。
_typeを1から0に変えてみると……
青ノーツが赤ノーツに変わってしまいました。
_cutDirectionを1から0に変えると……
斬る向きが逆になってしまいました。
なんだか楽しくなってきましたね。
さて、ノードエディターの使い方が分かった所で、でかいノーツを作りましょう。
Ctrl + Shift + Tキーで、カスタムイベントを生成出来ます。
こんなポップアップが出てきたら、AnimateTrackと打ちSubmitしましょう。
すると、BPM変更の横にAnimateTrackなるレーンが追加されます。
このレーン上をクリックし、AnimateTrackを1個設置します。そして、中身をノードエディターで見てみましょう。
{
"_time" : 4,
"_type" : "AnimateTrack",
"_data" : null
}
"_data" : nullと書いてありますね。nullは「何もない」という意味で、つまりAnimateTrackはまだ何の効果ももたらさないという訳です。これからここに命令を書き込んでいきます。次のように記述してみましょう。
{
"_time" : 4,
"_type" : "AnimateTrack",
"_data" : {
"_track" : "deka_Note",
"_scale" : [
[
1,
1,
1,
0
],
[
4,
4,
4,
1,
"easeInSine"
]
],
"_duration" : 10
}
}
書いた内容について解説していきます。
_trackはどのグループ(トラック)に命令を適用するかを決めます。今回の場合、"_track" : "deka_Note"と書いているので、deka_Noteと名付けたトラックに命令を適用します。
_scaleはオブジェクトの大きさを決めます。xyzの軸それぞれの大きさとその大きさになるのにかかる時間を決める事が出来ます。定義は[x, y, z, time, easing]です。始点では[1,1,1,0]と書いていますね。これはtimeが0の時xyzそれぞれの大きさが1になるという意味です。オブジェクトのデフォルトの大きさは1なので、大きさは変わりません。後で書きますが、ここで使うtimeはビートの値ではなく、_durationという語で使う値です。
終点では[4,4,4,1,"easeInSine"]と書いています。timeが1の時大きさは4になり、その大きさになるのにeaseInSineという関数を使っているという意味です。
イージング関数について説明しましょう。Noodleでは、値の変化率を決める関数を扱う事が出来ます。
easeInSineは、変化率が徐々に加速していく関数です。つまりさっき書いた内容では、timeが0から1になるに連れ、オブジェクトの大きさは1から4へと大きくなっていく、という事になります。
_durationはイベントの長さを決めます。今回は"_duration" : 10と書いているので、10ビートかけてイベントを進行させます。_scaleで、timeが0の時と1の時を書いたのはこのためです。
timeが0の時……つまりイベントが始まってすぐの0ビート目ではオブジェクトの大きさは1です。timeが進行していくと、イージング関数によりオブジェクトの大きさは徐々に大きくなっていき、timeが1になると……つまり10ビート目になるとオブジェクトの大きさは4になります。
どんな命令をAnimateTrackに書き込んだか、理解出来たでしょうか。
次は、ノーツに命令を適用させるために、さっき名付けたdeka_Noteというトラックにノーツを放り込みます。
"_customData" : {
"_track" : "deka_Note"
}
この記述をノーツに書き込みます。が、せっかく10ビートもあるカスタムイベントを作ったので、複数のノーツに書き込んでみましょう。
範囲選択で複数のノーツを選択して……
ノードエディターを開きます。
{
"_time" : -,
"_lineIndex" : -,
"_lineLayer" : 0,
"_type" : -,
"_cutDirection" : -
}
おっと、-と表示されていて値が書いていない箇所が出てきましたね。これは複数のオブジェクトを選択しながらノードエディターを開くと起こるもので、オブジェクト同士で値が共通していないとこの表記になります。私が選択したのは全て高さが0のノーツなので、_lineLayerだけは0と表示されました。
さて、記述を変えましょう。
{
"_time" : -,
"_lineIndex" : -,
"_lineLayer" : 0,
"_type" : -,
"_cutDirection" : -,
"_customData" : {
"_track" : "deka_Note"
}
}
deka_Noteにノーツを放り込みました。
これで、上手くいっていれば徐々に大きくなるノーツが出来上がっているはずです。実際に見てみましょう。
大きくなりすぎて、地面にあるセイバーにノーツが当たってしまいました。成功したようです!!
たったこれだけの作業で、大きいノートが作れました。そんなに難しくないですよね。え?難しい?確かに。
Noodleで出来る事は、もちろん大きさを変えるだけではありません。私がBeatServerにアップロードした譜面を見て、もっと色々な命令について学んでいきましょう。
■Noodle譜面例─裏切り者のレクイエム
記事冒頭のふぇふぃーさんの動画を見たか、もしくは譜面をプレイした前提で話していきます。まず冒頭から。
ここではNoodleは
①プレイヤーの視点が下から上に上がっていく
②小さな白いノーツが後ろ両脇から飛んでくる
の2種類の演出で使っています。
①についてですが、視点を操作するカスタムイベントがあります。
AssignPlayerToTrackというもので、これは指定したトラックでプレイヤー視点の変更が出来るようにするためのイベントです。
{
"_time" : 0,
"_type" : "AssignPlayerToTrack",
"_data" : {
"_track" : "PlayerTrack"
}
}
譜面では、PlayerTrackと名付けたトラックを指定しています。トラック名は何でも構いません。
隣にあるAnimateTrackでは、
{
"_time" : 0,
"_type" : "AnimateTrack",
"_data" : {
"_track" : "PlayerTrack",
"_duration" : 30,
"_position" : [
[
0,
-2,
0,
0
],
[
0,
0,
0,
1
]
]
}
}
PlayerTrackを指定して、_positionという語でプレイヤーの視点位置を時間と共に上げていっています。
_positionはオブジェクトの位置を決めます。定義は[x, y, z, time, easing, spline]です。今回は、始点はy軸が-2、終点は0になるように書いています。
あれ?イージング関数が見当たりませんね。この場合、値の変化率は一定(Liner)になります。30ビートかけてイベントが進行するので、y軸は1ビートあたり約0.067ずつ上がっていくという事になります。
②の白いノーツが飛んでくるからくりは、ノーツをノードエディターで見てみると分かります。
{
"_time" : 1,
"_lineIndex" : 20001,
"_lineLayer" : 20002,
"_type" : 0,
"_cutDirection" : 1,
"_customData" : {
"_track" : "smallNote",
"_fake" : true,
"_interactable" : false,
"_position" : [
-9.959,
5.593
],
"_noteJumpStartBeatOffset" : 10,
"_noteJumpMovementSpeed" : 2,
"_color" : [
1,
1,
1
],
"_animation" : {
"_rotation" : [
[
0,
180,
0,
0
]
],
"_dissolve" : [
[
1,
0
]
],
"_dissolveArrow" : [
[
1,
0
],
[
1,
0.2
],
[
1,
0.85
]
],
"_localRotation" : [
[
45,
90,
300,
0,
"splineCatmullRom"
],
[
34.39,
39.329,
171.062,
0.2,
"splineCatmullRom"
],
[
39.871,
24.516,
299.487,
0.4,
"splineCatmullRom"
],
[
64.517,
22.309,
121.982,
0.6,
"splineCatmullRom"
],
[
6.914,
49.159,
230.016,
0.8,
"splineCatmullRom"
]
],
"_position" : [
[
1.306,
-1.212,
1.44,
0,
"splineCatmullRom"
],
[
1.098,
-1.47,
-0.218,
0.2,
"splineCatmullRom"
],
[
-0.446,
-0.08,
-0.05,
0.4,
"splineCatmullRom"
],
[
0.826,
-1.066,
1.12,
0.6,
"splineCatmullRom"
],
[
-1.314,
0.976,
1.253,
0.8,
"splineCatmullRom"
],
[
0,
0,
0,
1,
"splineCatmullRom"
]
]
}
}
}
うわあ、とても長い!
でも、書いてある事はそんなに難しくありません。上から1つずつ見ていきましょう。
_lineIndexと_lineLayerが2万以上の値になっていますね。という事は凄い変な所にこのノーツはある……?そんな事はありません。
_positionで位置を定義している場合、_lineIndexと_lineLayerは無効になります。どれだけ変な値にしようが関係無いので、オブジェクトを識別するのに便利な仕様です。
"_track" : "smallNote"と書いていますが、このトラックのオブジェクトはサイズが小さくなるようにAnimateTrackで記述しています。
そういえば、このノーツは斬らなくてもヘルスは減らないしコンボにも影響しません。Noodleって何でもアリですね。
_fakeはtrueならノーツをコンボ/スコア/ヘルスバーに影響が出ないようにします。
_interactableはfalseならノーツの当たり判定を消します。
_fakeと_interactableは、ノーツを演出用として出す時に使えます。AnalysやNULCTRLでも使われていて、こういう譜面でやたらミス数が増えていくのはこのせいです。
Noodleにかかれば譜面情報に書かれている数値も意味を成しません。
_noteJumpStartBeatOffsetはオブジェクトのスポーン位置(オフセット)を決めます。
_noteJumpMovementSpeedはノーツ速度(NJS)を決めます。
オフセットは10、NJSが2なので……物凄い遠くから物凄く遅いノーツが飛んでくる事になります。
ノーツの色が白色なのは、Chromaの機能を使っているからです。
_colorはオブジェクトの色を決めます。
定義は[r, g, b, alpha, time, easing]です。今回は[1,1,1]と書いていますね。RGB値はカラーパレット(後述)では0~255の整数で表されますが、ノードエディターでは0~1の範囲で表されます。RGB値、アルファ値ともに値を1より大きくした場合、明るさが上がります。
明るさを上げ過ぎるとこうなります。ゲーム内でも発光していて死ぬほど眩しい。
_animationについて説明する時がやって来ました……。
_animationはオブジェクトに直接アニメーション関係の命令を書き込めるようにします。
ノーツを震わせたり回転させたり、といった動きは普通はカスタムイベント内で記述しますが、_animationを使う事でオブジェクトに書いても良いようになります。
_rotationはオブジェクトを世界に対して回転させます。
定義は[pitch, yaw, roll, time, easing]です。今回はヨーを180度回転させているので、ノーツがプレイヤーの後ろから飛んでくるようになっています。
_dissolveはノーツの見た目を矢印以外消します。ModifiersのGhostNotesみたいなものです。
_dissolveArrowはノーツの見た目から矢印を消します。ModifiersのDisappearingArrowsみたいなものです。
定義はどちらも[transparency, time, easing]です。
今回はtime=0の時点でどっちも有効なのに見た目が消えていませんね?
オブジェクトにアニメーションを直接設定すると、オブジェクトがスポーンした時がtime=0、デスポーンした時がtime=1になるのですが、_rotation等で見た目上の位置が変わるとtime=1より先でもオブジェクトが存在し続ける事が出来ます。今回のはあまり良い例ではないので、この2つの命令は後でまた説明します。
_localRotationはオブジェクト自体を回転させます。
定義は[pitch, yaw, roll, time, easing, spline]です。
今回はノーツをすっごいクルクルさせてます。記述には、splineCatmullRomという見慣れないものがありますね。
Noodleではスプライン曲線も扱う事が出来ます。
オブジェクトに弾力のある動きをさせたい時は使いましょう。
このノーツに書かれている内容が少しは理解出来たでしょうか。
全てを理解しなくても、白いノーツが後ろからゆっくりふよふよ飛んでくるんだな~くらいの認識で大丈夫です。
ようやく次のシーンに進めます。
赤と青の正方形の壁がノーツへと変わっていくシーンです。
エディターでは正方形の壁とノーツが同じ位置にありますね。
ここは特に難しい事はしてなくて、壁の方はノーツに切り替わる時にタイミング良くscaleを弄っているだけです。ノーツの方は切り替わるタイミングで_dissolveと_dissolveArrowを解除しています。_dissolveは矢印以外を消し、_dissolveArrowは矢印を消すという事をさっき説明しました。2つを同時に有効にするとどうなるか……答えは、ノーツが透明になります。ただし、scaleで小さくして見えなくするのと違い当たり判定はそのままです。判定変わらないのは結構プレイヤーに優しいのでどんどんこの技使っていきましょう。
次のシーン!
上と下に青と紫のブツブツが流れています。エディターで見るとこんな感じ。
ブツブツの正体はノーツでした。
ここもやってる事は単純で、_dissolveを中途半端な値にして消えかけの見た目にしただけです。_dissolveや_dissolveArrowのアニメーションを利用するNoodle譜面は多いので、あそこの演出どうなってるんだって譜面はこの2つの命令に注目して見てみると面白いかも知れません。
ちょっと飛んで、次はこちら。
ノーツが脈打つシーンです。
カスタムイベントの記述を見てみましょう。
{
"_time" : 145.75,
"_type" : "AssignPathAnimation",
"_data" : {
"_track" : "springNote",
"_scale" : [
[
1,
1,
1,
0
],
[
2,
1.5,
1,
0.1,
"easeInElastic"
],
[
1,
1,
1,
0.25,
"easeOutElastic"
],
[
2,
1.5,
1,
0.35,
"easeInElastic"
],
[
1,
1,
1,
0.5,
"easeOutElastic"
]
]
}
}
新たなカスタムイベントが出てきました。
AssignPathAnimationはオブジェクトをアニメーションさせるためのイベントですが、AnimateTrackと違いtimeはオブジェクトのスポーン/デスポーンを基準にします。
ノーツが脈打つのはscaleを使ってノーツを一瞬だけ大きくして、イージング関数でバウンドさせることでそう見せています。ノーツがデスポーンし始めるのはtime=0.75あたりからなので、time=0.5で終わるこのイベントはそのちょっと前に終了するという事になります。
そして次はそう、キングクリムゾンのシーン。
ノーツと壁が目の前で崩れていく、特殊OPの再現。ここどうするかちょっと悩んだけど良い感じに出来た。褒めて。
あっそれでどうやっているのかですが、これの直前に流れていたノーツや壁は_fakeと_interactableで斬れなくしてscaleで小さくしてます。下に向かって崩れていくノーツと壁の仕組みは、カスタムイベントを見れば分かります。
{
"_time" : 179.5,
"_type" : "AssignPathAnimation",
"_data" : {
"_track" : "detekurukabe",
"_definitePosition" : [
[
0,
0,
10,
0,
"easeInSine"
],
[
0,
0,
0,
1,
"easeInSine"
]
],
"_rotation" : [
[
0,
0,
0,
0,
"easeInQuart"
],
[
0,
180,
180,
1,
"easeInQuart"
]
]
}
}
_definitePositionはオブジェクトの位置を決めますが、_positionとは違いオブジェクトの動きを完全に上書きします。ジョジョで言うとクラフトワークで固定させてる感じ。
定義は[x, y, z, time, easing, spline]です。
z軸が10から0になっていくので、だんだん手前によって来てますね。また_rotationでオブジェクトをゆっくりと回転させてプレイヤーの立っている床の真下に持って行っています。ここには書いていませんが、用が済んだら(次のシーンに行ったら)_scaleで見えなくして、自然消滅させています。
次のシーン、GER。
_rotationでヨーを180度回転させてオブジェクトを後ろから飛ばしています。
次!
回転している壁は_rotationで回転させています。
色が変わる壁は、カスタムイベントで_colorをtimeが進むに連れ変化させていっています。
ラスト!
黄金の風が吹くシーンです。誰が何と言おうと黄金の風です。
ブツブツで想像出来たかも知れませんが、_dissolveと_dissolveArrowでノーツを良い感じにしてます。
Noodleと「裏切り者のレクイエム」の解説はこれで終わりです。後半説明雑でごめんなさい!
一度に色々と説明し過ぎたので、解りづらかったかも知れません。分からない所があったら、質問してきてください。
■Chromaでライトを派手にしよう
記事はまだ終わりではありません。今度はChromaについて解説していきます。
Chromaで出来るようになるのは……ノーツや壁、ボムの色を変える事もありますが、ライティングを大幅に拡張してくれます。
とりあえずライトのレーンを見てみましょう。
MMA2と見た目は殆ど変わらないものの、各ライトに名前が割り当てられています。なおライト名やライトの数はFitBeatやGreenDayなどEnvironmentによって変わります。
このまま赤と青の通常のライトを置いてもいいですが、Chromaを使ってまで置きたいのはもっと存在感のあるライトです。
画面上にあるタブから、赤青黄緑の円のアイコンをクリックしてみましょう。
画面右上にカラーパレットが出てきました。
カラーパレットではRGB値やアルファ値を自由に決めて色を作る事が出来ます。作った色の保存も可能です。
ChromaRGBの機能を有効にするとカラフルなライトが置けるようになるので、早速置いてみましょう。
適当に置いてみました。譜面を再生してライトを確認してみましょう。
置いた通りの色のライトが点きました。たったこれだけの操作で譜面が華やかになりましたね。
他の便利な機能についても紹介しましょう。
グラディエント(グラデーション)機能は2点のライト間で、連続的に色が変化するグラディエントを生成します。
画面では水色から赤紫色へと変化するグラディエントを作っていますね。
ちなみにノードエディターでも弄れます。
{
"_time" : 4,
"_type" : 2,
"_value" : 5,
"_customData" : {
"_lightGradient" : {
"_duration" : 1,
"_startColor" : [
0.275,
0.71,
0.71
],
"_endColor" : [
0.88,
0.293,
0.671
],
"_easing" : "easeLinear"
}
}
}
_startColorが始点の色、_endColorが終点の色です。
ステップグラディエント機能は色の変化が段階的なグラディエントを生成します。
8分刻みで作るとこんな感じになります。分かりやすく色が変化していく。16分や32分刻みで作ってもいいですが、あまり細かくし過ぎると通常のグラディエントと大して変わりません。
レーザー速度補間機能は2点のレーザー速度間を補間します。
速度0と速度10を選び、8分刻みで補間するとこんな感じです。
レーザーの向きを決めたり、直前のレーザー位置を保持するかどうかも選べるので、スタイリッシュなレーザーを作る事が可能です。
ノードエディターで見るとこう。
{
"_time" : 4,
"_type" : 13,
"_value" : 1,
"_customData" : {
"_preciseSpeed" : 0, #レーザーの速度 小数点以下も入れられる
"_direction" : 1, #レーザーの向き
"_lockPosition" : true #直前のレーザー位置を保持するか trueで保持
}
}
次は1つのレーンのライトで、異なる色を同時に発生させるための操作を見ていきましょう。
RingPropモードではIDを指定してライトを置けるようになります。
Pキーを押して早速RingPropを使ってみましょう。
BIG RINGS ID1…BIG RINGS ID2…BIG RINGS ID3…
ズラっと並んでいますね。ID1つ1つが、リング1つ1つと連動しています。
とりあえずゲーミング……じゃなかった虹色にライトを置いてみましょう。
わあ綺麗。細かく色を決める事が出来ましたね。
ちなみにRingPropと名前が付いていますが、PageUp、PageDownキーでサイドレーザーやバックレーザーもIDを指定して置けるようになります。
RingPropの注意点として、FlashライトとFadeライトが使えません。OnとOffのみ使えます。
リングの回転も制御してみましょう。RingRotationにライトを置き、例によってノードエディターを開きます。
{
"_time" : 5,
"_type" : 8,
"_value" : 0,
"_customData" : {
"_direction" : 0, #回転の向き 0か1のみ
"_speedMult" : 5, #回転の速度
"_propMult" : 2, #回転が手前の輪から奥の輪に伝わる速度
"_stepMult" : 1 #各輪の回転のばらつき具合 0でばらつかない
}
}
_propMultを小さくして長い間回転させたり、_stepMultを0にして整った回転をさせたり……など、様々に動かせるようになります。
さて、ここまでChromaのライティング拡張について説明をしてきましたが、ライトの色がどうとか、レーザーの速度がどうとか言っても画像だけでは伝わりにくいと思います。
そこで動画を撮ってきました。
かなへびさんとの合作譜面で、曲名は「Starlight Dance Floor」。
ライティングは全部私が担当しました。
このところBeatServerが不調なので記事投稿時に譜面をアップロード出来ているか分かりませんが、ノーツ配置も結構動けて楽しい感じなので良ければプレイしてみてください。(ダイレクトマーケティング)
■おわりに
特殊譜面がどうやって作られているか、その仕組みが少しは分かって貰えたでしょうか。
私は普段まともな文章書かないし、作譜も雰囲気でやってるしで、もしかしたら凄い読みづらかったかも知れません。説明が間違っていたらと思うと不安で不安で夜しか眠れない……。
この記事を読んでくれた方がNoodleやChromaに興味を持って、奇抜な譜面作ってくれたらとても嬉しいです。即プレイしにいきます。作ってください。変な譜面大好きなんです。
とても長い記事でしたが、ここまで読んで頂きありがとうございました!!
この記事が気に入ったらサポートをしてみませんか?