ObjectHandler.cs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System.Threading.Tasks;
  5. using CSVReader;
  6. using Logger;
  7. using System.Collections.Concurrent;
  8. using System.Linq;
  9. namespace ObjectScripts
  10. {
  11. public class ObjectHandler : AbstractObjectHandler
  12. {
  13. ///<summary>
  14. /// Dictionary to keep track of every DataObject.
  15. /// <para>(ObjectID,DataObject)</para>
  16. ///</summary>
  17. public Dictionary<int, DataObject> DataObjectDictionary;
  18. ///<summary>
  19. /// Dictionary for Objects that need to be created.
  20. ///</summary>
  21. private Dictionary<int, InputObject> ObjectsToCreate;
  22. ///<summary>
  23. /// HashSet filled with Objects that need to be deleted
  24. ///</summary>
  25. private HashSet<DataObject> ObjectsToDelete;
  26. ///<summary>
  27. /// how Long an object can live without an update.
  28. ///</summary>
  29. public float TTL = 10f;
  30. ///<summary>
  31. /// Dictionary to keep track of every Sensor.
  32. /// <para>(SensorID,SensorGameobject)</para>
  33. ///</summary>
  34. public Dictionary<int, GameObject> SensorList { get; set; }
  35. void Start()
  36. {
  37. Forward = true;
  38. ObjectDictionary = new Dictionary<int, GameObject>();
  39. ObjectsToCreate = new Dictionary<int, InputObject>();
  40. ObjectsToDelete = new HashSet<DataObject>();
  41. DataObjectDictionary = new Dictionary<int, DataObject>();
  42. this.UpdateRate = this.ManagerObject.UpdateRateInSeconds / this.ManagerObject.GameVelocity;
  43. }
  44. ///<summary>
  45. /// Create new GameObject corresponding to given InputObject
  46. ///</summary>
  47. private GameObject Create(InputObject input)
  48. {
  49. //Create GameObject and DataObject
  50. var id = input.ID;
  51. //new DataObject
  52. DataObject data;
  53. //new GameObject
  54. GameObject obj;
  55. switch (input.Type)
  56. {
  57. case EntityType.BIKE:
  58. obj = Instantiate(prefabBike);
  59. break;
  60. case EntityType.TRUCK:
  61. obj = Instantiate(prefabTruck);
  62. break;
  63. case EntityType.CAR:
  64. obj = Instantiate(prefabCar);
  65. break;
  66. case EntityType.PERSON:
  67. obj = Instantiate(prefabHuman);
  68. break;
  69. default:
  70. obj = Instantiate(prefabHuman);
  71. CityLogger.LogError(string.Format("Could not Add Object {0} invalid Entity Type \n", id));
  72. break;
  73. }
  74. //change name to the id
  75. obj.name = id.ToString();
  76. // add GameObject to ObjectDictionary
  77. try
  78. {
  79. ObjectDictionary.Add(id, obj);
  80. }
  81. catch (System.ArgumentException e)
  82. {
  83. CityLogger.LogError(string.Format("Could not Add Object {0} to ObjectDictionary\n{1}", id, e));
  84. }
  85. // get the DataObject
  86. data = obj.GetComponent<DataObject>();
  87. data.SetUp(id, this, input.Type, TTL, ManagerObject.GameVelocity);
  88. //Add DataObject to Dicitonary
  89. DataObjectDictionary.Add(id, data);
  90. //set the position in the simulation to the first given postion
  91. data.TargetPos = input.Pos;
  92. data.StartPos = input.Pos;
  93. //try to get the given sensor
  94. GameObject sensor;
  95. try
  96. {
  97. sensor = SensorList[input.SensorID];
  98. }
  99. catch (KeyNotFoundException ex)
  100. {
  101. CityLogger.LogError(ex.Message + "Sensor ID : " + input.SensorID.ToString());
  102. //if sensor was not found set default sensor
  103. sensor = SensorList[0];
  104. }
  105. //map input data to DataObject
  106. data.MapInputObjekt(input, sensor);
  107. return obj;
  108. }
  109. ///<summary>
  110. /// Add Object to ObjectToDelete list
  111. ///</summary>
  112. public override void DeleteObject(DataObject data)
  113. {
  114. ObjectsToDelete.Add(data);
  115. }
  116. ///<summary>
  117. /// Delete Object with same id as the given DataObject
  118. /// Removes GameObject from ObjectDictionary
  119. /// Removes DataObject from DataObjectDictionary
  120. /// Destroys GameObject
  121. ///</summary>
  122. private void DestroyObject(DataObject data)
  123. {
  124. var id = data.ID;
  125. GameObject removeObj;
  126. //check if object to remove is in ObjectDictionary
  127. if (ObjectDictionary.TryGetValue(id, out removeObj))
  128. {
  129. //try to remove GameObject out of ObjectDicitonary
  130. if (!ObjectDictionary.Remove(id))
  131. {
  132. //Implement ErrorHandling
  133. //didn't occured till now
  134. CityLogger.LogError(string.Format("Object could not be removed out of ObjectDictionary ObjectId: {0}", id));
  135. }
  136. //try to remove DataObject out of DataObjectDictionary
  137. if (!DataObjectDictionary.Remove(id))
  138. {
  139. //Implement ErrorHandling
  140. //didn't occured till now
  141. CityLogger.LogError(string.Format("Object could not be removed out of DataObjectDictionary ObjectId: {0}", id));
  142. }
  143. // try to Destroy GameObject
  144. try
  145. {
  146. Destroy(removeObj);
  147. }
  148. catch (System.Exception)
  149. {
  150. //Implement ErrorHandling
  151. //didn't occured till now
  152. throw;
  153. }
  154. }
  155. else
  156. {
  157. //Implement ErrorHandling
  158. //didn't occured till now
  159. CityLogger.LogError(string.Format("Object to remove was not found ObjectId: {0} ", id));
  160. }
  161. }
  162. private void Update()
  163. {
  164. //Update the update Rate
  165. this.GameVelocity = this.ManagerObject.GameVelocity;
  166. this.Forward = this.ManagerObject.forward;
  167. if (this.GameVelocity > 0)
  168. {
  169. this.UpdateRate = this.ManagerObject.UpdateRateInSeconds / this.GameVelocity;
  170. }
  171. else
  172. {
  173. this.UpdateRate = 0;
  174. }
  175. //Using ObjectsToDelete and ObjectsToCreate because Unity does not allow to call MonoBehaviour methods in parallel.
  176. // so if a parallel foreach is used to handle the input objects, then there is no way to call Create() or DestroyObject().
  177. //Delete/Destroy each Object in ObjectsToDelete
  178. foreach (var objectToDelete in ObjectsToDelete)
  179. {
  180. DestroyObject(objectToDelete);
  181. }
  182. //After deleteing clear List
  183. ObjectsToDelete.Clear();
  184. //Create each Object in ObjectsToCreate
  185. foreach (int id in ObjectsToCreate.Keys)
  186. {
  187. if (ObjectsToCreate.TryGetValue(id, out InputObject input))
  188. {
  189. Create(input);
  190. }
  191. else
  192. {
  193. CityLogger.LogError(string.Format("Could not create InputObjekt {0}", id));
  194. }
  195. }
  196. //After creating all Objects clear
  197. ObjectsToCreate.Clear();
  198. }
  199. ///<summary>
  200. /// Clear scene by destroying every GameObject
  201. ///</summary>
  202. public override void ClearAll()
  203. {
  204. this.ObjectsToDelete.UnionWith(this.DataObjectDictionary.Values);
  205. this.ObjectsToCreate.Clear();
  206. }
  207. ///<summary>
  208. /// Handle the InputBuffer
  209. ///</summary>
  210. public override void Handle(List<InputObject> InputBuffer)
  211. {
  212. // if InputBuffer not empty
  213. if (InputBuffer != null && InputBuffer.Count > 0)
  214. {
  215. //take the current DataObjectDictionary
  216. Dictionary<int, DataObject> dataDict;
  217. dataDict = DataObjectDictionary;
  218. //here a parallel foreach is possible but is way faster with a serial foreach
  219. foreach (InputObject input in InputBuffer)
  220. {
  221. // Debug.Log(b);
  222. //If Object with ID exist map the new data to the object
  223. if (dataDict.TryGetValue(input.ID, out DataObject data))
  224. {
  225. bool valid = SensorList.TryGetValue(input.SensorID, out GameObject sensor);
  226. if (!valid)
  227. {
  228. CityLogger.LogError(string.Format("Unable to find ID {0} in SensorList", input.SensorID));
  229. continue;
  230. }
  231. data.MapInputObjekt(input, sensor);
  232. // MapInputToDataObject(data, input);
  233. }
  234. else
  235. {
  236. //if there is no object with the ID. Create an Object.
  237. int id = input.ID;
  238. if (!ObjectsToCreate.ContainsKey(id))
  239. {
  240. ObjectsToCreate.Add(id, input);
  241. }
  242. else
  243. {
  244. //updates faster than creating.
  245. CityLogger.LogError(string.Format("Update faster then creating id: {0} (two updates for one object)", id));
  246. }
  247. // }
  248. }
  249. // Debug.Log(b);
  250. };
  251. }
  252. }
  253. }
  254. }