using HighwayRacers; using System.Collections.Generic; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using Unity.Entities; using Unity.Rendering; using UnityEngine; // Update the track-tile occupancy after CarMovementSystem so that we have the latest car offsets. // CarMovementSystem will use last frame's tile knowledge to avoid collisions. [UpdateAfter(typeof(CarMovementSystem))] public class TrackOccupancySystem : SystemBase { private CarMovementSystem m_CarMovementSystem; private StreetDefinitionSystem m_StreetDefinitionSystem; //private StreetDefinitionSystem m_StreetDefinitionSystem; private const int TILESCAPACITY = 500 * 90; //------------------------------------------------------------------------------------------------ protected override void OnCreate() { UnityEngine.Debug.Log(">> TrackOccupancySystem Created."); m_CarMovementSystem = World.GetExistingSystem(); //m_StreetDefinitionSystem = World.GetExistingSystem(); int TilesPerLane = TILESCAPACITY;// m_StreetDefinitionSystem.GetBufferLength(); //ENTITY Read Entity readEntity = EntityManager.CreateEntity(typeof(LaneOccupancy)); DynamicBuffer readBuffer = EntityManager.AddBuffer(readEntity); ResetBuffer(ref readBuffer, TilesPerLane); //ENTITY Write Entity writeEntity = EntityManager.CreateEntity(typeof(LaneOccupancy)); DynamicBuffer writeBuffer = EntityManager.AddBuffer(writeEntity); ResetBuffer(ref writeBuffer, TilesPerLane); m_GroupStreet = GetEntityQuery(typeof(StreetDataElement)); m_StreetDefinitionSystem = World.GetExistingSystem(); } EntityQuery m_GroupStreet; //------------------------------------------------------------------------------------------------ protected override void OnUpdate() { int TilesPerLane = TILESCAPACITY;// m_StreetDefinitionSystem.GetBuffer().Length; // Reset the write occupancy for each lane to 0 for all tiles DynamicBuffer writeBuffer = GetWriteBuffer(m_CarMovementSystem.Frame); ResetBuffer(ref writeBuffer, TilesPerLane); var streetslength = m_GroupStreet.CalculateEntityCount(); for (int i = 0; i < streetslength; i++) { var streetDefinition = m_StreetDefinitionSystem.GetBuffer(i); Entities .WithNativeDisableContainerSafetyRestriction(writeBuffer) .WithNativeDisableContainerSafetyRestriction(streetDefinition) .ForEach((Entity vehicle, in CarMovement carMovement) => { if (carMovement.Street == i && carMovement.IsShown) { int myLane = carMovement.Lane; int tilesPerLane = streetDefinition.Length; int myTile = GetMyTile(carMovement.Offset, tilesPerLane); //Get next Tile INDEX? writeBuffer.ElementAt(myTile + 500 * carMovement.Street).Occupied |= (byte)(1 << myLane); //Already [Occupied] OR [move to left line] } }) .ScheduleParallel(); } //if (CommonFields.ShowDebugTiles) //{ // Entities // .WithNativeDisableContainerSafetyRestriction(writeBuffer) // .ForEach((Entity tileEntity, ref URPMaterialPropertyBaseColor tileDebugMat, in TileDebugColor tileDebugColor) => // { // byte tiles = writeBuffer[(int)tileDebugColor.tileId].Occupied; // byte lane = (byte)(1 << (int)tileDebugColor.laneId); // if ((tiles & lane) == 0) // tileDebugMat.Value = new Unity.Mathematics.float4(0.5f, 0.5f, 0.5f, 1); // else // tileDebugMat.Value = new Unity.Mathematics.float4(1.0f, 0.0f, 0.0f, 1); // }) // .ScheduleParallel(); //} } //------------------------------------------------------------------------------------------------ public DynamicBuffer GetReadBuffer(uint frame) { var occupancyEntities = GetEntityQuery(typeof(LaneOccupancy)).ToEntityArray(Allocator.Temp); if (frame % 2 == 0) return EntityManager.GetBuffer(occupancyEntities[0]); else return EntityManager.GetBuffer(occupancyEntities[1]); } //------------------------------------------------------------------------------------------------ public DynamicBuffer GetWriteBuffer(uint frame) { var occupancyEntities = GetEntityQuery(typeof(LaneOccupancy)).ToEntityArray(Allocator.Temp); if (frame % 2 == 0) return EntityManager.GetBuffer(occupancyEntities[1]); else return EntityManager.GetBuffer(occupancyEntities[0]); } //------------------------------------------------------------------------------------------------ unsafe void ResetBuffer(ref DynamicBuffer buffer, int TilesPerLane) { buffer.ResizeUninitialized( TilesPerLane); int elementSize = UnsafeUtility.SizeOf(); UnsafeUtility.MemSet(buffer.GetUnsafePtr(), 0, buffer.Length * elementSize); } //------------------------------------------------------------------------------------------------ static public int GetMyTile(float carOffset, int TilesPerLane) { return (int)((carOffset * TilesPerLane + 0.5f) % TilesPerLane); } //------------------------------------------------------------------------------------------------ static public bool IsTileOccupied(ref DynamicBuffer buffer, int lane, int tile, int streetindex) { byte tiles = buffer[tile + streetindex * 500].Occupied; byte laneByte = (byte) (1 << (int)lane); return (tiles & laneByte) != 0; } }