質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

3095閲覧

Unity リズムゲームで時間のズレをなくしたい

GoF

総合スコア13

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2019/08/16 06:33

MusicEngineとDOTweenを使ってリズムゲームを作ろうとしています。
2拍ごとにブロックがジャンプし、ブロックが着地する直前にスペースキーを押して、スコアが増えるごとに速くなる内容なのですが、

C#

1 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using DG.Tweening; 6 7public class test : MonoBehaviour 8{ 9 10 public int BPM = 90; // BPM 11 private float totalTime; // 2拍の秒数 12 private float countTime = 0; // 2拍の秒数 13 private float countTimeAbout = 1.3f; // 通常の速度でだいたいの着地までの秒数 14 private float countTimeOver = 0.2f; // 猶予 15 private float countTimeResult = 0; 16 private int speedlevel = 1; //BPMが上がるごとに着地の秒数が変わるため、猶予を短くしないように猶予時間にこの値をかける 17 private bool gamestart = false; // スタート判定 18 private bool IsOK = true; // タイミングよく押せているか 19 private bool IsOh = false; // 着地の瞬間押していなかった状態 20 private float random = 0; //一定スコアを行った場合BPMをランダムにする判定 21 22 private int CurrentBeat = 0; // 拍数 23 24 static public int score = 0; // スコア 25 26 public AudioClip audioClip1; 27 private AudioSource audioSource; 28 29 // Start is called before the first frame update 30 void Start() 31 { 32 // オーディオを読み込む 33 audioSource = gameObject.GetComponent<AudioSource>(); 34 audioSource.clip = audioClip1; 35 36 totalTime = (120f / (float)Music.CurrentSection.Tempo); // 2拍の秒数 37 38 gamestart = false; // 起動時ゲームが始まらないようにする 39 40 } 41 42 // Update is called once per frame 43 void Update() 44 { 45 46 if (gamestart) // ゲーム開始時2拍の秒数を測る 47 { 48 countTime += Time.deltaTime; // 2拍の秒数 49 countTimeResult = countTimeAbout - (countTimeOver * speedlevel); // 通常の着地秒数- (猶予時間 x レベル) 50 } 51 52 if (countTime >= countTimeResult && Input.GetKeyDown(KeyCode.Space)) // 着地する直前にスペースキーを押すとOK判定 53 { 54 IsOK = true; 55 IsOh = false; 56 } 57 58 59 60 if (Music.IsJustChangedBeat()) 61 { 62 //Debug.Log(CurrentBeat); 63 if (CurrentBeat == 0 || CurrentBeat == 2) { // 0拍目、2拍目の時に動く 64 score++; 65 Debug.Log(score); 66 67 // 一定のスコアの時BPM、ピッチ、レベルを上げる 68 69 if (test.score >= 10 && test.score <= 19) 70 { 71 Music.CurrentSection.Tempo = 99; 72 audioSource.pitch = 1.1f; 73 speedlevel = 2; 74 75 } 76 77 if (test.score >= 20 && test.score <= 29) 78 { 79 Music.CurrentSection.Tempo = 116; 80 audioSource.pitch = 1.3f; 81 speedlevel = 3; 82 } 83 84 if (test.score >= 30 && test.score <= 39) 85 { 86 Music.CurrentSection.Tempo = 134; 87 audioSource.pitch = 1.5f; 88 speedlevel = 4; 89 } 90 91 if (test.score >= 40 && test.score <= 49) 92 { 93 Music.CurrentSection.Tempo = 151; 94 audioSource.pitch = 1.7f; 95 speedlevel = 5; 96 } 97 98 if (test.score >= 50) 99 { 100 Music.CurrentSection.Tempo = 171; 101 audioSource.pitch = 1.9f; 102 speedlevel = 6; 103 } 104 105 totalTime = (120f / (float)Music.CurrentSection.Tempo); // 飛ぶ時間 106 if (!IsOK) // 着地するまでにスペースキーを押していなかったらフラグを立てる 107 { 108 IsOh = true; // スペースキーを押すのがおそい判定のフラグを立てる 109 } 110 IsOK = false; 111 countTime = 0; // タイマーのリセット 112 this.gameObject.GetComponent<Transform>().DOJump // ブロックが飛ぶ動作 113 ( 114 new Vector3(0, 0, 0), // 自分の座標は変えない 115 3f, // 飛ぶ高さ 116 1, //飛ぶ回数 117 totalTime // 飛んでいる時間(2拍分) 118 ).SetRelative().SetEase(Ease.Linear); // 相対座標、等速 119 } 120 121 CurrentBeat++; // 現在の拍のカウント 122 if (CurrentBeat == 4) // 4になったら0にする 123 { 124 CurrentBeat = 0; 125 } 126 } 127 128 if (!IsOK && 0 < countTime && IsOh) // 着地までに押していなかった場合 129 { 130 131 //Destroy(gameObject); 132 IsOK = false; 133 IsOh = false; 134 } 135 136 if (0.1f < countTime && countTime < countTimeResult && Input.GetKeyDown(KeyCode.Space) && !IsOh) //押すタイミングが早かった場合 137 { 138 //Destroy(gameObject); 139 IsOK = false; 140 } 141 142 if (Input.GetKeyDown(KeyCode.Space) && !gamestart) // スタート時もう一度クリックしてもリセットしないようにする 143 { 144 audioSource.Play(); 145 gamestart = true; 146 IsOK = true; 147 IsOh = false; 148 } 149 150 } 151} 152

コードが汚くて申し訳ないです。曲はBPM=90です。
一定のスコアでAudioSource.Pitchを上げてBPMは予め調べた数字をまた代入し直しています。

解決したいところ

BPMが早くなると飛ぶ時間(totalTime)を変えているのですが、ブロックの座標がだんだん上に行ってしまいます。パソコンの性能でtotalTimeがズレるのはわかったのですが、その解決方法がわかりません。どうしたら時間のズレを無くせますか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

試行錯誤したところ、Music.IsJustChangedBeat()の条件に合う瞬間にDOjumpのtotalTimeが
間にあう時とあわない時があるので、SequenceにしてPause()をかけ、それをvoidにいれ、
飛ぶ座標の位置をtransform.positionで指定してから関数を呼び出しをしてRestart()をした結果
うまくいきました。

C#

1 2this.gameObject.transform.position = new Vector3(0, CurrentPosY, 0); 3Jump(); // void Jump()にDOJumpのコードをいれる(SequenceにしてPause()をかけとく) 4sequence.Restart();

このコードの状態でtotalTimeがMusic.IsJustChangedBeat()よりも超えた場合は
瞬間にCurrentPosYに移動するので、違和感がでたのでDOJumpはやめてDOMoveで緩急がついた
ジャンプにしました。

投稿2019/08/20 13:28

GoF

総合スコア13

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

直感ですが、countTime=0がおかしいですね
ここは端数を捨てていい場所ではないはずです

0.2秒、0.4秒後にブロックがあって0.21秒目に0.2秒のブロックを処理した場合
次のブロックは0.2秒後ではなく、0.19秒後です
この誤差が蓄積しているように思います

投稿2019/08/16 10:27

izmktr

総合スコア2856

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

GoF

2019/08/20 13:32

countTimeに端数を加算したところ、誤差なく押すタイミングの判定ができるようになりました。 回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問