diff --git a/Assets/Code/Components/Components.cs b/Assets/Code/Components/Components.cs index a3ba9d4..76aaad9 100644 --- a/Assets/Code/Components/Components.cs +++ b/Assets/Code/Components/Components.cs @@ -44,6 +44,12 @@ public struct SpawnRange : IComponentData public float3 max; } + public struct WorldBoundary : IComponentData + { + public float3 min; + public float3 max; + } + public struct Randomizer : IComponentData { public Unity.Mathematics.Random value; diff --git a/Assets/Code/Systems.Initialization/InitializeGroup/InitializeWorldBoundarySystem.cs b/Assets/Code/Systems.Initialization/InitializeGroup/InitializeWorldBoundarySystem.cs new file mode 100644 index 0000000..fb29011 --- /dev/null +++ b/Assets/Code/Systems.Initialization/InitializeGroup/InitializeWorldBoundarySystem.cs @@ -0,0 +1,54 @@ +using Unity.Entities; +using UnityEngine; + +namespace SimpleSetupEcs2d +{ + [UpdateInGroup(typeof(InitializeSystemGroup))] + public sealed partial class InitializeWorldBoundarySystem : SystemBase + { + protected override void OnCreate() + { + var query = SystemAPI.QueryBuilder() + .WithNone() + .Build(); + + RequireForUpdate(query); + } + + protected override void OnUpdate() + { + if (Camera.main == false) + { + return; + } + + var cam = Camera.main; + var camTrans = cam.transform; + +#if UNITY_EDITOR + UnityEditor.PlayModeWindow.GetRenderingResolution(out var resolutionWidth, out var resolutionHeight); +#else + var resolution = Screen.currentResolution; + var resolutionWidth = resolution.width; + var resolutionHeight = resolution.height; +#endif + + var scaleWidthFactor = resolutionWidth / (float)resolutionHeight; + var height = cam.orthographicSize * 2f; + var width = height * scaleWidthFactor; + + var rect = new Rect( + new(camTrans.position.x - (width * 0.5f), camTrans.position.y - (height * 0.5f)) + , new(width, height) + ); + + var boundary = new WorldBoundary { + min = new(rect.min, 0f), + max = new(rect.max, 0f), + }; + + EntityManager.CreateSingleton(boundary, nameof(WorldBoundary)); + CheckedStateRef.Enabled = false; + } + } +} diff --git a/Assets/Code/Systems.Initialization/InitializeGroup/InitializeWorldBoundarySystem.cs.meta b/Assets/Code/Systems.Initialization/InitializeGroup/InitializeWorldBoundarySystem.cs.meta new file mode 100644 index 0000000..8a68c8a --- /dev/null +++ b/Assets/Code/Systems.Initialization/InitializeGroup/InitializeWorldBoundarySystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 88432b6087acbbe47a959e2c3f131bd4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Code/Systems.Simulation/MoveBackFromOutsideWorldBoundarySystem.cs b/Assets/Code/Systems.Simulation/MoveBackFromOutsideWorldBoundarySystem.cs new file mode 100644 index 0000000..f141ddd --- /dev/null +++ b/Assets/Code/Systems.Simulation/MoveBackFromOutsideWorldBoundarySystem.cs @@ -0,0 +1,67 @@ +using Unity.Burst; +using Unity.Entities; +using Unity.Mathematics; +using Unity.Transforms; + +namespace SimpleSetupEcs2d +{ + [BurstCompile] + [UpdateInGroup(typeof(SimulationSystemGroup))] + [UpdateAfter(typeof(MoveSystem))] + public partial struct MoveBackFromOutsideWorldBoundarySystem : ISystem + { + private EntityQuery _boundaryQuery; + private EntityQuery _entityQuery; + + [BurstCompile] + public void OnCreate(ref SystemState state) + { + _boundaryQuery = SystemAPI.QueryBuilder() + .WithAll() + .Build(); + + _entityQuery = SystemAPI.QueryBuilder() + .WithAll() + .WithAllRW() + .WithAll() + .WithDisabled() + .WithDisabled() + .Build(); + + state.RequireForUpdate(_boundaryQuery); + state.RequireForUpdate(_entityQuery); + } + + [BurstCompile] + public void OnUpdate(ref SystemState state) + { + var boundary = _boundaryQuery.GetSingleton(); + + var job = new MoveBackFromOutsideWorldBoundaryJob { + boundary = boundary, + padding = 1f, + }; + + state.Dependency = job.ScheduleParallel(_entityQuery, state.Dependency); + } + + [BurstCompile] + private partial struct MoveBackFromOutsideWorldBoundaryJob : IJobEntity + { + public WorldBoundary boundary; + public float padding; + + private void Execute(in FaceDirection faceDirection, ref LocalTransform transform) + { + var position = transform.Position; + var min = boundary.min; + var max = boundary.max; + var xToTheRight = math.select(position.x, min.x - padding, position.x > max.x + padding); + var xToTheLeft = math.select(position.x, max.x + padding, position.x < min.x - padding); + position.x = math.select(xToTheLeft, xToTheRight, faceDirection.value > 0); + + transform.Position = position; + } + } + } +} diff --git a/Assets/Code/Systems.Simulation/MoveBackFromOutsideWorldBoundarySystem.cs.meta b/Assets/Code/Systems.Simulation/MoveBackFromOutsideWorldBoundarySystem.cs.meta new file mode 100644 index 0000000..66940b0 --- /dev/null +++ b/Assets/Code/Systems.Simulation/MoveBackFromOutsideWorldBoundarySystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8ad14f786b6b89a449de554f94e0b647 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: