#17 Sonic Evolution: Dance Monkey Edition (Version 2)

ยท

4 min read

Introduction:

Welcome back, rhythm aficionados! In this 17th edition of our Beat Saber VR blog series, we're cranking up the beats with a revamped version of our Cube Spawner script. Brace yourselves for a deep dive into the beats array, tailored for the mesmerizing track "Dance Monkey." Let's explore how to synchronize our game with the infectious rhythm of this chart-topping song.

Step 1: Understanding the Beats Array:

  1. Beat Array Overview:

    • The beats array encapsulates precise timestamps representing beats in the "Dance Monkey" track.

         public float[] beats = {
                    0.191377f, 0.510339f, 0.820188f, 1.120924f, 1.412546f,
            1.740622f, 2.041357f, 2.351206f, 2.560810f, 2.952678f,
            3.253413f, 3.572375f, 3.873111f, 4.173847f, 4.501922f,
            4.802658f, 4.994035f, 5.404129f, 5.704865f, 6.005601f,
            6.351902f, 6.643525f, 6.926034f, 7.244996f, 7.454600f,
            7.846468f, 8.165430f, 8.484392f, 8.776014f, 9.085863f,
            9.404825f, 10.051863f, 10.981521f, 11.843864f, 12.484898f,
            13.393029f, 13.660691f, 14.324055f, 14.789568f, 15.842695f,
            16.598199f, 17.346072f, 18.277097f, 19.192860f, 19.803368f,
            20.734394f, 21.535686f, 22.191983f, 23.161165f, 24.130347f,
            24.626385f, 27.175258f, 29.685974f, 30.319377f, 30.952779f,
            31.998275f, 35.218707f, 39.499898f, 40.133300f, 40.797228f,
            41.911406f, 44.376334f, 49.298559f, 49.924330f, 50.534838f,
            51.137715f, 52.358732f, 53.572118f, 54.800766f, 56.006520f,
            57.280957f, 58.463817f, 59.081957f, 59.692465f, 60.089296f
            };
      
  2. Timestamps Exploration:

    • Each entry in the array corresponds to a specific timestamp where a cube should be spawned.
  3. Adjustments and Additions:

    • Customize the array based on the rhythm of "Dance Monkey." Add or modify timestamps to align with the song's beats.

Step 2: Script Breakdown:

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

public class CubeSpawner : MonoBehaviour
{
    public GameObject cube;
    public AudioClip song;

    public AudioSource audioSource;

    public Vector3 spawnOffset = new Vector3(0.0f, 1.5f, 1.0f);
    public float xRange = 0.8f;
    public float yRange = 0.3f;
    public float minDistance = 12f;
    public float minSpawnDelay = 1.5f;
    public float maxSpawnDelay = 2.0f;

    public float beat = 60 / 105;
    private float timer;
    private int beatIndex = 0;

    private float lastSpawnTime;
    private bool canSpawn = true;

    public float endTime = 60f;

    public float[] beats = {
            0.191377f, 0.510339f, 0.820188f, 1.120924f, 1.412546f,
    1.740622f, 2.041357f, 2.351206f, 2.560810f, 2.952678f,
    3.253413f, 3.572375f, 3.873111f, 4.173847f, 4.501922f,
    4.802658f, 4.994035f, 5.404129f, 5.704865f, 6.005601f,
    6.351902f, 6.643525f, 6.926034f, 7.244996f, 7.454600f,
    7.846468f, 8.165430f, 8.484392f, 8.776014f, 9.085863f,
    9.404825f, 10.051863f, 10.981521f, 11.843864f, 12.484898f,
    13.393029f, 13.660691f, 14.324055f, 14.789568f, 15.842695f,
    16.598199f, 17.346072f, 18.277097f, 19.192860f, 19.803368f,
    20.734394f, 21.535686f, 22.191983f, 23.161165f, 24.130347f,
    24.626385f, 27.175258f, 29.685974f, 30.319377f, 30.952779f,
    31.998275f, 35.218707f, 39.499898f, 40.133300f, 40.797228f,
    41.911406f, 44.376334f, 49.298559f, 49.924330f, 50.534838f,
    51.137715f, 52.358732f, 53.572118f, 54.800766f, 56.006520f,
    57.280957f, 58.463817f, 59.081957f, 59.692465f, 60.089296f
    };

    void Start()
    {
        lastSpawnTime = Time.time;
        audioSource = GetComponent<AudioSource>();
        float delay = 9.3f;
        Invoke("StartSongPlayback", delay);
    }

    void StartSongPlayback()
    {
        audioSource.clip = song;
        audioSource.Play();
    }

    void Update()
    {
        if (beatIndex >= beats.Length)
        {
            canSpawn = false;
        }
        else if (timer > beats[beatIndex])
        {
            if (canSpawn)
            {
                SpawnCube();
            }

            beatIndex++;

            timer = 0f;
        }

        timer += Time.deltaTime;

        if (Input.GetKeyDown(KeyCode.Q) || OVRInput.GetDown(OVRInput.RawButton.B))
        {
            ToggleSpawn();
        }

        endTime = Mathf.Max(endTime, beats[beats.Length - 1]);
    }

    void SpawnCube()
    {
        float x = UnityEngine.Random.Range(-xRange, xRange);
        float y = UnityEngine.Random.Range(-yRange / 2.0f, yRange);

        Vector3 spawnPos = transform.position - new Vector3(0.0f, 0.0f, spawnOffset.z);
        Vector3 directionToPlayer = (transform.position - spawnPos).normalized;
        Vector3 initialPos = new Vector3(x, y, 0.0f) + directionToPlayer * minDistance;

        GameObject spawnedCube = Instantiate(cube, initialPos, Quaternion.identity);
        spawnedCube.transform.Rotate(transform.forward, 90 * UnityEngine.Random.Range(0, 4));
        Rigidbody rbCube = spawnedCube.GetComponent<Rigidbody>();
        rbCube.useGravity = false;

        float mag = 1.0f;
        Vector3 addedVelocity = -directionToPlayer * mag;

        rbCube.AddForce(addedVelocity, ForceMode.VelocityChange);

        float scale = UnityEngine.Random.Range(0.1f, 0.25f);
        spawnedCube.transform.localScale = new Vector3(scale, scale, scale);

        lastSpawnTime = Time.time;
    }

    public void ToggleSpawn()
    {
        canSpawn = !canSpawn;
    }
}

Step 3: Integration in Unity:

  1. Project Setup:

    • Open the Project

    • Import the "Dance Monkey" track into the project assets.

  2. Cube Spawner Component:

    • Attach the CubeSpawner script to an empty GameObject in the scene.

  3. Adjust Parameters:

    • Fine-tune parameters such as spawnOffset, xRange, yRange, and others to suit your level design.
  4. Run the Scene:

    • Hit play and witness cubes dancing to the beats of "Dance Monkey."

The code for this version is in the Version-2 branch, here is the link: https://github.com/Akash3121/Beat-Saber-Game-VR/tree/Version-2

Conclusion:

You've successfully upgraded your Beat Saber experience with the pulsating vibes of "Dance Monkey." Stay tuned for the next chapter, where we'll explore advanced interactions and elevate our VR rhythm game to new heights! Keep the beats flowing!

Happy Coding :)

ย