見出し画像

ダンスゲーを作りたい#14 Animationの速度を曲に合わせるその1

前回一時停止でちらっとお見せしたこちら

animator.SetFloat("MoveSpeed", 0.0f); //一時停止

何をしているかと申しますと、

アニメーションの再生速度を0にしろよ=いったん止めろ

という命令になって一時停止なわけです。

つまり、本質的には

MoveSpeedという変数を勝手に作って、再生速度はここを参照しろよという設定をAnimationController内のステイトに対して行っているので

MoveSpeedに値を入れればその速さで動いてくれるという状態です。

この値さえ計算すればOKですね。

まず曲再生

以前作った曲を再生するスクリプトを引っ張り出してきました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System ;
using System.IO;

//曲データのクラスです。
public class MusicData
{
   public float BPM;
   public string Maker;
   public Dictionary<string, float>[] score;
   
}
//現在再生中の曲情報を扱うクラスです
public class NowMusic{
   public MusicData Data;
   public string Name;
   public AudioClip clip;
   
}

public class Music_manager : MonoBehaviour
{
   //現在再生中の曲データです
   public NowMusic nowmusic;
   //現在再生中の曲オブジェクトです
   static GameObject AudioObj;
   //現在再生中のオーディオソースです
   static AudioSource AudioSource;

   //managerをセットする
   //ゲーム開始時に呼び出します。
   //名前を入れて呼び出すと上記インスタンスに係る曲のセッティングをすべてやってくれます
   public void StartMusicManager(string musicname ){
       Create_music();
       nowmusic=new NowMusic();
       nowmusic.Name=musicname;
       
       
       nowmusic.clip = set_music(nowmusic.Name);
       nowmusic.Data=getData_music(nowmusic.Name);
   }
   /*以下メイン機能関数軍です*/
   //再生を開始します
   public void play_music(){
       AudioSource.clip = nowmusic.clip;
       AudioSource.Play();
   }
   //現在の曲の再生時間を返します
   public float getTime_music(){
       return AudioSource.time;
   }
   //nullで呼び出すと現在何拍目かを返します
   //timeを入れると指定時間が何拍目かを返します
   public int getBeatNum_music(float time){
       if(time==null){
           return (int)((nowmusic.Data.BPM*time)/60)+1;
       }
       return (int)((nowmusic.Data.BPM*AudioSource.time)/60)+1;
   }
   //nullで呼び出すと呼び出された時点でscore計算範囲内か返します
   //timeを入れると指定時間がscore計算範囲内か返します
   public bool NowisOnBeat_music(float time){
       if(time==null){
           float nowtime=AudioSource.time;
           double mintime=(((60/(double)nowmusic.Data.BPM)*getBeatNum_music(nowtime))-((60/(double)nowmusic.Data.BPM)*(4/10)));
           double maxtime=(((60/(double)nowmusic.Data.BPM)*getBeatNum_music(nowtime))+((60/(double)nowmusic.Data.BPM)*(4/10)));
           if(mintime<nowtime&&maxtime>nowtime){
               return true;
           }
           return false;
       }else{
           double mintime=(((60/(double)nowmusic.Data.BPM)*getBeatNum_music(time))-((60/(double)nowmusic.Data.BPM)*(4/10)));
           double maxtime=(((60/(double)nowmusic.Data.BPM)*getBeatNum_music(time))+((60/(double)nowmusic.Data.BPM)*(4/10)));
           if(mintime<time&&maxtime>time){
               return true;
           }
           return false;
       }
       
   }
   //Resource.Music下のファイル名一覧を返します
   public string[] getNamelist_music(){
       string[] names=Directory.GetFiles(@"Assets/Resources/Music", "*.mp3");
       for(int i=0 ;i<names.Length;i++){
               names[i]=names[i].Replace("Assets/Resources/Music\\","").Replace(".mp3","");
       }
       return  names;
   }
   
   
   //曲名から曲データを取得する関数
   public MusicData getData_music(string name){
       string inputString = Resources.Load<TextAsset>("Music/"+name).ToString();
       return JsonUtility.FromJson<MusicData>(inputString);
   }
   //曲名を入れるとクリップを作ってくれます
   public AudioClip set_music(string MusicName){
       string path="music/"+MusicName;
       return Resources.Load<AudioClip>(path);
   }
   
   
//以下機能補助関数軍
   void Create_music(){
       //audioオブジェクトがあるかだけチェックする
       AudioObj = GameObject.Find("Audio");
       //なければ
       if (AudioObj == null)
       {
           //オブジェクトを生成
           AudioObj = new GameObject("Audio");
           //これやるとヒエラルキーに表示されなくて便利っていう記述
           AudioObj.hideFlags = HideFlags.HideAndDontSave;
       }
       //audiosourceコンポーネントも上記同様取得する
       AudioSource = AudioObj.GetComponent<AudioSource>();
       if (AudioSource == null)
       {
           AudioSource = AudioObj.AddComponent<AudioSource>();
       }
   }

}

ものすごい長いですね。もう内容なんかは忘れてます。

簡単に言うと曲名を受け取ったら、Resourceフォルダから曲ファイルと曲データを再生可能にしてくれるっていう感じのスクリプトだった気がします。

曲名一覧が取得出来たりもするので、実質フォルダにファイルを置くだけで曲の追加ができることを目指したスクリプトです。

詳しくはコード読んでいただくとして、今はとりあえず曲の再生と曲のBPM取得ができればいいので、

適当なオブジェクトにつけて、呼び出したいスクリプトから、

MusicManager=GetComponent<Muisc_manager>()とでもやって取得し、

MusicManager.StartMuiscManager(曲名)で初期化すれば、

MusicManager.play_music() で曲を再生。

MusicManager.nowmusic.Data.BPM にはBPMが格納されている。

ってとこだけでOKです。

ちなみに曲ファイルと曲データのファイルはAssets/Resource/Musicに入れといてください。

曲データの中身は

{
   "BPM":85,
   "Maker":"Marron Fields Production"
}

って書いてあるだけのjsonファイルです。

この先データが増えたら受け取るクラスも拡張すればいい感じですね。

今回は呼び出し元として以前作った各種manager達も併せて、ゲームの進行を管理するGameManagerスクリプトを作成しました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Game_manager : MonoBehaviour
{
   Motion_manager motion;
   Input_manager input;
   Model_manager model;
   Userdata_manager userdata;
   Music_manager music;
   
   void Start(){
       motion = GetComponent<Motion_manager>(); 
       input = GetComponent<Input_manager>(); 
       model = GetComponent<Model_manager>(); 
       userdata = GetComponent<Userdata_manager>(); 
       music = GetComponent<Music_manager>(); 
       
      
       userdata.StartUserDataManager();
       music.StartMusicManager("Closed_Case");
       model.StartModelManagaer("testmodel1");
       motion.StartMotionManager();
       input.StartInputManager();
       music.play_music();
       Debug.Log(music.nowmusic.Data.BPM);
   }
}

musicがMusi_managerですね。

これで▶押すと曲が流れて(gifなので曲ないですがpcからは流れてます)

BPMがコンソールに出てるので取得できることもわかりました。

画像1

長くなってしまったので、続きは次回にしましょう。

ちなみに昨日は競プロだったんですが、なんか撃沈して悲しい気持ちです。

ではまた。



この記事が気に入ったらサポートをしてみませんか?