UnityTrafficSimulation/UnityProject/Assets/Scripts/TrafficController.cs

307 lines
8.1 KiB
C#

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<CrossroadUnity> crossroadsUnity;
public TrafficLights trafficLights;
[Header("Misc setup")]
public GameObject carPrefab;
public List<Color> 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<RoadSystem>(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<CarHL>().RoadID = index;
car.GetComponent<CarHL>().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;
}
}
}
}