using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; //Define the system managing the events. (Singleton) //TODO: Switch to a registering approach for events public sealed class EventManager : MonoBehaviour { public static string EventManager_path="/GameSystem/EventManager"; //Singleton private static EventManager _instance=null; public static EventManager Instance { get { if(_instance is null) //Force Awakening if needed GameObject.Find(EventManager_path).GetComponent().Awake(); return _instance; } } [HideInInspector] public bool ready = false; //Wether the ClientManager is initialized [SerializeField] float SpawnRange = 1.0f; //Range of an event spawn from its origin (real max distance = 2*range) [SerializeField] float spawnChance = 100.0f; //Probability of an event to spawn (%) [SerializeField] int maxSoftObs = 1, maxHardObs = 1; //Maximum active events // [SerializeField] // float eventSpawnTimer = 0.5f; //Intial time before first spawn (pseudo-random after that) // [SerializeField] // float maxTimeNewEvents = 2.0f; //Longest waiting time for new clients // bool eventSpawnReady = false; [SerializeField] string SoftObsRessourceFolder = "Events/SoftObstacles", HardObsRessourceFolder = "Events/HardObstacles"; //Ressource folder w/ events prefabs private Dictionary eventPrefabs = new Dictionary(); GameObject EventContainer=null; //List of active event ID List softObsList = new List(); List hardObsList = new List(); [SerializeField] float coroutineRefreshRate = 1.0f; //Time (s) before refreshing a coroutine private Dictionary coroutines= new Dictionary(); //Dict of EventManager coroutines associated to each client ID //Spawn an event near position with a probability of spawnChance% public void spawnSoftObs(Vector2 position, float spawnChance = 100.0f) { Vector3 spawnPoint; if (Random.Range(0.0f, 99.9f) targetClients, Vector2 position, float spawnChance = 100.0f) { //TODO: Orienté client vers event + prefab Vector3 spawnPoint; if (Random.Range(0.0f, 99.9f)(); while(EventManager.Instance!=null){ if(GameSystem.Instance.serviceOpen) { //Try to spawn softObs or hardObs randomly if(Random.value<0.5 && client.status=="consuming") EventManager.Instance.spawnSoftObs(clientObj.transform.position, spawnChance); else { List otherClients = findNearClients(clientObj, 1.0f); if(otherClients.Count>0) { foreach(GameObject ocl in otherClients) Debug.DrawLine(clientObj.transform.position, ocl.transform.position, Color.red, coroutineRefreshRate); // Debug.Log("Clients near"); GameObject tgtClient = otherClients[Random.Range(0, otherClients.Count)]; //TODO : Compute spawnChance w/ clients happiness Vector2 eventPos=(clientObj.transform.position+tgtClient.transform.position)/2; //Event pos between clients List targetClients = new List(){client, tgtClient.GetComponent()}; EventManager.Instance.spawnHardObs(targetClients, eventPos, spawnChance); } } } yield return new WaitForSeconds(coroutineRefreshRate); //Called every coroutineRefreshRate second } } //Return the list of other clients in range of client. The client in event status are ignored. List findNearClients(GameObject client, float range) { List res = new List(); List clientList = ClientManager.Instance.clientList; Vector3 originPos = client.transform.position; Vector3 otherPos; foreach(GameObject cl in clientList) { otherPos=cl.transform.position; if(Vector2.Distance(originPos, otherPos)().status!="event")//Ignore clients already in event status res.Add(cl); } return res; } //Try to find a random point on NavMesh inside a range circle. A result would at a maximum distance of 2*range. bool RandomPoint(Vector3 center, float range, out Vector3 result) { for (int i = 0; i < 50; i++) { Vector3 randomPoint = center + (Vector3)Random.insideUnitCircle * range; NavMeshHit hit; if (NavMesh.SamplePosition(randomPoint, out hit, range, NavMesh.AllAreas)) { result = hit.position; return true; } } result = Vector3.zero; return false; } //Awake is called when the script instance is being loaded. void Awake() { //Singleton if (_instance != null && _instance != this) Destroy(this.gameObject); else _instance = this; if(!ready) { EventContainer = GameObject.Find(EventManager_path); if (EventContainer is null) throw new System.Exception("No EventManager found under GameSystem"); eventPrefabs["soft"] = Resources.LoadAll(SoftObsRessourceFolder); eventPrefabs["hard"] = Resources.LoadAll(HardObsRessourceFolder); if (eventPrefabs["soft"].Length==0) { Debug.LogWarning("EventManager didn't find events prefab in ressource folder : "+SoftObsRessourceFolder); } if (eventPrefabs["hard"].Length==0) { Debug.LogWarning("EventManager didn't find events prefab in ressource folder : "+HardObsRessourceFolder); } ready = true; } } // Update is called once per frame void Update() { // if(!eventSpawnReady) // { // eventSpawnTimer-= Time.deltaTime; // if(eventSpawnTimer<=0) // eventSpawnReady=true; // } } void OnDisable() { StopAllCoroutines(); } void OnDestroy() { StopAllCoroutines(); } }