- Home /
Music and spawning times not synchronized
Hello there, I'm making a 2d mobile rhythm game, in which you are this player in the middle of the screen that must defeat enemies spawning from the right and left of the screen on the beat of a song.
something like this: https://youtu.be/LAgG6Xn6dv4
The problem is that when I transition from the play menu scene to the game scene and even when I build the game to my mobile device, there is a slight delay between the spawning times and the music beat.
something like this: https://youtu.be/eRF2EP1b-Ig
My question is: How do I make sure that the song and spawning times remain synchronized when transitioning from one scene to the game scene?
This is one of my first posts on Unity Answers, so if I did any mistakes in writing this, please forgive me and tell me how to do it better in the future.
These are the scripts that I use:
EnemiesManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemiesManager : MonoBehaviour
{
public Transform leftSpawnPoint;
public Transform rightSpawnPoint;
public GameObject player;
public Animator playerAnimator;
public GameObject[] enemies;
public LevelScriptable level;
public InputQueue queue;
int spawnIndex;
float levelTime;
float levelStartTime;
private Vector3 left, right;
List<Enemy> spawnedEnemies;
void Start ()
{
levelStartTime = Time.fixedTime;
levelTime = Time.fixedTime;
spawnIndex = 0;
spawnedEnemies = new List<Enemy>();
left = new Vector3(-1, 1, 1);
right = new Vector3(1, 1, 1);
}
void SpawnEnemy(LevelScriptable.Enemy enemy)
{
Vector3 spawnPosition;
if (enemy.zone == LevelScriptable.Zone.Left)
spawnPosition = leftSpawnPoint.position;
else
spawnPosition = rightSpawnPoint.position;
GameObject newEnemy = Instantiate(enemies[(int)enemy.type], spawnPosition, Quaternion.identity);
newEnemy.GetComponent<Enemy>().Initialize(enemy.zone, enemy.type, enemy.speed, this);
spawnedEnemies.Add(newEnemy.GetComponent<Enemy>());
}
private void FixedUpdate()
{
if (spawnIndex >= level.enemies.Count)
return;
if (level.enemies[spawnIndex].time <= levelTime)
{
SpawnEnemy(level.enemies[spawnIndex]);
spawnIndex++;
}
levelTime = Time.fixedTime - levelStartTime;
}
private void Update()
{
while(queue.inputs.Count != 0)
{
GestureDetector.TouchInfo input = queue.inputs[0];
if ((int)input.zone == 0)
player.transform.localScale = left;
else player.transform.localScale = right;
if ((int)input.type == 0 || (int)input.type == 2)
playerAnimator.Play("Tap");
else if ((int)input.type == 1)
playerAnimator.Play("Swipe");
for (int i = spawnedEnemies.Count - 1; i >= 0; i--)
{
Enemy curEnemy = spawnedEnemies[i].GetComponent<Enemy>();
if ((int)curEnemy.zone == (int)input.zone && (int)curEnemy.type == (int)input.type)
{
if (curEnemy.isKillable)
{
KillEnemy(curEnemy);
break;
}
}
}
queue.inputs.RemoveAt(0);
}
}
public void KillEnemy(Enemy enemy)
{
spawnedEnemies.Remove(enemy);
Destroy(enemy.gameObject);
}
}
AudioManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(AudioSource))]
public class AudioManager : MonoBehaviour
{
public AudioSource audio;
void Start()
{
audio = GetComponent<AudioSource>();
audio.PlayDelayed(0);
Debug.Log("started");
}
}
SceneLoader.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class SceneLoader : MonoBehaviour
{
private bool loadScene = false;
[SerializeField]
private int scene;
[SerializeField]
private Text loadingText;
public void Play()
{
if (loadScene == false)
{
loadScene = true;
loadingText.text = "Loading...";
// ...and start a coroutine that will load the desired scene.
StartCoroutine(LoadNewScene());
}
}
void Update()
{
// If the new scene has started loading...
if (loadScene == true)
{
// ...then pulse the transparency of the loading text to let the player know that the computer is still working.
loadingText.color = new Color(loadingText.color.r, loadingText.color.g, loadingText.color.b, Mathf.PingPong(Time.time, 1));
}
}
IEnumerator LoadNewScene()
{
yield return new WaitForSeconds(0);
// Start an asynchronous operation to load the scene that was passed to the LoadNewScene coroutine.
SceneManager.LoadSceneAsync(scene);
}
}
Thanks for the help, Andy
Answer by digipaul · Sep 29, 2018 at 08:51 AM
Unitys AudioSource thing has a time field which tells you how long the sound has been playing in seconds. Maybe you should use that to synchronize the enemies spawning.
So the spawning times should relate to the song playing time, and not to the scene playing time?