Vivifyを使った譜面の作り方
この記事は書きかけです。カスタムイベントの詳細についてはHeckのVivifyの項を参照してください。
Vivifyとは
Vivifyとは、Unityのアセットを使用した譜面を読み込むために必要なMOD。
読み込めるアセットはPrefabかMaterialの形式に出来るならほぼなんでも。(3Dモデル、シェーダー、オーディオ、テクスチャなど……。)
マッパーはVivifyを活用して、カスタムメイドのアセットを作成して譜面の中に入れられる。
ReMapperの導入
ReMapperとは、カスタムイベントを使用する譜面作成を補助するTypeScriptライブラリ。
Vivifyを使用するためにはカスタムイベントを書く必要があり、そのためには譜面にイベントを書くための何かしらのツールが必要となる。メモ帳で譜面のdatファイルに直接書き込んでも良いが、ここではReMapperを使用する。
ReMapperのセットアップ
①Visual Studio Codeを起動し、編集したい譜面のフォルダを開く。

②ターミナルを開き、次のように入力する。

deno install --allow-all -f --reload --global https://raw.githubusercontent.com/Swifter1243/ReMapper-Setup/master/setup/rm_setup.ts
rm_setup
rm_setupを入力後聞かれる質問はそれぞれ、
「プロジェクトを複数の難易度用にセットアップするか」
「プロジェクトをVivify用にセットアップするか」
「Gitをセットアップするか」
で、Yes→Yes→Noで良い。

その後、script.tsというファイルが出来ていたら成功。中を覗くと、以下のようになっているはず。
import * as rm from "https://deno.land/x/remapper@4.0.0/src/mod.ts"
import * as bundleInfo from './bundleinfo.json' with { type: 'json' }
const pipeline = await rm.createPipeline({ bundleInfo })
const bundle = rm.loadBundle(bundleInfo)
const materials = bundle.materials
const prefabs = bundle.prefabs
// ----------- { SCRIPT } -----------
async function doMap(file: rm.DIFFICULTY_NAME) {
const map = await rm.readDifficultyV3(pipeline, file)
// Example: Run code on every note!
// map.allNotes.forEach(note => {
// console.log(note.beat)
// })
// For more help, read: https://github.com/Swifter1243/ReMapper/wiki
}
await Promise.all([
doMap('ExpertPlusStandard'),
doMap('ExpertStandard'),
doMap('HardStandard')
])
// ----------- { OUTPUT } -----------
pipeline.export({
outputDirectory: '../OutputMaps/hoge'
})
function add(value: AnyNote, index: number, array: readonly AnyNote[]): void {
throw new Error("Function not implemented.");
}
これを書き換えてVivify譜面を作っていく。
例えば、以下のように書き換えると、
➀譜面をプレイするのに必須のMODを追加する。
②指定したEnviromentを消去する。
➂アセットバンドルから「hoge」という名前のPrefabを呼び出し、その後削除する。
④譜面を「OutputMaps」フォルダ内の「hogehoge」というフォルダに出力し、またzipで圧縮したファイルも出力する。
という処理になる。
import * as rm from "https://deno.land/x/remapper@4.0.0/src/mod.ts"
import * as bundleInfo from './bundleinfo.json' with { type: 'json' }
const pipeline = await rm.createPipeline({ bundleInfo })
const bundle = rm.loadBundle(bundleInfo)
const materials = bundle.materials
const prefabs = bundle.prefabs
// ----------- { SCRIPT } -----------
async function doMap(file: rm.DIFFICULTY_NAME) {
const map = await rm.readDifficultyV3(pipeline, file)
//➀必須MODを追加
map.require("Chroma")
map.require("Vivify")
//➁指定したEnvironmentを消去
rm.environmentRemoval(map, [
"GameCore",
"Environment",
])
//vivify
//➂hogeというPrefabを0ビート目に呼び出す
const hoge = rm.instantiatePrefab(map, {
beat: 0,
asset: prefabs.hoge.path,
id: "hogeid",
})
//➂hogeを10ビート目に削除
hoge.destroyObject(10)
}
//難易度ExpertPlusにのみ反映
await Promise.all([
doMap('ExpertPlusStandard')
])
// ----------- { OUTPUT } -----------
//➃譜面を2箇所に出力
pipeline.export({
outputDirectory: '../OutputMaps/hogehoge',
zip: {
name: 'hoge',
includeBundles: true,
},
})
function add(value: AnyNote, index: number, array: readonly AnyNote[]): void {
throw new Error("Function not implemented.");
}
ReMapperでは他にも色んな事が出来る。
詳細はこの記事のVivifyカスタムイベントの項を見たり、HeckのVivifyの項を見たり、Swifterさんの「you」プロジェクトを見て欲しい。
ちなみに、スクリプトを更新した時に自動で実行するには、Powershellのターミナルで次のように入力。
deno install -qAf --unstable --global https://deno.land/x/denon/denon.ts
その後、Visual Studio Codeのターミナルで次のように入力。
denon rm
denon rmは起動の度に毎回入力する必要がある。
Unityのセットアップ
➀アーカイブからバージョン2019.4.28f1のUnityをインストールする。
②Unity Hubで、2019.4.28f1の新しいプロジェクトを作成する。
➂https://github.com/Swifter1243/VivifyTemplateから最新のUnityPackageをインポート。
④Vivifyタブが上部にあれば成功!
Unityのアセットバンドルのビルド
PrefabやMaterialをビーセイやReMapperで呼び出すには、Unityでアセットバンドルを作って譜面と同じフォルダに置かなければならない。
Vivify用のアセットバンドルに出来るのはPrefabとMaterialのみ。(その中に含まれているAnimationやShaderはバンドルに入る)
バンドルを作成するには、バンドルにしたい物を選択後、Inspector下部のAssetBundleラベルの右側のNoneを押し、Newを押してbundleと名付ける。

ビルドに進むには、上部のVivifyタブを押し、Build Configuration Windowを押す。

すると下記のようなウィンドウが出現する。

・Versionsはビルドしたいバージョンを表し、ビーセイのSteam版1.34未満はWindows 2019、1.34以上はWindows 2021、Quest版はAndroid 2021がバンドルの動作に必要となる。最終的に譜面をアップロードするまでは、自分の環境1つ分だけのビルドで良い。
・Compressedは圧縮するかどうかで、これも譜面のアップロードまではチェックしなくて良い。アップロード時は必ずチェックする。
・Bundle To Exportはビルド対象のアセットのラベルの名前。(変更しなくて良い)
・Export Bundle InfoとPrettify Bundle Infoはチェックしたままにする。
・Output Directoryはバンドルの出力先。通常は譜面のフォルダで良い。
・Quick Buildは、F5を押した時にどのバージョンですぐビルドするか。自分の環境のバージョンを選択する。
全て確認し終えたら、BuildボタンまたはSetupボタンを押す。
■Buildボタンを押した場合
下記画像のように、文字が緑色になれば成功。Output Directoryで指定した場所にbundleinfo.jsonとbundleWindows2021.vivifyのような名前のファイルがある事を確認する。

■Setupボタンを押した場合
ボタンがSetupからBuildに変わるまで、画面の指示に従う。
Quest版のセットアップ時にインストールするのは、https://unity.com/ja/releases/editor/whats-new/2021.3.16#installersのComponent installers → Android Build Supportのもの。
Vivify カスタムイベント
この項目は書きかけです。カスタムイベントの詳細についてはHeckのVivifyの項を参照してください。
・アセットのパスはbundleinfo.jsonで確認出来る。prefabs.hoge.pathのように書くと、「hoge」という名前のprefabを指定する。
・アセットのパスは全て小文字で書く必要がある。アセット名が「Hoge」であっても「hoge」と書く。
・コード例は全てReMapperでのもの。
InstantiatePrefab
Prefabを呼び出す。
const hoge = rm.instantiatePrefab(map, {
beat: 0,
asset: prefabs.hoge.path, //Prefabのパス
id: "hogeid", //(DestroyObject等で識別するためのid)
track: "hogetrack", //(NEで識別するためのtrack)
})
DestroyObject
Prefab、Camera、Textureを破棄する。アセットをずっと読み込んだままだと重くなる要因のため、必要無くなったアセットは破棄すること。
hoge.destroyObject(x) //xにビートを入れる
assignObjectPrefab
特定のオブジェクトをPrefabに置き換える。パスをnullにするとデフォルトモデルに戻す事も出来る。
セイバー
rm.assignObjectPrefab(map, {
saber: {
type: "Both", //どちらのセイバーに影響を与えるか Both, Left, Right
asset: prefabs.hogesaber.path, //セイバーのPrefabのパス
trailAsset: materials.hogetrail.path, //(トレイルのPrefabのパス)
trailDuration: 0.4, //(トレイルの持続時間)
trailTopPos: [0, 0, 1], //(トレイルの先端の位置)
trailBottomPos: [0, 0, 0], //(トレイルの終端の位置)
trailGranularity: 50, //(トレイルメッシュの分割数)
trailSamplingFrequency: 60, //(トレイルの秒間描画数)
},
})
ノーツ
rm.assignObjectPrefab(map, {
colorNotes: {
track: "hoge", //NEで識別するためのtrack
asset: prefabs.hogenote.path, //ノーツのPrefabのパス
anyDirectionAsset: prefabs.hogedot.path, //(ドットノーツのPrefabのパス)
debrisAsset: prefabs.hogedebris.path, //(デブリのPrefabのパス)
},
})
SetMaterialProperty
Materialのプロパティを設定する。プロパティ名はbundleinfo.isonの他、シェーダーファイルのPropertiesの所でも見つかる。

materials.hoge.set(map, {
_hogeproperty: [
[0, 0], //1つ目はプロパティの値、(2つ目は時間)、(3つ目はイージング)
[1, 1]
]
}, 0, 10) //(0ビートから10ビートかけて再生)
トラブルシューティング
スクリプトは実行出来るが、”クラスが定義されていない”のようなエラーが出る。
→拡張機能の検索で@builtin typescriptと入力し、"TypeScriptとJavaScript の言語機能"を無効にする。
アセットが黒い見た目になる。
→VRに対応したシェーダーか確認する。良く分からなかったらUnityでCrate→Shader→Vivifyのものを使う所から始める。
アセットが白く発光する。
→シェーダーのアルファ値を0にする。それでも解決しない場合はアルファ関係の設定を見直す。
片目だけしかレンダリングされない。
→参照 https://redhologerbera.hatenablog.com/entry/2022/01/31/212231