快速エンジニア

駆け出しエンジニア、雑記を書く。Unity多め

Unityで音ゲーつくる ノーツの判定実装

こんにちは、ノーツの判定を実装しました。
基本的にタップ処理はEventTriggerに「Pointer Up」「Pointer Down」を登録してコールするメソッドをセットして呼び出します。
判定ゾーンは2つなので2つ分セットします。
f:id:tantakotako:20210123211223p:plain

用意した判定の種類の以下の6つです。Noneはノーツが来ていないときに押された場合の判定です。(無くてもいいかも)

public enum JudgementType
{
    None,
    Miss,
    Perfect,
    Great,
    Good,
    Bad
}

また、生存ノーツ用のリストを用意しておき、ノーツを生成した時に格納しておきましょう。それを時間順(beatBegin)に並べ一番先頭に来たノーツを次に来るノーツとして設定します。LinQを使うと取り出しやすいです(最近までリンキューと読んでいた)。

次のノーツが判定ゾーンと重なる時間は拍と秒数の変換により分かっている(secBegin - CurrentSec)のでそれと判定ゾーンをタップした時間との差で判定を決めます。

void JudgementType GetJudgementType(float differenceSec){
        if(differenceSec <= 0.05f)
        {
            return JudgementType.Perfect;
        }
        else if(differenceSec <= 0,10f)
        {
            return JudgementType.Great;
        }
        else if(differenceSec <= 0.20f)
        {
            return JudgementType.Good;
        }
        else if (differenceSec <= 0.30f)
        {
            return JudgementType.Bad;
        }
        else
        {
            return JudgementType.None;
        }
}

しかし、これだけだと全くタップしなかったorタップがBadよりも遅かったときのMiss判定が実装されていません。
「全くタップしなかった」と「タップがBadよりも遅かった」は同義とし、その判定をノーツごとのUpdate()で行います。

void Update(){
    if (noteProperty.secBegin - PlayerController.CurrentSec < -JudgementManager.JudgementZone[JudgementType.Bad])
    {
         //ミス処理
    }
}

ミス処理にはノーツのオブジェクトを消去する処理を書きます。生存ノーツ用のリストからも消去します。
成功処理はタップした時に呼び出すメソッドから先ほどのGetJudgementTypeを取得し、None以外の場合で同じくノーツを消去する処理を書きます。効果音や後ほど紹介するスコア計算などもここで呼び出すようにしています。

シングルノー

特筆する点はありません。タップ処理がそのままシングルノーツの判定実装になります。

ロングノーツ

始点と終点を考える必要があります。終点は指を離した時なので「Pointer Up」に登録したメソッドを呼びます。中身は同じような処理を書きます。ただ、押しっぱなしにしているかを判断するために処理中フラグを用意しておき、押した際に処理中フラグをtrueに、離した際にfalseにしています。そのため、先ほどのミス処理では処理中フラグがtrueの時(ずっと押しっぱなしだった)とfalseの時(押してすらいない、もしくは離すのが早い)の2通りの処理を書く必要があります。また、処理中フラグがtrueの時にノーツの色を変えたり始点を判定ゾーンに合わせたりするとプレイした時に納得のいく感触が得られるかと思います。

フリックノーツ

ロングノーツと同じく押した際と離した際の処理を書く必要があります。押した際にmousepositionで座標を保存しておき、離した際にその座標から一定数動いているかどうかでフリック成功かを判断します。差は0.2fくらいがちょうどいいと思います。もし向きを指定したい場合はx軸だけ、もしくはy軸だけに限定しましょう。

 bool canFlicked = flickDifference <= Mathf.Abs(flickStartPos.x - flickEndPos.x) ||
                flickDifference <= Mathf.Abs(flickStartPos.y - flickEndPos.y);