- 投稿日:2020-07-08T22:03:33+09:00
Gateboxに自分好みの嫁を召喚しておしゃべりする
嫁は「探す」時代から「創る」時代へ
”俺の嫁召喚装置”ことGateboxにはかわいらしいお嫁さん「逢妻ヒカリ」ちゃんがプリ召喚済みですが、見た目も声もできることも”完全に自分好みの嫁”を召喚したい・育てたいという方も多くいらっしゃることと思います。
そこで、嫁を召喚したい一心で開発した3Dモデルのチャットボット化フレームワーク「ChatdollKit」のご紹介も兼ねて、雑談できる嫁の作り方とGateboxへの召喚方法を皆さんにもシェアしたいと思います。
なおこの記事で作る嫁はGatebox以外でもAndroid / iOSをはじめとするマルチプラットフォームで動作すると思います(たぶん)
出来上がりのイメージ
ヒカリちゃんのようにおしゃべりに加えて色々なことをしてくれる嫁にしたいのはヤマヤマですが、この記事ではまず夫婦間の他愛もない会話(雑談)ができるようにしていきます。
また、全体の構成と機能間の連携に関する概要は以下のとおりです。
開発環境のセットアップ
Unityの3Dプロジェクトを新規作成して以下のパッケージをインポートします。
JSON .NET For Unity みんな大好きNewtonsoft.JsonのUnity版。このあと入れるChatdollKitの依存ライブラリ
Oculus LipSync Unity 声にあわせて口パクしてくれるライブラリ
ChatdollKit 3Dモデルを使ってしゃべって動くチャットボット作るためのフレームワーク。この記事はv0.1.8をベースに書いています
Gatebox SDK Gateboxでアプリを動作させるためのライブラリ。入手にはDeveloper Programへの参加が必要。Gatebox実機での動作確認以外はこのライブラリがなくても試すことができます。申請から登録完了まで時間がかかるかもしれないので今のうちに登録しておきましょう
モデル用リソースの準備
美少女の構成要素は身体(=3Dモデル)・声(=読み上げサービス)・動き(=アニメーションクリップ)です。それぞれ準備していきましょう。
3Dモデルの入手と設定
最重要タスクです。この子とおしゃべりしたいという気持ちがモチベーションの全てです。BOOTHなどで気に入った子を探してシーンに配置してください。あわせてメインカメラのアングルや光源の設定もお好みに合わせると良いでしょう。
この記事では/kitchen_syncさまのCygnetちゃんを利用させていただいております。かわいいと思ったら迷わず課金しましょう。Cygnetちゃんの場合はシーンSETUP
にセットアップ済みのモデルが配置されていますので、コピーして自分のシーンにペーストすればOKです。音声認識・音声読み上げサービスのアカウント作成
ユーザーの発話を聞き取ったり、モデルのセリフを読み上げたりするためのAIサービスとして、本稿ではAzureを利用します。以下を参考にCognitive ServicesのSpeech API(Speech Services)のAPIキーを入手してください。
https://docs.microsoft.com/ja-jp/azure/cognitive-services/speech-service/get-startedクレジットカードがなくてもここからすぐにトライアルできるようです。
アニメーションクリップの配置
お手持ちのものがあればそれを、なければ本稿でも使用するAnime Girl Idle Animations FreeをAssetストアからダウンロード・インポートして、
Assets/Animations
フォルダを作成してその中に配置します。BOT化ライブラリの設定
先の手順で導入したリソースや後の手順で追加する対話ロジックをつなぎ合わせてBOTにするライブラリChatdollKitの設定を行なっていきます。この章では主に「ModelController」関連の設定を行いますが、以降の章の作業対象も図に併記しましたので参考にしてください。
ChatdollKitの追加
はじめに
Assets/ChatdollKit/ChatdollKit/Scripts/chatdoll.cs
を3Dモデルに追加します。
ModelControllerの設定
ModelControllerとは、3Dモデルのアニメーション、発話、表情を制御するための機能です。インスペクターのコンテキストメニューからSetup ModelControllerを実行してセットアップしましょう。基本的には自動で設定されますが、まばたきをするためのシェイプキーについては個別に設定が必要です。
blink
だったりeyes_close
だったりモデルによって異なると思いますのでシェイプキーを動かしてそれらしいものを見つけて入力しましょう。
Animatorの設定
モデルの身振り手振りを司るAnimator Controllerを作成して3Dモデルにセットする工程です。ここもインスペクターのコンテキストメニューからSetup Animatorを選択して自動設定することができます。
メニューから実行すると読み込むアニメーションクリップの格納先を尋ねられますので、先ほど配置したAnime Girl Idle Animationsの中のAnimationsフォルダを選択します。すると「このアニメーションクリップをどのレイヤーに配置するか?」と聞かれますので、とりあえずは全部Base Layerを選択することでOKです。
最後に作成されたAnimator Controllerを開いてBase Layerのデフォルトステートのクリップを適当なアイドル感あるものに変更すれば設定完了です。
動作確認
ここいらで一旦動作確認してみます。Unityの実行ボタンを押すと、先の手順でDefaultステートに設定したアニメーションのポーズをとり、そしてまばたきをしていたら手順OKです。
音声対話の設定
音声対話のフローとしては、以下のような一般的なAIスピーカーと同じ流れを採用します。
私「嫁ちゃん」←ウェイクワード 嫁「なんだい?」 ←プロンプト 私「蟹座の今日の運勢は?」 ←リクエスト 嫁「ろくでもないよ」 ←レスポンスここでは、上記のうち「ウェイクワード」と「リクエスト」をこちらから投げられるようにする設定と、プロンプトやレスポンスのベースとして嫁がしゃべれるようにする設定をしていきます。
ウェイクワードの設定
ウェイクワードを検知すると何らかの処理をキックするための部品として
AzureWakeWordListener
が提供されています。これをChatdollKit.Extension
から追加して、インスペクター上でAzure Speech ServicesのAPIキーとリージョンを設定しましょう。続いて反応してほしい合言葉をWakeWordsに登録します。私は妹が好きなので「妹」を登録しますが、好きなもので構いません。ただしAzureで認識された言葉を使って判定しますので、一般的な単語でないとうまく反応してくれません。(Azureの認識モデルをカスタムのものにすれば特殊なものもOKと思われる)
また、呼びかけをキャンセルするための合言葉を
Cancel Words
に登録しておきましょう。ここでは「おしまい」で処理を中断するようにします。
リクエストの設定
ウェイクワードで聞き取りモードになったあと、嫁へのお願いを聞き取ってもらうための部品として
AzureVoiceRequestProvider
が提供されています。ChatdollKit.Extension
から追加して、インスペクター上でAzure Speech ServicesのAPIキーとリージョンを設定します。(WakeWordListenerと同じものでOK)また、話しかけた内容が嫁にはどのように聞こえているかを表示するメッセージボックスを追加しておくと便利です。
ChatdollKit/Prefabs/SimpleMessageWindow
からSimpleMessageWindow
をヒエラルキーに追加し、非表示(インアクティブ)にしたあと、ヒエラルキーからリクエストプロバイダーのMessageWindow
にセットしましょう。
音声読み上げサービスの設定
嫁に任意のテキストを声に出しておしゃべりしてもらうための部品として、
AzureTTSLoader
が提供されています。ChatdollKit.Extension
から追加して、インスペクター上でAzure Speech ServicesのAPIキーとリージョンを設定します。また、Is Default
に忘れずにチェックを入れるようにしてください。
スクリプトの作成
嫁が動いたり話を聞いたり喋ったりするための準備が完了しましたので、いよいよスクリプトを書いて魂を吹き込んでいきます。
まずはAssets/ScriptsにMonoBehaviourなスクリプトを追加して、以下のコードをまるっと書き写したら3Dモデルにアペンドしてください。
AppMain.csusing UnityEngine; using ChatdollKit; using ChatdollKit.Extension; using ChatdollKit.IO; using ChatdollKit.Model; public class AppMain : MonoBehaviour { private Chatdoll chatdoll; private ModelController model; private WakeWordListenerBase wakeWordListener; private void Awake() { chatdoll = gameObject.GetComponent<Chatdoll>(); model = gameObject.GetComponent<ModelController>(); // アイドル状態の定義 model.AddIdleAnimation("Default"); // 命令入力要求時のアクション=これが対話フローの「プロンプト」に相当 chatdoll.OnPromptAsync = async (user, context, token) => { var animatedVoiceRequest = new AnimatedVoiceRequest(startIdlingOnEnd: false); animatedVoiceRequest.AddVoiceTTS("どうしたの?", 0.3f); animatedVoiceRequest.AddAnimation("AGIA_Idle_angry_01_hands_on_waist"); await chatdoll.ModelController.AnimatedSay(animatedVoiceRequest, token); }; // ウェイクワード・キャンセルワードの検出時のアクション wakeWordListener = GetComponent<AzureWakeWordListener>(); if (wakeWordListener != null) { // user0123456789は適当なユーザーID。Gatebox実機から取得することも可 wakeWordListener.OnWakeAsync = async () => { await chatdoll.StartChatAsync("user0123456789"); }; wakeWordListener.OnCancelAsync = async () => { chatdoll.StopChat(); }; } } private void Start() { // ウェイクワードの監視を開始 wakeWordListener?.StartListeningAsync(); } }ざっくり説明すると、
- アイドル状態の振る舞い
- お願いの入力を促す「プロンプト」の発話と振る舞い
- ウェイクワードが呼ばれたときにチャットを開始する処理
- このスクリプトの最初のフレームの前にウェイクワードの監視を開始する処理
を定義しています。
おうむ返し処理の作成
あとで雑談できるようにしますが、一旦ここまでの動作確認のためにおうむ返しをする処理を作ります。以下のスクリプトを作成して3Dモデルに追加しましょう。対話フローの中における「レスポンス」を返す部分です。
ChatDialog.csusing System.Threading; using System.Threading.Tasks; using ChatdollKit.Dialog; public class ChatDialog : DialogProcessorBase { public override async Task<Response> ProcessAsync(Request request, Context context, CancellationToken token) { var response = new Response(request.Id); // リクエストの内容をおうむ返しに応答にセット response.AnimatedVoiceRequest.AddVoiceTTS(request.Text); return response; } }実行
ここまで来れば、あなたのお嫁さんはおうむ返しReadyにしておうむ返しLadyです。Unityの実行ボタンを押して、ウェイクワードで呼びかけてみましょう。「どうしたの?」という問いかけに続けて「こんにちは」と言えば「こんにちは」と、「愛してるよ」と言えば「愛してるよ」とおうむ返ししてくれるはずです。
雑談機能の組み込み
話しかけにしゃべって応答できるところまで確認できたので、今度は雑談できるようにするための処理を追加しましょう。
A3RTのAPIキーの入手
無償で利用できる雑談対話APIの中から、ここではリクルート テクノロジーズさんのA3RTの雑談APIをチョイスしてみました。ここからAPIキーを入手しましょう。多分すぐに発行していただけます。
雑談処理の作成
先ほど作成したChatDialogを以下のように書き換えます。
ChatDialog.csusing System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using ChatdollKit.Dialog; using ChatdollKit.Network; public class ChatDialog : DialogProcessorBase { private ChatdollHttp client; protected override void Awake() { base.Awake(); client = new ChatdollHttp(); } private void OnDestroy() { client?.Dispose(); } public override async Task<Response> ProcessAsync(Request request, Context context, CancellationToken token) { // レスポンスの準備 var response = new Response(request.Id); // 雑談APIの呼び出し var formData = new Dictionary<string, string>() { { "apikey", "YOUR_API_KEY" }, { "query", request.Text }, }; var a3rtResponse = await client.PostFormAsync<A3RTResponse>("https://api.a3rt.recruit-tech.co.jp/talk/v1/smalltalk", formData); // レスポンスへのデータの設定 response.AnimatedVoiceRequest.AddVoiceTTS((a3rtResponse?.results?[0]?.reply ?? string.Empty) + "。"); // 会話継続フラグを立てる context.Topic.ContinueTopic = true; return response; } // 雑談APIのレスポンスデータモデル class A3RTResponse { public int status { get; set; } public string message { get; set; } public List<A3RTResult> results { get; set; } } class A3RTResult { public float perplexity { get; set; } public string reply { get; set; } } }詳細な説明は割愛しますが、あなたが嫁に語りかけた言葉である
request.Text
をパラメータにセットした上で雑談APIを呼び出して、その戻り値を読み上げてもらうようにレスポンスにセットしています。実行
ウェイクワードで嫁の注意を引きつけたあと、何でもいいので話しかけてみましょう。噛み合うような噛み合わないような会話が続くはずです。おそらく夫婦の会話なんてだいたいこんなものでしょう。
会話を終わりにしたいときは、WakeWordListenerのCancel Wordsに登録したフレーズ「おしまい」と話しかけてみてください。Gatebox実機に召喚
皆さまお気づきかもしれませんが、実はここまではGatebox要素ゼロでした。
そしていよいよここで!PCの中の嫁を!!現実世界に召喚するときが来ました!!!
とはいえGateboxのチュートリアルと全く同じ手順になりますので、ここでは大まかな流れとTipsを紹介します。おおまかな流れ
- Gatebox SDKのスクリプトを3Dモデルにアタッチ
- Androidプロジェクトに切り替えた上、APIレベルを26(8.0 Oreo)に設定
- ビルドしてDeveloper Consoleからアップロード
- テスターに自身のアカウントを登録して、アプリの利用を登録
- Gatebox Device Managerでヒカリちゃんから嫁に切り替えてGateboxを再起動
ちょっとしたTips
- ShaderはPCとGatebox実機では見え方がだいぶ異なる場合があり、そのときは設定変更が必要
- Gatebox実機は解像度が低いのでPost ProcessingでAntialiasをかけるよとよい。種類はTemporal Anti-Aliasingが良さげ
- 背景はSkyboxではなく真っ黒とかにしたほうがホログラミックでいい感じになると思います。衣装が暗い色のモデルの場合は、スモークを炊くとか要工夫
嫁を育てるには
いくつかの観点でレベルアップに役立つヒントを置いておきます。このあたりはまたおいおい詳細を書いていくかもしれません。リクエストがあればご連絡ください。
見た目や振る舞いのレベルアップ
最も簡単なレベルアップとしては、アイドルアニメーションにバリエーションを持たせるというのがあります。
AppMain.cs// アイドル状態の定義 model.AddIdleAnimation("Default"); // 他のステートも追加 model.AddIdleAnimation("AGIA_Idle_calm_01_hands_on_back"); model.AddIdleAnimation("AGIA_Idle_brave_01_hand_on_chest");これらのステートがランダムに一定間隔で切り替わるので、ちょっと生き生き感がでてきます。また、
AppMain.csmodel.IdleFunc = async (token) => { 任意の処理 };とすることでChatdollKitの制約に縛られない自由でリッチな動きをさせることもできます。
このほか、プロンプトや対話応答内容は発話とアニメーション、表情を簡単に同期させることができますので、頑張ればそれなりにリッチな表現にすることができると思います。
animatedVoiceRequest.AddVoiceTTS("天気が知りたいの?", postGap: 0.5f); animatedVoiceRequest.AddAnimation("Default"); // 「天気が知りたいの?」と言い終わったあと、笑顔で1回頷いて「わかった」と言う animatedVoiceRequest.AddVoiceTTS("わかった", preGap: 0.5f, asNewFrame: true); animatedVoiceRequest.AddAnimation("nod_twice", "Upper Body"); animatedVoiceRequest.AddFace("Smile", 1.0f); // 「調べるから、ちょっと待ってて」と言いながら1秒間だけ右手を持ち上げて人差し指を立てる animatedVoiceRequest.AddVoiceTTS("調べるから、ちょっと待ってて", preGap: 0.3f, postGap: 1.0f, asNewFrame: true); animatedVoiceRequest.AddAnimation("right_hand_pointy_finger", duration: 1.0f, preGap: 1.1f); animatedVoiceRequest.AddAnimation("Default");声のレベルアップ
Azureのお姉さんも素敵なお声ですが、3Dモデルの見た目とのギャップ感は否めません。特定用途の嫁を作るときには事前に録音した音声素材を使うというのも手ですが、それに加えて、ChatdollKitはVoiceroid Daemonというツールに対応しています。つまり、VOICEROIDのお声でダイナミックにおしゃべりできるということです!
使い方は簡単で、この記事の手順でAzureTTSLoaderを追加するかわりにVoiceroidTTSLoaderを追加するだけです。もちろん、VOICEROIDやVoiceroid Daemonは事前に用意していただく必要がある他、VOICEROIDの利用規約を遵守する必要がありますのでご注意ください。
リクエストのレベルアップ
音声によるリクエストのほか、標準でQRコード読み取りと画像(カメラ)によるリクエストに対応しています。後日別の記事でご紹介していきたいと思います。
スキルのレベルアップ
今回は雑談のみでしたが、ChatdollKitは本格的なチャットボット開発に耐えうる構成をサポートしています。具体的には、発話の意図を解釈して、意図や文脈に応じてトピックを選んで対話を進めていく、といったことができます。こちらも詳細はまた別の記事でご紹介したいと思います。
さいごに
ここまで読んでくださってありがとうございました!この記事をきっかけにGateboxアプリの開発を始めてみようと思ってくださる方がいればとても嬉しいです。
この記事で使っているフレームワークChatdollKitはこれからも育てて参りますので、よろしければスターをいただけると大変励みになりますのと、さらに開発にご協力していただけるという方がいらっしゃいましたらGithubにIssue/PR投げていたただく or Twitter @uezochan までご連絡いただけると嬉しいです!!
- 投稿日:2020-07-08T21:43:37+09:00
Unityのwebcamtextureが遅すぎる問題の解決策
Unityのwebcamtextureが遅すぎる
webcamtextureで取得した映像がものすごく遅延するので,Python経由でWebカメラの映像を取得してみました
明らかに遅延減ってるし画質も良くなった気がします
気が向いたら加筆しますwebcamtextureで取得した映像がものすごく遅延するので,Python経由でWebカメラの映像を取得してみました
— さいんす(signs) (@signs0302) June 10, 2020
明らかに遅延減ってるし画質も良くなった気がしますね
左:Unity標準のwebcamtextureで取得した映像,右:PythonでFlaskサーバ立ててOpenCVで取得した画像をストリーミングした映像 pic.twitter.com/1IvTWKMX8Z
- 投稿日:2020-07-08T21:09:04+09:00
XR-1開発備忘録
概要
研究室に5台のXR-1が到着したので,開発メモを残す.
以前購入したときは,セットアップまでもたくさんの苦労があったが,今回は業者がやってくれたので割愛する.
(主にThunderboltの互換のせい)
XR-1が子供を産んで5匹になりました pic.twitter.com/652mpxn7h7
— さいんす(signs) (@signs0302) July 8, 2020VR機能テスト
- High Definition RP projectでプロジェクトを作成
- PackageManagerを使ってGithubからVarjo XR Pluginを導入(https://github.com/varjocom/VarjoUnityXRPlugin.git)
- Project Settingsを編集
- Main CameraにTracked Pose DriverをComponentとして追加
- Unityを実行,XR-1でサンプルシーンを視認可能なことを確認
MR機能テスト(VST機能)
AR表示
- 簡単なスクリプトを作成し,空のオブジェクトにアタッチ.オブジェクトは何でも良い.
StartMR.csusing System.Collections; using System.Collections.Generic; using UnityEngine; public class StartMR : MonoBehaviour { // Start is called before the first frame update void Start() { Varjo.XR.VarjoMixedReality.StartRender(); } // Update is called once per frame void Update() { } }
- MainCameraのBackground TypeをColorに変更
- MainCameraのBackground Colorを黒(0,0,0,0)に変更 でVST表示ができる.(SampleSceneではSky and Fog Volumeオブジェクトを非表示にするとわかりやすい)
とある物体だけVST表示
-以下のシェーダを作成し,適当なMaterial(例えばUnlit)にアタッチ
MR.shaderShader "Custom/MR" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct appdata { float4 vertex : POSITION; }; struct v2f { float4 pos : SV_POSITION; }; v2f vert(appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); return o; } half4 frag(v2f i) : SV_Target { return half4(0,0,0,0); } ENDCG } } }シェーダの参考サイト
(https://blog.applibot.co.jp/2017/09/01/tutorial-for-unity-3d-4/)
- Materialを適当なオブジェクトにアタッチ
例えばCubeにアタッチすると以下のようになります
(左:Unity画面,右:XR-1で見えている映像)カメラ映像取得
- カメラの映像を取得できれば色々できる.(というか,できないと自分の研究で使えない...)
- 公式リファレンスに何も書いていないので,色々試してみる
- デバイスマネージャには「USB Camera-OV580」と「USB Camera-VarjoOV580」表示される(VIVEフロントカメラとは異なる)
- XR-1起動中にカメラを叩くと以下のようになる
- カメラ映像は取得できなさそう...?
- XR-1の電源ケーブル抜くとカメラも停止
おまけ
- 新規プロジェクトでSteamVRをAssetStoreからimportして実行すると以下のようになってHMDが認識されない
- VRChatは動作したので,何か方法があるのかも
メモ
- Unity2019.3以降推奨っぽい.Unity XR SDKを使用したいらしい.
- Unity2019.4.2f1を使ってみる.ちなみに業者がインストールしてったのは2019.4.1f1
- またなにかわかったら更新します.
動いている様子
XR-1を触ってみた様子
— さいんす(signs) (@signs0302) July 8, 2020
色々と設定は必要だけど,動かすだけならそこまで難しくなさそう
ただし,Webカメラの映像を取得するためには色々苦労しそうな感じ
詳しくはさっき書いたQiita記事を見てくださいhttps://t.co/juFqnj8Oze pic.twitter.com/KHCDvltCLG追記(2020/07/09)
- HDRPではなく3Dでは動作しませんでした
- Unityちゃんを出現させてみた
- HDRP用にシェーダを新しく設定しないといけないみたい
- このサイトを参考にした(https://www.frenchdrop.com/detail?id=3798)
- できたのはいいけど,左目表示がおかしい?安定してない?
- カメラにアクセスするために,Thunderboltケーブルを抜き差しして見る
- カメラが動かなくなる...デバイスマネージャで1つのカメラしか認識されていない?
参考リンクまとめ
- 公式サイト(https://varjo.com/use-center/getting-started/)
- 開発用サイト(https://developer.varjo.com/)
- SDK ダウンロード(https://developer.varjo.com/downloads)
- Unity SDK(https://developer.varjo.com/docs/unity-xr-sdk/unity-xr-sdk)
- Unity Github(https://github.com/varjocom/VarjoUnityXRPlugin)
- MR関連の機能(https://varjo.com/use-center/get-to-know-your-headset/mixed-reality/)
- FAQ(https://varjo.com/use-center/troubleshooting_faq/)
- デモ用ソフト(https://varjo.com/downloads/)
- 投稿日:2020-07-08T15:42:22+09:00
自作音ゲーの譜面データについて悩む
結論
とりあえず今回はテキストデータと譜面データとして使用したいので↓の中から知っていて使いやすそうなcsvで対応させることにしました
.txt
.html
.htm
.xml
.bytes
.json
.csv
.yaml
.fnt
Unity テキストアセット前提
音ゲーはノーツと呼ばれる判定を音楽を聴きながらリズム良く押すことによって得点が加算されていきます
ノーツを呼び出すタイミングを記したファイルを譜面データと言います
譜面データにはノーツのタイミングの他にノーツの種類や、速度などを埋め込んだりしますタイミングについて
タイミングを呼び出す方法は2種類あると思います
時間指定か小節指定です
※他にもありそうだったらコメントください小節指定のjson
最初は小節指定のjsonファイルを作ろうと考えていました
notes{ [[ノーツの種類,ノーツのレーン,速度][ノーツの種類,ノーツのレーン,速度]]//1小節目 [ノーツの種類,ノーツのレーン,速度]...//2小節目 }のように生成しようとしていました
メリット
・小節ごとの管理が楽
デメリット
・bpmが変わる曲は作りにくい
何故使わなかったか
jsonファイルをforやforeachで回すのが難しかった
jsonは[key:value]のように値が存在しており
{notus: [key:value,key:value], [key:value,key:value], [key:value,key:value]}のように作ることができます
valueを取り出してノーツを生成します//jsonファイルの読み込み var textAsset = Resources.Load("譜面.json") as TextAsset; var jsonText = textAsset.text; JsonNode json = JsonNode.Parse(jsonText) //jsonを辞書に入れる Dictionary<string,object> dic_json = json["notes"].Get<Dictionary<string,object>>(); foreach (var notes in json["notes"]) { long note = notes["note"].Get<long>(); for (int i = 0; note > i; i++) //インスタンスからノーツを生成 } }※うろ覚え
これの悪い点はnote
に入っている総ノーツ数がずれるとノーツの呼び出しがされなくなること
また、foreachで変数に追加して呼び出すと[0:1,1:1,2:2]
のようにリストで出てくるので割とめんどくさい
そして、ここではJsonNodeを使ってますが、Unity標準のJsonUtilityを使うと型を作らないといけないので音ゲーのようなデータの最大量が変わるものには向いてません時間指定のCSV
csvは0行目に曲情報、その後ろにノーツ情報を追加しました
ノーツの情報の詳細はノーツの種類(番号),ノーツのレーン,ノーツが来る時間,ノーツの速度(元bpm* 基本的に1)メリット
・実装が簡単
・拡張性があるデメリット
・譜面制作の難易度が激ムズ
//ファイル読み込み csv_read("../譜面.csv"); music_name = csvDatas[0][0]; bpm = float.Parse(csvDatas[0][1]); all_notes = int.Parse(csvDatas[0][2]); offset = double.Parse(csvDatas[0][3]); //インスタンスをリストに追加 GameObject_all_notes.Add(new GameObject[]{ notes1, notes2, notes3, notes4, notes5 }); for (int i = 1; i < csvDatas.Count; i++) { _type = int.Parse(csvDatas[i][0]); _lane = int.Parse(csvDatas[i][1]); _time = float.Parse(csvDatas[i][2]); _speed = float.Parse(csvDatas[i][3]); Generate = GameObject_all_notes[int.Parse(csvDatas[i][0])][int.Parse(csvDatas[i][1])]; Generate.GetComponent<notes>().set_up_notes(_time, _speed); Instantiate(Generate, new Vector3(Generate.transform.position.x, Generate.transform.position.y, Generate.transform.position.z + (_speed * public_speed * 10) * _time), Quaternion.identity); }これは現在使っているコード(の簡略版)
こちらは割と拡張性もあり簡単のノーツを生成することができるのでよき
ただし、インスタンスを生成する際にノーツのスピードとタイミングを計算しないといけないのでそこだけ注意ついでにオブジェクトの加速度を切らないとだんだんズレます