using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; /* Traffic controller * Felelős a forgalom irányításáért és a forgalom figyeléséért. * * Az autók innen kérdezik le, hogy adott kereszteződésből merre lehet menni a lámpa szerint, illetve van-e még hely * az adott úton. * * Autókat spawnol (és színez is). * * Lekérdezi a lámpák állapotát. * Jegyzi a várakozó autók számát és elüldi a megfelelő szervernek. * * Csak szerveroldalon fut. */ //Nem kell SyncVar-ral foglalkoznia a UNET-nek [NetworkSettings(channel = 0, sendInterval = 0)] public class TrafficController : NetworkBehaviour { [Header("Network setup")] public string url = "http://localhost:8080/"; public string getURI = "/trafficLights/"; public string putRoadsURI = "/roads/"; public string putCarCountURI = "/passedCarCount"; [Header("Road setup")] public Road[] roads = new Road[16]; public List crossroadsUnity; public TrafficLights trafficLights; [Header("Misc setup")] public GameObject carPrefab; public List carColors; public carCount carCounter; //ezek roadID-k public int[] spawnPosition = { 0, 1, 5, 6, 10, 11, 15, 12 }; public float updateInterval = 1; public float spawnInterval = 0.5f; private float timePassedUpdate = 0; private float timePassedSpawn = 0; private int current = 0; public override void OnStartServer () { base.OnStartServer(); url = url.TrimEnd('/'); trafficLights = new TrafficLights(); StartCoroutine("getState"); } void Update () { if (!isServer) return; timePassedUpdate += Time.deltaTime; if (timePassedUpdate >= updateInterval) { StartCoroutine("getState"); StartCoroutine("putRoads"); StartCoroutine("putCarCount"); timePassedUpdate = 0; } timePassedSpawn += Time.deltaTime; if (timePassedSpawn >= spawnInterval) { spawnCar(spawnPosition[current++]); current %= spawnPosition.Length; timePassedSpawn = 0; } } IEnumerator getState () { using (WWW www = new WWW(url + getURI)) { yield return www; trafficLights.roadSystem = JsonUtility.FromJson(www.text); for (int i = 0; i < 4; i++) { crossroadsUnity[i].colors.RpcUpdateColors(trafficLights[i].N, trafficLights[i].E, trafficLights[i].S, trafficLights[i].W); trafficLights.isWithoutLights[i] = !(trafficLights[i].N != "off" && trafficLights[i].E != "off" && trafficLights[i].S != "off" && trafficLights[i].W != "off"); } } } IEnumerator putRoads () { string roadStates = "{ \"NW\": { \"W\":" + roads[0].carCount.ToString() + ",\"N\":" + roads[1].carCount.ToString() + ",\"E\":" + roads[2].carCount.ToString() + ",\"S\":" + roads[3].carCount.ToString() + "}" + ", \"NE\": { \"W\":" + roads[4].carCount.ToString() + ",\"N\":" + roads[5].carCount.ToString() + ",\"E\":" + roads[6].carCount.ToString() + ",\"S\":" + roads[7].carCount.ToString() + "}" + ", \"SE\": { \"W\":" + roads[8].carCount.ToString() + ",\"N\":" + roads[9].carCount.ToString() + ",\"E\":" + roads[10].carCount.ToString() + ",\"S\":" + roads[11].carCount.ToString() + "}" + ", \"SW\": { \"W\":" + roads[12].carCount.ToString() + ",\"N\":" + roads[13].carCount.ToString() + ",\"E\":" + roads[14].carCount.ToString() + ",\"S\":" + roads[15].carCount.ToString() + "}" + "}"; byte[] data = System.Text.Encoding.UTF8.GetBytes(roadStates); UnityWebRequest www = UnityWebRequest.Put(url + putRoadsURI, data); yield return www.SendWebRequest(); if (www.isNetworkError || www.isHttpError) { Debug.Log(www.error); } } IEnumerator putCarCount () { byte[] data = System.Text.Encoding.UTF8.GetBytes(carCounter.throughput.ToString()); UnityWebRequest www = UnityWebRequest.Put(url + putCarCountURI, data); yield return www.SendWebRequest(); if (www.isNetworkError || www.isHttpError) { Debug.Log(www.error); } } //Beállítja a hívó autó next roadId-jét és megmondja, mehet-e a lámpa alapján. public bool getInfo(int index, string direction, ref int forwardRoadID, ref int rightRoadID) { bool canGo = trafficLights.canGo(index); switch (direction) { case "North": forwardRoadID = crossroadsUnity[index].southNextRoadID; rightRoadID = crossroadsUnity[index].westNextRoadID; return trafficLights[index].N == "green" || canGo; case "East": forwardRoadID = crossroadsUnity[index].westNextRoadID; rightRoadID = crossroadsUnity[index].northNextRoadID; return trafficLights[index].E == "green" || canGo; case "South": forwardRoadID = crossroadsUnity[index].northNextRoadID; rightRoadID = crossroadsUnity[index].eastNextRoadID; return trafficLights[index].S == "green" || canGo; case "West": forwardRoadID = crossroadsUnity[index].eastNextRoadID; rightRoadID = crossroadsUnity[index].southNextRoadID; return trafficLights[index].W == "green" || canGo; default: return false; } } //Megmondja, hogy az autó mehet-e az alapján, hogy hány autó van a cél úton. //Az autó arra megy majd, amerre tud. public bool changeRoad(int current, int next) { if (next == -1) { roads[current].carCount--; return true; } if (roads[next].isThereSpace) { roads[current].carCount--; roads[next].carCount++; roads[next].isThereSpace = false; return true; } else return false; } //Szerveroldalról autót spawnol, ha tud. [Server] public void spawnCar(int index) { if(roads[index].spawnPoint) { if (roads[index].isThereSpace) { roads[index].isThereSpace = false; roads[index].carCount++; GameObject car = (GameObject)Instantiate(carPrefab, roads[index].spawnPoint.transform.position, roads[index].spawnPoint.transform.rotation); car.GetComponent().RoadID = index; car.GetComponent().CarColor = carColors[Random.Range(0, carColors.Count)]; NetworkServer.Spawn(car); } } } } [System.Serializable] public struct CrossroadUnity { public trafficLightColor colors; //int?-et nem támogat unity, invalid érték: -1 //Itt a kereszteződésből kivezető út ID-jét tároljuk. public int northNextRoadID; public int southNextRoadID; public int westNextRoadID; public int eastNextRoadID; } /* Utak kiosztása: * Egy út lehet, hogy fizikailag egy, viszont az alapján van szétosztva, hogy melyik kereszteződésbe torkollik. * Lehet intuitívabb elnevezése lenne road helyett a lane. * * 1 5 * V V * 0 > < 2 4 > < 6 * ^ ^ * 3 7 * * 13 9 * V V * 12 > < 14 8 > < 10 * ^ ^ * 15 11 * * (Észak felfele van [arra mutat a fehér nyíl pályán], a 4 csomópont a 4 kereszteződésnek felel meg.) */ //Unityben egy utat egy ilyen szimbolizál [System.Serializable] public struct Road { //Nem kötelező megadni public Transform spawnPoint; //A safespace állítja public bool isThereSpace; public int carCount; } [System.Serializable] public struct Crossroads { public string N; public string E; public string S; public string W; } [System.Serializable] public struct RoadSystem { public Crossroads NW; public Crossroads NE; public Crossroads SE; public Crossroads SW; } public class TrafficLights { public RoadSystem roadSystem; public bool[] isWithoutLights = { true, true, true, true }; public bool[] isThereSpace = { true, true, true, true }; public bool canGo(int i) { return isWithoutLights[i] && isThereSpace[i]; } public Crossroads this[int i] { get { switch(i) { case 0: return roadSystem.NW; case 1: return roadSystem.NE; case 2: return roadSystem.SE; default: return roadSystem.SW; } } } }