123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using System.Threading.Tasks;
- using CSVReader;
- using Logger;
- using System.Collections.Concurrent;
- using System.Linq;
- namespace ObjectScripts
- {
- public class ObjectHandler : AbstractObjectHandler
- {
- ///<summary>
- /// Dictionary to keep track of every DataObject.
- /// <para>(ObjectID,DataObject)</para>
- ///</summary>
- public Dictionary<int, DataObject> DataObjectDictionary;
- ///<summary>
- /// Dictionary for Objects that need to be created.
- ///</summary>
- private Dictionary<int, InputObject> ObjectsToCreate;
- ///<summary>
- /// HashSet filled with Objects that need to be deleted
- ///</summary>
- private HashSet<DataObject> ObjectsToDelete;
- ///<summary>
- /// how Long an object can live without an update.
- ///</summary>
- public float TTL = 10f;
- ///<summary>
- /// Dictionary to keep track of every Sensor.
- /// <para>(SensorID,SensorGameobject)</para>
- ///</summary>
- public Dictionary<int, GameObject> SensorList { get; set; }
- void Start()
- {
- Forward = true;
- ObjectDictionary = new Dictionary<int, GameObject>();
- ObjectsToCreate = new Dictionary<int, InputObject>();
- ObjectsToDelete = new HashSet<DataObject>();
- DataObjectDictionary = new Dictionary<int, DataObject>();
- this.UpdateRate = this.ManagerObject.UpdateRateInSeconds / this.ManagerObject.GameVelocity;
- }
- ///<summary>
- /// Create new GameObject corresponding to given InputObject
- ///</summary>
- private GameObject Create(InputObject input)
- {
- //Create GameObject and DataObject
- var id = input.ID;
- //new DataObject
- DataObject data;
- //new GameObject
- GameObject obj;
- switch (input.Type)
- {
- case EntityType.BIKE:
- obj = Instantiate(prefabBike);
- break;
- case EntityType.TRUCK:
- obj = Instantiate(prefabTruck);
- break;
- case EntityType.CAR:
- obj = Instantiate(prefabCar);
- break;
- case EntityType.PERSON:
- obj = Instantiate(prefabHuman);
- break;
- default:
- obj = Instantiate(prefabHuman);
- CityLogger.LogError(string.Format("Could not Add Object {0} invalid Entity Type \n", id));
- break;
- }
- //change name to the id
- obj.name = id.ToString();
- // add GameObject to ObjectDictionary
- try
- {
- ObjectDictionary.Add(id, obj);
- }
- catch (System.ArgumentException e)
- {
- CityLogger.LogError(string.Format("Could not Add Object {0} to ObjectDictionary\n{1}", id, e));
- }
- // get the DataObject
- data = obj.GetComponent<DataObject>();
- data.SetUp(id, this, input.Type, TTL, ManagerObject.GameVelocity);
- //Add DataObject to Dicitonary
- DataObjectDictionary.Add(id, data);
- //set the position in the simulation to the first given postion
- data.TargetPos = input.Pos;
- data.StartPos = input.Pos;
- //try to get the given sensor
- GameObject sensor;
- try
- {
- sensor = SensorList[input.SensorID];
- }
- catch (KeyNotFoundException ex)
- {
- CityLogger.LogError(ex.Message + "Sensor ID : " + input.SensorID.ToString());
- //if sensor was not found set default sensor
- sensor = SensorList[0];
- }
- //map input data to DataObject
- data.MapInputObjekt(input, sensor);
- return obj;
- }
- ///<summary>
- /// Add Object to ObjectToDelete list
- ///</summary>
- public override void DeleteObject(DataObject data)
- {
- ObjectsToDelete.Add(data);
- }
- ///<summary>
- /// Delete Object with same id as the given DataObject
- /// Removes GameObject from ObjectDictionary
- /// Removes DataObject from DataObjectDictionary
- /// Destroys GameObject
- ///</summary>
- private void DestroyObject(DataObject data)
- {
- var id = data.ID;
- GameObject removeObj;
- //check if object to remove is in ObjectDictionary
- if (ObjectDictionary.TryGetValue(id, out removeObj))
- {
- //try to remove GameObject out of ObjectDicitonary
- if (!ObjectDictionary.Remove(id))
- {
- //Implement ErrorHandling
- //didn't occured till now
- CityLogger.LogError(string.Format("Object could not be removed out of ObjectDictionary ObjectId: {0}", id));
- }
- //try to remove DataObject out of DataObjectDictionary
- if (!DataObjectDictionary.Remove(id))
- {
- //Implement ErrorHandling
- //didn't occured till now
- CityLogger.LogError(string.Format("Object could not be removed out of DataObjectDictionary ObjectId: {0}", id));
- }
- // try to Destroy GameObject
- try
- {
- Destroy(removeObj);
- }
- catch (System.Exception)
- {
- //Implement ErrorHandling
- //didn't occured till now
- throw;
- }
- }
- else
- {
- //Implement ErrorHandling
- //didn't occured till now
- CityLogger.LogError(string.Format("Object to remove was not found ObjectId: {0} ", id));
- }
- }
- private void Update()
- {
- //Update the update Rate
- this.GameVelocity = this.ManagerObject.GameVelocity;
- this.Forward = this.ManagerObject.forward;
- if (this.GameVelocity > 0)
- {
- this.UpdateRate = this.ManagerObject.UpdateRateInSeconds / this.GameVelocity;
- }
- else
- {
- this.UpdateRate = 0;
- }
- //Using ObjectsToDelete and ObjectsToCreate because Unity does not allow to call MonoBehaviour methods in parallel.
- // so if a parallel foreach is used to handle the input objects, then there is no way to call Create() or DestroyObject().
- //Delete/Destroy each Object in ObjectsToDelete
- foreach (var objectToDelete in ObjectsToDelete)
- {
- DestroyObject(objectToDelete);
- }
- //After deleteing clear List
- ObjectsToDelete.Clear();
- //Create each Object in ObjectsToCreate
- foreach (int id in ObjectsToCreate.Keys)
- {
- if (ObjectsToCreate.TryGetValue(id, out InputObject input))
- {
- Create(input);
- }
- else
- {
- CityLogger.LogError(string.Format("Could not create InputObjekt {0}", id));
- }
- }
- //After creating all Objects clear
- ObjectsToCreate.Clear();
- }
- ///<summary>
- /// Clear scene by destroying every GameObject
- ///</summary>
- public override void ClearAll()
- {
- this.ObjectsToDelete.UnionWith(this.DataObjectDictionary.Values);
- this.ObjectsToCreate.Clear();
- }
- ///<summary>
- /// Handle the InputBuffer
- ///</summary>
- public override void Handle(List<InputObject> InputBuffer)
- {
- // if InputBuffer not empty
- if (InputBuffer != null && InputBuffer.Count > 0)
- {
- //take the current DataObjectDictionary
- Dictionary<int, DataObject> dataDict;
- dataDict = DataObjectDictionary;
- //here a parallel foreach is possible but is way faster with a serial foreach
- foreach (InputObject input in InputBuffer)
- {
- // Debug.Log(b);
- //If Object with ID exist map the new data to the object
- if (dataDict.TryGetValue(input.ID, out DataObject data))
- {
- bool valid = SensorList.TryGetValue(input.SensorID, out GameObject sensor);
- if (!valid)
- {
- CityLogger.LogError(string.Format("Unable to find ID {0} in SensorList", input.SensorID));
- continue;
- }
- data.MapInputObjekt(input, sensor);
- // MapInputToDataObject(data, input);
- }
- else
- {
- //if there is no object with the ID. Create an Object.
- int id = input.ID;
- if (!ObjectsToCreate.ContainsKey(id))
- {
- ObjectsToCreate.Add(id, input);
- }
- else
- {
- //updates faster than creating.
- CityLogger.LogError(string.Format("Update faster then creating id: {0} (two updates for one object)", id));
- }
- // }
- }
- // Debug.Log(b);
- };
- }
- }
- }
- }
|