Search Unity

Spawn a SortableDictionary at specific time

Discussion in 'Scripting' started by iKlikla, Feb 26, 2017.

  1. iKlikla

    iKlikla

    Joined:
    Jul 31, 2016
    Posts:
    3
    Hello fellow Unity devs,
    i am currently working on a Rhythm Game Project and need your help.

    I have hand-mapped all notes into a SortableDictionary and saved that.
    In my "Ingame" Scene I load the file and add the notes to a SortableDictionary again.
    I now have this Object:

    TIME (Time.time normalized), NOTE (1-5)

    What I now want to do is detect when a note should spawn and Instiate a NoteObject at the top of my screen. I have the problem to check if the current time matches a time in the SortableDictionary.

    My PlayManager
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System;
    5. using System.IO;
    6.  
    7. public class PlayManager : MonoBehaviour {
    8.  
    9.     public bool isPlaying = false;
    10.     public float playingTime = 0f;
    11.     public float playingStartedTime = 0f;
    12.     AudioSource audioSource;
    13.     SortedDictionary<float, float> notesTable;
    14.  
    15.     public void Start()
    16.     {
    17.         // Setup the file
    18.         Debug.Log("Loading Song: " + PlayerPrefs.GetString("selectedSong"));
    19.         audioSource = GetComponent<AudioSource>();
    20.         audioSource.clip = Resources.Load("Songs/" + PlayerPrefs.GetString("selectedSong")) as AudioClip;
    21.  
    22.         // Setup the notes
    23.         Debug.Log("Loading Song Notes: " + PlayerPrefs.GetString("selectedSong") + ".song");
    24.         notesTable = new SortedDictionary<float, float>();
    25.  
    26.         String fileName = "Assets/Resources/Songs/" + PlayerPrefs.GetString("selectedSong") + ".song";
    27.         if (File.Exists(fileName))
    28.         {
    29.             var sr = File.OpenText(fileName);
    30.             var line = sr.ReadLine();
    31.             while (line != null)
    32.             {
    33.                 try
    34.                 {
    35.                     String[] splitLine = line.Split("|".ToCharArray());
    36.                     splitLine[1] = splitLine[1];
    37.                     notesTable.Add(float.Parse(splitLine[0]), float.Parse(splitLine[1]));
    38.                 } catch(IndexOutOfRangeException ioore)
    39.                 {
    40.                     String[] splitVersion = line.Split("-".ToCharArray());
    41.                     Debug.Log("Using SONGNOTES Version: " + splitVersion[1]);
    42.                 }
    43.                 line = sr.ReadLine();
    44.             }
    45.  
    46.             // DEBUG OUTPUT ALL NOTES
    47.             foreach(KeyValuePair<float, float> note in notesTable)
    48.             {
    49.                 Debug.Log(note.Key + " - " + note.Value);
    50.             }
    51.         } else
    52.         {
    53.             Debug.Log("CRITICAL ERROR! Could not find Song file!");
    54.             return;
    55.         }
    56.  
    57.         // Start Countdown
    58.         StartCoroutine("startSong");
    59.     }
    60.  
    61.     public void Update()
    62.     {
    63.         if (isPlaying)
    64.         {
    65.             playingTime = Time.time - playingStartedTime;
    66.  
    67.             // DETECT NOTE AND SPAWN NOTEOBJECT
    68.         }
    69.     }
    70.  
    71.     public void startPlaying()
    72.     {
    73.         playingStartedTime = Time.time;
    74.         playingTime = 0;
    75.         isPlaying = true;
    76.         audioSource.Play();
    77.         Debug.Log("Started Playing at" + playingStartedTime);
    78.     }
    79.     public void stopPlaying()
    80.     {
    81.         playingStartedTime = Time.time;
    82.         isPlaying = false;
    83.         audioSource.Stop();
    84.         Debug.Log("Stopped Playing at " + playingStartedTime);
    85.     }
    86.  
    87.     IEnumerator startSong()
    88.     {
    89.         yield return new WaitForSeconds(1f);
    90.         Debug.Log("Play in 3 Seconds!");
    91.         yield return new WaitForSeconds(1f);
    92.         Debug.Log("Play in 2 Seconds!");
    93.         yield return new WaitForSeconds(1f);
    94.         Debug.Log("Play in 1 Second!");
    95.         yield return new WaitForSeconds(1f);
    96.         startPlaying();
    97.     }
    98. }
    99.  
    A sample song file
    Code (CSharp):
    1. SONGNOTES-1.0.0
    2. 2.435412|2
    3. 2.799766|4
    4. 3.314533|2
    5. 3.562937|4
    6. 3.81162|1
    7. 4.225603|2
    8. 4.739169|4
    9. 4.971102|2
    10. 5.23617|4
    11. 5.502206|1
    12. 6.263303|2
    13. 6.72717|4
    14. 7.240736|1
    15. 7.489878|4
    16. 7.737736|1
    17. 8.21817|5
    18. 9.278503|4
    19. 9.477352|1
    20. 9.560068|4
    21. 9.709745|1
    22. 9.842085|4
    23. 10.10677|1
    24. 10.45507|2
    25. 10.83601|4
    26. 11.26644|2
    27. 11.51497|4
    28. 11.74687|2
    29. 12.17819|1
    30. 12.77437|4
    31. 12.98937|1
    32. 13.23833|2
    33. 13.48637|4
    34. 14.19908|2
    35. 14.6792|4
    36. 15.24244|2
    37. 15.47437|4
    38. 15.73993|2
    39. 16.253|5
    40. 18.27414|4
    41. 18.62204|1
    42. 18.80433|4
    43. 19.01964|1
    44. 19.99707|4
    45. 20.26219|4
    46. 20.5272|4
    47. 20.79263|1
    48. 21.04077|2
    49. 22.44894|2
    50. 22.714|2
    51. 22.94594|2
    52. 23.19444|1
    53. 23.42637|2
    54. 23.9565|3
    55. 26.47464|4
    56. 26.69|3
    57. 26.9882|4
    58. 27.23677|3
    59. 28.16479|1
    60. 28.69457|2
    61. 28.95963|1
    62. 29.24129|2
    63. 30.23527|4
    64. 30.69944|1
    65. 31.22927|4
    66. 32.2067|5
    67. 32.68714|3
    68. 33.21727|5
    69. 34.31067|2
    70. 34.7414|1
    71. 35.20527|2
    72. 35.45382|1
    73. 35.75197|4
    74. 36.31524|1
    75. 36.79567|2
    76. 37.04417|4
    77. 37.30923|1
    78. 37.47509|2
    79. 38.2701|4
    80. 38.75084|2
    81. 39.24754|1
    82. 39.49606|2
    83. 39.82739|1
    84. 40.22497|4
    85. 41.28754|4
    86. 41.45305|2
    87. 41.53628|4
    88. 41.65185|2
    89. 41.75125|4
    90. 41.93348|2
    91. 42.13241|4
    92. 42.38078|1
    93. 42.74525|4
    94. 43.25882|2
    95. 43.47419|4
    96. 43.72268|1
    97. 44.26947|5
    98. 44.78295|4
    99. 45.04802|1
    100. 45.44562|2
    101. 45.66098|4
    102. 46.27395|4
    103. 46.73794|1
    104. 47.23491|4
    105. 47.41705|1
    106. 47.71532|4
    107. 48.17912|5
    108. 50.29983|3
    109. 50.82986|3
    110. 51.32711|4
    111. 51.57538|4
    112. 51.80722|4
    113. 52.23795|1
    114. 52.80122|4
    115. 53.04972|1
    116. 53.26508|4
    117. 53.53015|1
    118. 53.76208|2
    119. 54.02752|4
    120. 54.27565|1
    121. 54.50758|2
    122. 54.70639|4
    123. 55.05436|2
    124. 55.28622|4
    125. 55.36905|2
    126. 55.63412|4
    127. 56.03193|1
    128. 56.28022|5
    129. 58.28479|2
    130. 58.78178|1
    131. 59.26221|2
    132. 59.52733|1
    133. 59.77579|4
    134. 60.25622|2
    135. 60.85262|2
    136. 61.08455|4
    137. 61.33305|1
    138. 61.54847|2
    139. 62.29394|4
    140. 62.82405|1
    141. 63.32105|4
    142. 63.53642|1
    143. 63.76835|2
    144. 64.29856|5
    145.  
     
  2. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Code (CSharp):
    1. using System.Linq;
    2. private float currentTime = 0;
    3. public void Update()
    4.     {
    5.         if (isPlaying)
    6.         {
    7.             playingTime = Time.time - playingStartedTime;
    8.             var kvp = notes.Where(x => x.Key < playingTime).LastOrDefault();
    9.             if (kvp != null)
    10.             {
    11.                 if (kvp.Key != currentTime)
    12.                 {
    13.                       currentTime = kvp.Key;
    14.                       InstantiateNote(kvp.Value);
    15.                 }
    16.            }
    17.         }
    18.     }
    19. public void InstantiateNote(float value)
    20. {
    21.       // Code here to spawn a note
    22. }
    23. public void startPlaying()
    24. {
    25.        currentTime  = 0;
    26.        //rest of the code
    27. }
    28.  
    29.  
    I would also add a final time code to all your songs with a note value of -1. Then InstantiateNote can call stopPlaying when it receives a -1 for a note

    Basically that LinQ line searches through the dictionary for all the notes that are less than currentTime. Find the last one. Checks if its different than our stored last currentTime. If it is we hit a new note so we instantiate it and update our currentTime (so we don't keep spawning the same note over and over)