using Unity.Burst; using Unity.Collections; using Unity.Entities; using Unity.Jobs; using Unity.Mathematics; using Unity.Transforms; using Hash128 = Unity.Entities.Hash128; namespace Unity.MegaCity.Streaming { /// /// Set of jobs to handle streaming in/out of sub scenes /// [BurstCompile] public partial struct StreamSubScenesIn : IJobEntity { public NativeList AddRequestList; public float3 CameraPosition; public float MaxDistanceSquared; public void Execute(Entity entity, in SceneSectionData sceneData) { AABB boundingVolume = sceneData.BoundingVolume; var distanceSq = boundingVolume.DistanceSq(CameraPosition); if (distanceSq < MaxDistanceSquared) AddRequestList.Add(entity); } } [BurstCompile] public partial struct StreamSubScenesOut : IJobEntity { public NativeList RemoveRequestList; public float3 CameraPosition; public float MaxDistanceSquared; public Hash128 PlayerSectionGUID; public void Execute(Entity entity, in SceneSectionData sceneData) { if (sceneData.SceneGUID == PlayerSectionGUID) return; AABB boundingVolume = sceneData.BoundingVolume; var distanceSq = boundingVolume.DistanceSq(CameraPosition); if (distanceSq > MaxDistanceSquared) RemoveRequestList.Add(entity); } } [BurstCompile] public struct BuildCommandBufferJob : IJob { public EntityCommandBuffer CommandBuffer; public NativeArray AddRequestArray; public NativeArray RemoveRequestArray; public void Execute() { foreach (var entity in AddRequestArray) { CommandBuffer.AddComponent(entity, new RequestSceneLoaded { LoadFlags = SceneLoadFlags.LoadAdditive }); } foreach (var entity in RemoveRequestArray) { CommandBuffer.RemoveComponent(entity); } } } [BurstCompile] [UpdateInGroup(typeof(InitializationSystemGroup))] [WorldSystemFilter(WorldSystemFilterFlags.LocalSimulation | WorldSystemFilterFlags.ClientSimulation)] public partial struct StreamingLogicSystem : ISystem { private EntityQuery _query; public void OnCreate(ref SystemState state) { state.RequireForUpdate(); _query = state.GetEntityQuery(ComponentType.ReadOnly(), ComponentType.ReadOnly()); } public void OnUpdate(ref SystemState state) { state.CompleteDependency(); var entityCommandBufferSystem = state.World.GetExistingSystemManaged(); var streamingLogicConfig = _query.GetSingleton(); var cameraPosition = _query.GetSingleton().Position; var addRequestList = new NativeList(Allocator.TempJob); var removeRequestList = new NativeList(Allocator.TempJob); var streamIn = new StreamSubScenesIn { AddRequestList = addRequestList, CameraPosition = cameraPosition, MaxDistanceSquared = streamingLogicConfig.DistanceForStreamingIn * streamingLogicConfig.DistanceForStreamingIn }; state.Dependency = streamIn.Schedule(state.Dependency); var streamOut = new StreamSubScenesOut { RemoveRequestList = removeRequestList, CameraPosition = cameraPosition, MaxDistanceSquared = streamingLogicConfig.DistanceForStreamingOut * streamingLogicConfig.DistanceForStreamingOut, PlayerSectionGUID = streamingLogicConfig.PlayerSectionGUID, }; state.Dependency = streamOut.Schedule(state.Dependency); state.Dependency = new BuildCommandBufferJob { CommandBuffer = entityCommandBufferSystem.CreateCommandBuffer(), AddRequestArray = addRequestList.AsDeferredJobArray(), RemoveRequestArray = removeRequestList.AsDeferredJobArray() }.Schedule(state.Dependency); entityCommandBufferSystem.AddJobHandleForProducer(state.Dependency); addRequestList.Dispose(state.Dependency); removeRequestList.Dispose(state.Dependency); } } [BurstCompile] [UpdateInGroup(typeof(InitializationSystemGroup))] [WorldSystemFilter(WorldSystemFilterFlags.Presentation)] public partial struct ServerStreamingLogicSystem : ISystem { private EntityQuery m_Query; public void OnCreate(ref SystemState state) { state.RequireForUpdate(); m_Query = state.GetEntityQuery(ComponentType.ReadOnly(), ComponentType.ReadOnly()); } public void OnUpdate(ref SystemState state) { var entityCommandBufferSystem = state.World.GetExistingSystemManaged(); var streamingLogicConfig = m_Query.GetSingleton(); var cameraPosition = m_Query.GetSingleton().Position; var addRequestList = new NativeList(Allocator.TempJob); var removeRequestList = new NativeList(Allocator.TempJob); var streamIn = new StreamSubScenesIn { AddRequestList = addRequestList, CameraPosition = cameraPosition, MaxDistanceSquared = streamingLogicConfig.DistanceForStreamingIn * streamingLogicConfig.DistanceForStreamingIn }; state.Dependency = streamIn.Schedule(state.Dependency); var streamOut = new StreamSubScenesOut { RemoveRequestList = removeRequestList, CameraPosition = cameraPosition, MaxDistanceSquared = streamingLogicConfig.DistanceForStreamingOut * streamingLogicConfig.DistanceForStreamingOut, PlayerSectionGUID = streamingLogicConfig.PlayerSectionGUID, }; state.Dependency = streamOut.Schedule(state.Dependency); state.Dependency = new BuildCommandBufferJob { CommandBuffer = entityCommandBufferSystem.CreateCommandBuffer(), AddRequestArray = addRequestList.AsDeferredJobArray(), RemoveRequestArray = removeRequestList.AsDeferredJobArray() }.Schedule(state.Dependency); entityCommandBufferSystem.AddJobHandleForProducer(state.Dependency); addRequestList.Dispose(state.Dependency); removeRequestList.Dispose(state.Dependency); } } }