From 868f743ae638af0db4871e5a515fcdc942a7069a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kub=C5=9B?= Date: Wed, 10 Jun 2026 21:55:54 +0200 Subject: [PATCH 1/3] feat(ships): add horizontal thrust in PlayerShip and gimbal system --- Assets/Scripts/Ships/AIShip.cs | 3 ++- Assets/Scripts/Ships/PlayerShip.cs | 6 +++-- Assets/Scripts/Ships/Ship.cs | 15 ++++++----- .../Ships/Systems/Gimbal/ControlAllocator.cs | 13 ++++----- .../Systems/Gimbal/EngineDirectionSolver.cs | 15 ++++++++--- .../Systems/Gimbal/SasTurnInputResolver.cs | 25 +++++++++-------- .../Tests/ShipControlAllocatorThrustTests.cs | 27 ++++++++++++++++--- .../Tests/TestHelpers/MovableShipTestProxy.cs | 5 +++- ProjectSettings/InputManager.asset | 17 ++++++++++++ 9 files changed, 91 insertions(+), 35 deletions(-) diff --git a/Assets/Scripts/Ships/AIShip.cs b/Assets/Scripts/Ships/AIShip.cs index 2505e7a8..b9cd3653 100644 --- a/Assets/Scripts/Ships/AIShip.cs +++ b/Assets/Scripts/Ships/AIShip.cs @@ -64,6 +64,7 @@ protected override void ReadMovementInput() { _aiShipStateMachine.Tick(Time.deltaTime); PendingForwardInput = 0f; + PendingHorizontalInput = 0f; PendingTurnInput = 0f; _pendingEnginesActive = false; @@ -82,7 +83,7 @@ protected override void ApplyMovementPhysics() return; } - MarkEnginesActivity(ApplyEngineForces(PendingForwardInput, PendingTurnInput, Time.fixedDeltaTime, true)); + MarkEnginesActivity(ApplyEngineForces(PendingForwardInput, 0, PendingTurnInput, Time.fixedDeltaTime, true)); } private void ComputeNavigationInputs(Vector2 targetPosition) diff --git a/Assets/Scripts/Ships/PlayerShip.cs b/Assets/Scripts/Ships/PlayerShip.cs index 03b87d2f..0ae9df13 100644 --- a/Assets/Scripts/Ships/PlayerShip.cs +++ b/Assets/Scripts/Ships/PlayerShip.cs @@ -30,7 +30,8 @@ protected override void ReadMovementInput() ToggleSas(); PendingForwardInput = Input.GetAxis("Vertical") * speedMultiplier; - PendingTurnInput = -Input.GetAxis("Horizontal") * rotationMultiplier; + PendingHorizontalInput = Input.GetAxis("Horizontal") * speedMultiplier; + PendingTurnInput = -Input.GetAxis("Roll") * rotationMultiplier; } protected override void ApplyMovementPhysics() @@ -41,7 +42,8 @@ protected override void ApplyMovementPhysics() return; } - MarkEnginesActivity(ApplyEngineForces(PendingForwardInput, PendingTurnInput, Time.fixedDeltaTime, + MarkEnginesActivity(ApplyEngineForces(PendingForwardInput, PendingHorizontalInput, PendingTurnInput, + Time.fixedDeltaTime, sasEnabled)); } diff --git a/Assets/Scripts/Ships/Ship.cs b/Assets/Scripts/Ships/Ship.cs index f6ad8359..244d0e6b 100644 --- a/Assets/Scripts/Ships/Ship.cs +++ b/Assets/Scripts/Ships/Ship.cs @@ -80,6 +80,7 @@ public class Ship : MonoBehaviour, IShip protected float PendingForwardInput; + protected float PendingHorizontalInput; protected float PendingTurnInput; [Inject] @@ -390,10 +391,11 @@ protected void MarkEnginesActivity(bool active) engine.SetActive(active); } - protected bool ApplyEngineForces(float forwardInput, float turnInput, float deltaTime, + protected bool ApplyEngineForces(float forwardInput, float horizontalInput, float turnInput, float deltaTime, bool sasEnabled = false) { forwardInput = Mathf.Clamp(forwardInput, -1f, 1f); + horizontalInput = Mathf.Clamp(horizontalInput, -1f, 1f); turnInput = Mathf.Clamp(turnInput, -1f, 1f); var selfRigidbody = CommandModule.PixelatedRigidbody?.Rigidbody; @@ -407,7 +409,7 @@ protected bool ApplyEngineForces(float forwardInput, float turnInput, float delt var centerOfMass = selfRigidbody.worldCenterOfMass; var maxLeverArm = EngineDirectionSolver.GetMaxLeverArmLength(engines, centerOfMass); var finalTurnInput = sasEnabled - ? _sasTurnInputResolver.ResolveTurnInput(turnInput, forwardInput, selfRigidbody, + ? _sasTurnInputResolver.ResolveTurnInput(turnInput, forwardInput, horizontalInput, selfRigidbody, GetCurrentHeadingDegrees(), engines, forward, centerOfMass, maxLeverArm, GetSasSettings()) : turnInput; var desiredDirectionPerEngine = new Vector2[engines.Count]; @@ -424,7 +426,7 @@ protected bool ApplyEngineForces(float forwardInput, float turnInput, float delt } var desiredDirection = EngineDirectionSolver.GetDesiredEngineDirection( - forward, centerOfMass, maxLeverArm, engine, forwardInput, finalTurnInput); + forward, centerOfMass, maxLeverArm, engine, forwardInput, horizontalInput, finalTurnInput); desiredDirectionPerEngine[i] = desiredDirection; if (desiredDirection.sqrMagnitude <= Mathf.Epsilon) @@ -449,7 +451,7 @@ protected bool ApplyEngineForces(float forwardInput, float turnInput, float delt var thrustRatios = ControlAllocator.AllocateControlInputs(engines, desiredDirectionPerEngine, centerOfMass, forward, - forwardInput, finalTurnInput, maxLeverArm, GetControlAllocatorSettings()); + forwardInput, horizontalInput, finalTurnInput, maxLeverArm, GetControlAllocatorSettings()); var anyForceApplied = false; @@ -535,10 +537,11 @@ internal Vector2 GetForwardForTesting() return CommandModule.Transform!.up; } - internal void ApplyEngineForcesForTesting(float forwardInput, float turnInput, float deltaTime, + internal void ApplyEngineForcesForTesting(float forwardInput, float horizontalInput, float turnInput, + float deltaTime, bool sasEnabled = false) { - ApplyEngineForces(forwardInput, turnInput, deltaTime, sasEnabled); + ApplyEngineForces(forwardInput, horizontalInput, turnInput, deltaTime, sasEnabled); } internal void ConfigureAllocatorForTesting(bool isEnabled, int iterations = 24, float forceWeight = 1f, diff --git a/Assets/Scripts/Ships/Systems/Gimbal/ControlAllocator.cs b/Assets/Scripts/Ships/Systems/Gimbal/ControlAllocator.cs index 62d0c02a..e06ac0c0 100644 --- a/Assets/Scripts/Ships/Systems/Gimbal/ControlAllocator.cs +++ b/Assets/Scripts/Ships/Systems/Gimbal/ControlAllocator.cs @@ -9,12 +9,13 @@ public class ControlAllocator { public static float[] AllocateControlInputs(IReadOnlyList engines, IReadOnlyList desiredDirections, - Vector2 centerOfMass, Vector2 forward, float forwardInput, float turnInput, float maxLeverArm, + Vector2 centerOfMass, Vector2 forward, float forwardInput, float horizontalInput, float turnInput, + float maxLeverArm, ControlAllocatorSettings settings) { var thrustRatios = new float[engines.Count]; - var requestedForceDirection = forwardInput >= 0f ? forward : -forward; - var requestedForceMagnitude = Mathf.Abs(forwardInput); + var shipRight = EngineDirectionSolver.GetShipRight(forward); + var requestedForce = forward * forwardInput + shipRight * horizontalInput; var columns = new Vector3[engines.Count]; var hasAnyEffectiveColumn = false; @@ -48,9 +49,9 @@ public static float[] AllocateControlInputs(IReadOnlyList engines, if (!hasAnyEffectiveColumn) return thrustRatios; - var targetForceMagnitude = requestedForceMagnitude * totalThrustCapacity * settings.ForceWeight; - var targetX = requestedForceDirection.x * targetForceMagnitude; - var targetY = requestedForceDirection.y * targetForceMagnitude; + var targetForceMagnitude = totalThrustCapacity * settings.ForceWeight; + var targetX = requestedForce.x * targetForceMagnitude; + var targetY = requestedForce.y * targetForceMagnitude; var torqueScale = Mathf.Max(totalTorqueCapacity, Mathf.Max(1f, maxLeverArm)); var targetTorque = turnInput * torqueScale * settings.TorqueWeight; diff --git a/Assets/Scripts/Ships/Systems/Gimbal/EngineDirectionSolver.cs b/Assets/Scripts/Ships/Systems/Gimbal/EngineDirectionSolver.cs index 03343ce0..e4448d2d 100644 --- a/Assets/Scripts/Ships/Systems/Gimbal/EngineDirectionSolver.cs +++ b/Assets/Scripts/Ships/Systems/Gimbal/EngineDirectionSolver.cs @@ -15,21 +15,28 @@ public static float GetMaxLeverArmLength(IEnumerable engines, Vector2 ce return Mathf.Max(maxLeverArm, 0.01f); } + public static Vector2 GetShipRight(Vector2 shipForward) + { + return new Vector2(shipForward.y, -shipForward.x); + } + public static Vector2 GetDesiredEngineDirection(Vector2 shipForward, Vector2 centerOfMass, float maxLeverArm, - Engine engine, float forwardInput, float turnInput) + Engine engine, float forwardInput, float horizontalInput, float turnInput) { var lever = engine.WorldThrustPoint - centerOfMass; var rotationalDirection = new Vector2(-lever.y, lever.x) / maxLeverArm; - return shipForward * forwardInput + rotationalDirection * turnInput; + return shipForward * forwardInput + GetShipRight(shipForward) * horizontalInput + + rotationalDirection * turnInput; } public static float EstimateNetTorqueForTurnInput(IReadOnlyList engines, Vector2 shipForward, - Vector2 centerOfMass, float maxLeverArm, float forwardInput, float turnInput) + Vector2 centerOfMass, float maxLeverArm, float forwardInput, float horizontalInput, float turnInput) { return (from engine in engines.AsValueEnumerable() where !(engine.MaxThrust <= 0f) let desiredDirection = - GetDesiredEngineDirection(shipForward, centerOfMass, maxLeverArm, engine, forwardInput, turnInput) + GetDesiredEngineDirection(shipForward, centerOfMass, maxLeverArm, engine, forwardInput, + horizontalInput, turnInput) where !(desiredDirection.sqrMagnitude <= Mathf.Epsilon) let thrust = Mathf.Clamp01(desiredDirection.magnitude) * engine.MaxThrust let force = desiredDirection.normalized * thrust diff --git a/Assets/Scripts/Ships/Systems/Gimbal/SasTurnInputResolver.cs b/Assets/Scripts/Ships/Systems/Gimbal/SasTurnInputResolver.cs index e315950e..6815a047 100644 --- a/Assets/Scripts/Ships/Systems/Gimbal/SasTurnInputResolver.cs +++ b/Assets/Scripts/Ships/Systems/Gimbal/SasTurnInputResolver.cs @@ -16,19 +16,21 @@ public void CaptureDesiredHeading(float currentHeadingDegrees) _hasDesiredHeading = true; } - public float ResolveTurnInput(float requestedTurnInput, float forwardInput, Rigidbody2D selfRigidbody, + public float ResolveTurnInput(float requestedTurnInput, float forwardInput, float horizontalInput, + Rigidbody2D selfRigidbody, float currentHeadingDegrees, IReadOnlyList engines, Vector2 shipForward, Vector2 centerOfMass, - float maxLeverArm, in SasTurnInputSettings settings) + float maxLeverArm, SasTurnInputSettings settings) { UpdateDesiredHeadingOnTurnRelease(requestedTurnInput, currentHeadingDegrees, settings); var headingHoldTurnInput = GetHeadingHoldTurnInput(requestedTurnInput, selfRigidbody, currentHeadingDegrees, settings); if (Mathf.Abs(requestedTurnInput) > settings.TurnReleaseThreshold || - Mathf.Abs(forwardInput) <= Mathf.Epsilon) + (Mathf.Abs(forwardInput) <= Mathf.Epsilon && Mathf.Abs(horizontalInput) <= Mathf.Epsilon)) return headingHoldTurnInput; - var forwardCompensation = CalculateForwardThrustCompensationTurnInput(forwardInput, engines, shipForward, + var forwardCompensation = CalculateThrustCompensationTurnInput(forwardInput, horizontalInput, engines, + shipForward, centerOfMass, maxLeverArm, settings); var withForwardCompensation = headingHoldTurnInput + forwardCompensation * settings.ForwardCompensationStrength; @@ -37,7 +39,7 @@ public float ResolveTurnInput(float requestedTurnInput, float forwardInput, Rigi } private void UpdateDesiredHeadingOnTurnRelease(float requestedTurnInput, float currentHeadingDegrees, - in SasTurnInputSettings settings) + SasTurnInputSettings settings) { CaptureCurrentHeadingIfNeeded(currentHeadingDegrees); @@ -49,7 +51,7 @@ private void UpdateDesiredHeadingOnTurnRelease(float requestedTurnInput, float c } private float GetHeadingHoldTurnInput(float requestedTurnInput, Rigidbody2D selfRigidbody, - float currentHeadingDegrees, in SasTurnInputSettings settings) + float currentHeadingDegrees, SasTurnInputSettings settings) { if (Mathf.Abs(requestedTurnInput) > settings.TurnReleaseThreshold) return requestedTurnInput; @@ -66,8 +68,9 @@ private float GetHeadingHoldTurnInput(float requestedTurnInput, Rigidbody2D self return Mathf.Clamp(turnCorrection, -settings.MaxTurnInput, settings.MaxTurnInput); } - private float CalculateForwardThrustCompensationTurnInput(float forwardInput, IReadOnlyList engines, - Vector2 shipForward, Vector2 centerOfMass, float maxLeverArm, in SasTurnInputSettings settings) + private static float CalculateThrustCompensationTurnInput(float forwardInput, float horizontalInput, + IReadOnlyList engines, + Vector2 shipForward, Vector2 centerOfMass, float maxLeverArm, SasTurnInputSettings settings) { if (engines.Count == 0) return 0f; @@ -75,14 +78,14 @@ private float CalculateForwardThrustCompensationTurnInput(float forwardInput, IR const float sampleTurnInput = 0.2f; var baselineTorque = EngineDirectionSolver.EstimateNetTorqueForTurnInput(engines, shipForward, - centerOfMass, maxLeverArm, forwardInput, 0f); + centerOfMass, maxLeverArm, forwardInput, horizontalInput, 0f); if (Mathf.Abs(baselineTorque) <= 0.0001f) return 0f; var positiveSampleTorque = EngineDirectionSolver.EstimateNetTorqueForTurnInput(engines, shipForward, - centerOfMass, maxLeverArm, forwardInput, sampleTurnInput); + centerOfMass, maxLeverArm, forwardInput, horizontalInput, sampleTurnInput); var negativeSampleTorque = EngineDirectionSolver.EstimateNetTorqueForTurnInput(engines, shipForward, - centerOfMass, maxLeverArm, forwardInput, -sampleTurnInput); + centerOfMass, maxLeverArm, forwardInput, horizontalInput, -sampleTurnInput); var torqueSlope = (positiveSampleTorque - negativeSampleTorque) / (sampleTurnInput * 2f); if (Mathf.Abs(torqueSlope) <= 0.0001f) diff --git a/Assets/Scripts/Ships/Tests/ShipControlAllocatorThrustTests.cs b/Assets/Scripts/Ships/Tests/ShipControlAllocatorThrustTests.cs index 1e59ef05..fcd5efd1 100644 --- a/Assets/Scripts/Ships/Tests/ShipControlAllocatorThrustTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipControlAllocatorThrustTests.cs @@ -33,7 +33,7 @@ public IEnumerator ForwardInput_OneRearEngine_UsesAtLeastNinetyPercentThrust() yield return WaitForLifecycle(); shipWithEngines.Ship.ConfigureAllocatorForTesting(true); - shipWithEngines.Ship.ApplyEngineForcesForTesting(1f, 0f, 0.02f); + shipWithEngines.Ship.ApplyEngineForcesForTesting(1f, 0f, 0f, 0.02f); Assert.That(shipWithEngines.Engines[0].CurrentThrustRatioForTesting, Is.GreaterThanOrEqualTo(0.9f)); } @@ -58,7 +58,7 @@ public IEnumerator BackwardInput_BackwardFacingEngine_UsesAtLeastNinetyPercentTh yield return WaitForLifecycle(); shipWithEngines.Ship.ConfigureAllocatorForTesting(true); - shipWithEngines.Ship.ApplyEngineForcesForTesting(-1f, 0f, 0.02f); + shipWithEngines.Ship.ApplyEngineForcesForTesting(-1f, 0f, 0f, 0.02f); Assert.That(shipWithEngines.Engines[0].CurrentThrustRatioForTesting, Is.GreaterThanOrEqualTo(0.9f)); } @@ -78,12 +78,31 @@ public IEnumerator ForwardInput_FiveHighThrustWingEngines_UsesAtLeastNinetyPerce shipWithEngines.Ship.ConfigureAllocatorForTesting(true, 14, 1f, 0.4f, 0.02f); - shipWithEngines.Ship.ApplyEngineForcesForTesting(1f, 0f, 0.02f); + shipWithEngines.Ship.ApplyEngineForcesForTesting(1f, 0f, 0f, 0.02f); foreach (var engine in shipWithEngines.Engines) Assert.That(engine.CurrentThrustRatioForTesting, Is.GreaterThanOrEqualTo(0.9f)); } + [UnityTest] + public IEnumerator HorizontalInput_OneRearEngine_UsesAtLeastNinetyPercentThrust() + { + var shipWithEngines = CreateShipWithEngines( + new EngineSpec + { + LocalPosition = new Vector2(0f, -5f), + LocalRotationZ = 0f, + MaxThrust = 10f + }); + + yield return WaitForLifecycle(); + + shipWithEngines.Ship.ConfigureAllocatorForTesting(true); + shipWithEngines.Ship.ApplyEngineForcesForTesting(0f, 1f, 0f, 0.02f); + + Assert.That(shipWithEngines.Engines[0].CurrentThrustRatioForTesting, Is.GreaterThanOrEqualTo(0.9f)); + } + [UnityTest] public IEnumerator BackwardInput_ForwardFacingEngine_UsesAtMostTenPercentThrust() { @@ -104,7 +123,7 @@ public IEnumerator BackwardInput_ForwardFacingEngine_UsesAtMostTenPercentThrust( yield return WaitForLifecycle(); shipWithEngines.Ship.ConfigureAllocatorForTesting(true); - shipWithEngines.Ship.ApplyEngineForcesForTesting(-1f, 0f, 0.02f); + shipWithEngines.Ship.ApplyEngineForcesForTesting(-1f, 0f, 0f, 0.02f); Assert.That(shipWithEngines.Engines[1].CurrentThrustRatioForTesting, Is.LessThanOrEqualTo(0.1f)); } diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/MovableShipTestProxy.cs b/Assets/Scripts/Ships/Tests/TestHelpers/MovableShipTestProxy.cs index 4fd4698f..d5547a7f 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/MovableShipTestProxy.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/MovableShipTestProxy.cs @@ -5,18 +5,21 @@ namespace Ships.Tests.TestHelpers public sealed class MovableShipTestProxy : Ship { public float ForwardInput { get; set; } + public float HorizontalInput { get; set; } public float TurnInput { get; set; } public bool SasEnabled { get; set; } protected override void ReadMovementInput() { PendingForwardInput = ForwardInput; + PendingHorizontalInput = HorizontalInput; PendingTurnInput = TurnInput; } protected override void ApplyMovementPhysics() { - MarkEnginesActivity(ApplyEngineForces(PendingForwardInput, PendingTurnInput, Time.fixedDeltaTime, + MarkEnginesActivity(ApplyEngineForces(PendingForwardInput, PendingHorizontalInput, PendingTurnInput, + Time.fixedDeltaTime, SasEnabled)); } } diff --git a/ProjectSettings/InputManager.asset b/ProjectSettings/InputManager.asset index b16147e9..19c85758 100644 --- a/ProjectSettings/InputManager.asset +++ b/ProjectSettings/InputManager.asset @@ -21,6 +21,22 @@ InputManager: type: 0 axis: 0 joyNum: 0 + - serializedVersion: 3 + m_Name: Roll + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: q + altPositiveButton: e + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 - serializedVersion: 3 m_Name: Vertical descriptiveName: @@ -485,3 +501,4 @@ InputManager: type: 2 axis: 5 joyNum: 0 + m_UsePhysicalKeys: 1 From e7c8a12f2e276ddbd83033030eb5356c3f959bb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kub=C5=9B?= Date: Wed, 10 Jun 2026 22:11:18 +0200 Subject: [PATCH 2/3] fix(ships): check if spawn explosion on all connection points --- Assets/Scripts/Core/Constants/GameplayConstants.cs | 2 +- Assets/Scripts/Ships/Modules/Module.cs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Assets/Scripts/Core/Constants/GameplayConstants.cs b/Assets/Scripts/Core/Constants/GameplayConstants.cs index ac8b8fd5..479533ab 100644 --- a/Assets/Scripts/Core/Constants/GameplayConstants.cs +++ b/Assets/Scripts/Core/Constants/GameplayConstants.cs @@ -10,6 +10,6 @@ public static class GameplayConstants /// public const float ModuleDestroyedBelowPixelRatio = 0.15f; - public const float ChanceOfSpawningExplosionOnDetachingConnectionPoint = 0.1f; + public const float ChanceOfSpawningExplosionOnDetachingConnectionPoint = 0.3f; } } \ No newline at end of file diff --git a/Assets/Scripts/Ships/Modules/Module.cs b/Assets/Scripts/Ships/Modules/Module.cs index e18e1c76..61ceea5b 100644 --- a/Assets/Scripts/Ships/Modules/Module.cs +++ b/Assets/Scripts/Ships/Modules/Module.cs @@ -357,22 +357,23 @@ private void DetachConnections(Module otherModule) /// public void DetachAllConnections() { + SpawnExplosionsOnDetachment(_connectionPoints); + foreach (var otherModule in new List(_connections.Keys)) { RemoveConnectionTo(otherModule); if (otherModule) otherModule.RemoveConnectionTo(this); } - SpawnExplosionsOnDetachment(_connectionPoints); - _connectionPoints.Clear(); } private void SpawnExplosionsOnDetachment(Dictionary> connectionPoints) { - foreach (var worldPos in from connectionPoint in connectionPoints.AsValueEnumerable() + foreach (var worldPos in from allConnectionsPoints in connectionPoints.Values.AsValueEnumerable() + from worldPoint in allConnectionsPoints where Random.value < GameplayConstants.ChanceOfSpawningExplosionOnDetachingConnectionPoint - select PixelatedRigidbody.LocalToWorldPoint(connectionPoint.Value[0])) + select PixelatedRigidbody.LocalToWorldPoint(worldPoint)) _effectsSpawner.SpawnExplosion(worldPos); } From 65b93d3d4d86ac4a66d78dd46322fa7f132ea16c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kub=C5=9B?= Date: Wed, 10 Jun 2026 22:50:10 +0200 Subject: [PATCH 3/3] fix(ships): inject missing effects spawner WIP will improve soon with tests refactor --- Assets/Scenes/MainGame.unity | 759 ++---------------- .../Ships/Tests/ModuleConnectionTests.cs | 4 +- .../Tests/ModuleDestructionThresholdTests.cs | 4 +- .../Ships/Tests/ModuleJointLifecycleTests.cs | 2 + .../Tests/ShipControlAllocatorThrustTests.cs | 8 + .../Ships/Tests/ShipCrewAssignmentTests.cs | 2 + .../Ships/Tests/ShipDestroyAllModulesTests.cs | 3 + .../Ships/Tests/ShipDestructionJunkTests.cs | 2 + .../Ships/Tests/ShipDisconnectionTests.cs | 8 + .../Ships/Tests/ShipGameplayMovementTests.cs | 21 +- .../Ships/Tests/ShipSnapshotServiceTests.cs | 6 + .../Ships/Tests/TestHelpers/ShipTestBase.cs | 2 +- .../SmallMovableShipTestFactory.cs | 2 + .../Tests/TestHelpers/TestContainerFactory.cs | 2 +- .../Scripts/Ships/Tests/TestHelpers/Utils.cs | 20 + .../Ships/Tests/TestHelpers/Utils.cs.meta | 3 + .../Scripts/UI/MainGame/ShipStatusPanel.uxml | 15 +- .../UI/MainGame/ShipStatusPanelController.cs | 89 -- 18 files changed, 149 insertions(+), 803 deletions(-) create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Utils.cs create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Utils.cs.meta diff --git a/Assets/Scenes/MainGame.unity b/Assets/Scenes/MainGame.unity index 94ac3af5..7460e54a 100644 --- a/Assets/Scenes/MainGame.unity +++ b/Assets/Scenes/MainGame.unity @@ -199,6 +199,7 @@ Transform: m_Children: - {fileID: 938120423} - {fileID: 2070891737} + - {fileID: 731135735} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &351339372 @@ -527,161 +528,6 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: a23daa814fdcb27409b9213a72216579, type: 3} m_Name: m_EditorClassIdentifier: ---- !u!1 &583050423 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 583050424} - - component: {fileID: 583050425} - - component: {fileID: 583050426} - m_Layer: 5 - m_Name: TopLeft - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &583050424 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 583050423} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1243962500} - m_Father: {fileID: 2081192575} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 214.02966, y: -270.31335} - m_SizeDelta: {x: 428.0594, y: 540.6266} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &583050425 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 583050423} - m_Enabled: 0 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} - m_Name: - m_EditorClassIdentifier: - m_IgnoreReversedGraphics: 1 - m_BlockingObjects: 0 - m_BlockingMask: - serializedVersion: 2 - m_Bits: 4294967295 ---- !u!223 &583050426 -Canvas: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 583050423} - m_Enabled: 1 - serializedVersion: 3 - m_RenderMode: 0 - m_Camera: {fileID: 0} - m_PlaneDistance: 100 - m_PixelPerfect: 0 - m_ReceivesEvents: 1 - m_OverrideSorting: 0 - m_OverridePixelPerfect: 0 - m_SortingBucketNormalizedSize: 0 - m_VertexColorAlwaysGammaSpace: 0 - m_UseReflectionProbes: 0 - m_AdditionalShaderChannelsFlag: 25 - m_UpdateRectTransformForStandalone: 0 - m_SortingLayerID: 0 - m_SortingOrder: 0 - m_TargetDisplay: 0 ---- !u!1 &632147081 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 632147082} - - component: {fileID: 632147083} - - component: {fileID: 632147084} - m_Layer: 5 - m_Name: Image - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &632147082 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 632147081} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1782625163} - m_Father: {fileID: 1379767995} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0} - m_AnchorMax: {x: 0.5, y: 0} - m_AnchoredPosition: {x: 0, y: 104.5} - m_SizeDelta: {x: 265.26, y: 342.4} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &632147083 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 632147081} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 490afd89c4513c7409dee785a2b52262, type: 3} - m_Type: 0 - m_PreserveAspect: 1 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &632147084 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 632147081} - m_CullTransparentMesh: 1 --- !u!1 &642403955 GameObject: m_ObjectHideFlags: 0 @@ -761,6 +607,77 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &731135734 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 731135735} + - component: {fileID: 731135737} + - component: {fileID: 731135736} + m_Layer: 0 + m_Name: PauseMenu + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &731135735 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 731135734} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 256191738} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &731135736 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 731135734} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 19102, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: UnityEngine.dll::UnityEngine.UIElements.UIDocument + m_PanelSettings: {fileID: 11400000, guid: bdbe1f2b7f606d8bca72704a6c95444a, type: 2} + m_ParentUI: {fileID: 0} + sourceAsset: {fileID: 9197481963319205126, guid: e3e0cc16574c4527819a5593fb1c692e, type: 3} + m_SortingOrder: 2 + m_Position: 0 + m_WorldSpaceSizeMode: 1 + m_WorldSpaceWidth: 1920 + m_WorldSpaceHeight: 1080 + m_PivotReferenceSize: 0 + m_Pivot: 0 + m_WorldSpaceCollider: {fileID: 0} +--- !u!114 &731135737 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 731135734} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 92e0c8584fe746a1b4db31f42f6b8eb8, type: 3} + m_Name: + m_EditorClassIdentifier: UI::UI.MainGame.PauseMenuController + uiDocument: {fileID: 731135736} + pointerOverUiChannel: {fileID: 11400000, guid: fe59adb565b6e2758b87bd8eda75cff1, type: 2} + pauseStateChannel: {fileID: 11400000, guid: 74f53e084322486ddb6ba9576741f3e3, type: 2} --- !u!1 &825322231 GameObject: m_ObjectHideFlags: 0 @@ -1108,7 +1025,6 @@ MonoBehaviour: playerShip: {fileID: 4229628396879989915} uiDocument: {fileID: 938120422} pointerOverUiChannel: {fileID: 11400000, guid: fe59adb565b6e2758b87bd8eda75cff1, type: 2} - pauseStateChannel: {fileID: 11400000, guid: 74f53e084322486ddb6ba9576741f3e3, type: 2} barAnimationSpeed: 5 criticalEnergyThreshold: 0.2 --- !u!114 &938120422 @@ -1390,69 +1306,6 @@ Sprite: m_Bones: [] m_ScriptableObjects: [] m_SpriteID: ---- !u!1 &1243962499 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1243962500} - - component: {fileID: 1243962502} - m_Layer: 5 - m_Name: IconHolder - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &1243962500 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1243962499} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1375166404} - m_Father: {fileID: 583050424} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 100.683105, y: -25.191101} - m_SizeDelta: {x: 201.3662, y: 40.22} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1243962502 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1243962499} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Padding: - m_Left: 0 - m_Right: 0 - m_Top: 0 - m_Bottom: 0 - m_ChildAlignment: 0 - m_Spacing: 10 - m_ChildForceExpandWidth: 1 - m_ChildForceExpandHeight: 0 - m_ChildControlWidth: 0 - m_ChildControlHeight: 0 - m_ChildScaleWidth: 0 - m_ChildScaleHeight: 0 - m_ReverseArrangement: 0 --- !u!28 &1315293367 Texture2D: m_ObjectHideFlags: 0 @@ -1499,143 +1352,6 @@ Texture2D: offset: 0 size: 0 path: ---- !u!1 &1375166403 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1375166404} - - component: {fileID: 1375166405} - - component: {fileID: 1375166406} - m_Layer: 5 - m_Name: ReloadingText - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &1375166404 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1375166403} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 1243962500} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 200, y: 40.22} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1375166405 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1375166403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: ^ READY! ^ - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: cada6f9e7a8870b43a0e2746b88c1003, type: 2} - m_sharedMaterial: {fileID: -5390082150881352509, guid: cada6f9e7a8870b43a0e2746b88c1003, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} - m_enableVertexGradient: 0 - m_colorMode: 3 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_StyleSheet: {fileID: 0} - m_TextStyleHashCode: -1183493901 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_fontSize: 36 - m_fontSizeBase: 36 - m_fontWeight: 400 - m_enableAutoSizing: 0 - m_fontSizeMin: 18 - m_fontSizeMax: 72 - m_fontStyle: 0 - m_HorizontalAlignment: 1 - m_VerticalAlignment: 256 - m_textAlignment: 65535 - m_characterSpacing: 0 - m_characterHorizontalScale: 1 - m_wordSpacing: 0 - m_lineSpacing: 0 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_TextWrappingMode: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 0 - m_linkedTextComponent: {fileID: 0} - parentLinkedComponent: {fileID: 0} - m_enableKerning: 0 - m_ActiveFontFeatures: 6e72656b - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_EmojiFallbackSupport: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 1 - m_isCullingEnabled: 0 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: -153.0032, w: 0} - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - m_hasFontAssetChanged: 0 - m_baseMaterial: {fileID: 0} - m_maskOffset: {x: 0, y: 0, z: 0, w: 0} ---- !u!222 &1375166406 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1375166403} - m_CullTransparentMesh: 1 --- !u!1 &1378726334 GameObject: m_ObjectHideFlags: 0 @@ -1682,85 +1398,6 @@ MonoBehaviour: m_EditorClassIdentifier: playerShip: {fileID: 4229628396879989915} hudDocument: {fileID: 938120422} ---- !u!1 &1379767994 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1379767995} - - component: {fileID: 1379767996} - - component: {fileID: 1379767997} - m_Layer: 5 - m_Name: Bottom - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &1379767995 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1379767994} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 632147082} - m_Father: {fileID: 2081192575} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0} - m_AnchorMax: {x: 0.5, y: 0} - m_AnchoredPosition: {x: 0, y: 540} - m_SizeDelta: {x: 1920, y: 1080} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1379767996 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1379767994} - m_Enabled: 0 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} - m_Name: - m_EditorClassIdentifier: - m_IgnoreReversedGraphics: 1 - m_BlockingObjects: 0 - m_BlockingMask: - serializedVersion: 2 - m_Bits: 4294967295 ---- !u!223 &1379767997 -Canvas: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1379767994} - m_Enabled: 1 - serializedVersion: 3 - m_RenderMode: 0 - m_Camera: {fileID: 0} - m_PlaneDistance: 100 - m_PixelPerfect: 0 - m_ReceivesEvents: 1 - m_OverrideSorting: 0 - m_OverridePixelPerfect: 0 - m_SortingBucketNormalizedSize: 0 - m_VertexColorAlwaysGammaSpace: 0 - m_UseReflectionProbes: 0 - m_AdditionalShaderChannelsFlag: 25 - m_UpdateRectTransformForStandalone: 0 - m_SortingLayerID: 0 - m_SortingOrder: 0 - m_TargetDisplay: 0 --- !u!1 &1383913807 GameObject: m_ObjectHideFlags: 0 @@ -2441,143 +2078,6 @@ Texture2D: offset: 0 size: 0 path: ---- !u!1 &1782625162 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1782625163} - - component: {fileID: 1782625164} - - component: {fileID: 1782625165} - m_Layer: 5 - m_Name: Speed - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &1782625163 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1782625162} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 632147082} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 200, y: 50} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1782625164 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1782625162} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: 0.0 - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 612e60bb3cd0fe243a2ba7049a364bdb, type: 2} - m_sharedMaterial: {fileID: -6392427880851853517, guid: 612e60bb3cd0fe243a2ba7049a364bdb, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} - m_enableVertexGradient: 0 - m_colorMode: 3 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_StyleSheet: {fileID: 0} - m_TextStyleHashCode: -1183493901 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_fontSize: 62 - m_fontSizeBase: 60 - m_fontWeight: 400 - m_enableAutoSizing: 1 - m_fontSizeMin: 18 - m_fontSizeMax: 62 - m_fontStyle: 0 - m_HorizontalAlignment: 2 - m_VerticalAlignment: 512 - m_textAlignment: 65535 - m_characterSpacing: 0 - m_characterHorizontalScale: 1 - m_wordSpacing: 0 - m_lineSpacing: 0 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_TextWrappingMode: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 0 - m_linkedTextComponent: {fileID: 0} - parentLinkedComponent: {fileID: 0} - m_enableKerning: 0 - m_ActiveFontFeatures: 6e72656b - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_EmojiFallbackSupport: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 1 - m_isCullingEnabled: 0 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 29.988708, y: -33.90033, z: 29.336792, w: -34.552246} - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - m_hasFontAssetChanged: 0 - m_baseMaterial: {fileID: 0} - m_maskOffset: {x: 0, y: 0, z: 0, w: 0} ---- !u!222 &1782625165 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1782625162} - m_CullTransparentMesh: 1 --- !u!213 &1817160241 Sprite: m_ObjectHideFlags: 0 @@ -2989,7 +2489,7 @@ MonoBehaviour: m_PanelSettings: {fileID: 11400000, guid: bdbe1f2b7f606d8bca72704a6c95444a, type: 2} m_ParentUI: {fileID: 0} sourceAsset: {fileID: 9197481963319205126, guid: b9d361ba943e464c949f26aa2554aa20, type: 3} - m_SortingOrder: 0 + m_SortingOrder: 1 m_Position: 0 m_WorldSpaceSizeMode: 1 m_WorldSpaceWidth: 1920 @@ -3010,110 +2510,6 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: Game.UI::UI.Main.MissionResultUIController uiDocument: {fileID: 2070891738} ---- !u!1 &2081192571 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2081192575} - - component: {fileID: 2081192573} - - component: {fileID: 2081192572} - - component: {fileID: 2081192574} - m_Layer: 5 - m_Name: Canvas - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!114 &2081192572 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2081192571} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} - m_Name: - m_EditorClassIdentifier: - m_IgnoreReversedGraphics: 1 - m_BlockingObjects: 0 - m_BlockingMask: - serializedVersion: 2 - m_Bits: 4294967295 ---- !u!114 &2081192573 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2081192571} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} - m_Name: - m_EditorClassIdentifier: - m_UiScaleMode: 0 - m_ReferencePixelsPerUnit: 100 - m_ScaleFactor: 1 - m_ReferenceResolution: {x: 800, y: 600} - m_ScreenMatchMode: 0 - m_MatchWidthOrHeight: 0 - m_PhysicalUnit: 3 - m_FallbackScreenDPI: 96 - m_DefaultSpriteDPI: 96 - m_DynamicPixelsPerUnit: 1 - m_PresetInfoIsWorld: 0 ---- !u!223 &2081192574 -Canvas: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2081192571} - m_Enabled: 1 - serializedVersion: 3 - m_RenderMode: 0 - m_Camera: {fileID: 0} - m_PlaneDistance: 100 - m_PixelPerfect: 0 - m_ReceivesEvents: 1 - m_OverrideSorting: 0 - m_OverridePixelPerfect: 0 - m_SortingBucketNormalizedSize: 0 - m_VertexColorAlwaysGammaSpace: 0 - m_UseReflectionProbes: 0 - m_AdditionalShaderChannelsFlag: 0 - m_UpdateRectTransformForStandalone: 0 - m_SortingLayerID: 0 - m_SortingOrder: 0 - m_TargetDisplay: 0 ---- !u!224 &2081192575 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2081192571} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0, y: 0, z: 0} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1379767995} - - {fileID: 583050424} - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0, y: 0} --- !u!114 &133733233019135677 MonoBehaviour: m_ObjectHideFlags: 0 @@ -3493,6 +2889,10 @@ PrefabInstance: propertyPath: playerShip value: objectReference: {fileID: 4229628396879989915} + - target: {fileID: 4648251575334767366, guid: cf3e414adef6859f2af6ac1a62b52293, type: 3} + propertyPath: m_Enabled + value: 1 + objectReference: {fileID: 0} - target: {fileID: 8678225184202570128, guid: cf3e414adef6859f2af6ac1a62b52293, type: 3} propertyPath: enemyTeam value: @@ -3560,11 +2960,11 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 8043235518903841380, guid: 73ba02c33057fdee2abc1a92f3596c42, type: 3} propertyPath: m_LocalPosition.x - value: -7.5 + value: -46.2 objectReference: {fileID: 0} - target: {fileID: 8043235518903841380, guid: 73ba02c33057fdee2abc1a92f3596c42, type: 3} propertyPath: m_LocalPosition.y - value: -48.9 + value: -55.2 objectReference: {fileID: 0} - target: {fileID: 8043235518903841380, guid: 73ba02c33057fdee2abc1a92f3596c42, type: 3} propertyPath: m_LocalPosition.z @@ -3648,7 +3048,6 @@ SceneRoots: - {fileID: 1894711975} - {fileID: 642403958} - {fileID: 1465463664} - - {fileID: 2081192575} - {fileID: 857200673} - {fileID: 1384098534} - {fileID: 7506938062858957730} diff --git a/Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs b/Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs index 00a07989..4489fe8a 100644 --- a/Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs +++ b/Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs @@ -47,6 +47,8 @@ public IEnumerator UnrotatedModuleOnRight_ConnectsToCommandModule() var command = shipGo.GetComponentInChildren(); var engine = shipGo.GetComponentInChildren(); + Container.InjectGameObject(shipGo); + return (ship, command, engine); } @@ -74,4 +76,4 @@ private static void AssertModulesConnected(Ship ship, Command command, Engine en "Command module should have connection points to engine"); } } -} +} \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/ModuleDestructionThresholdTests.cs b/Assets/Scripts/Ships/Tests/ModuleDestructionThresholdTests.cs index 5e172ff7..12a94b36 100644 --- a/Assets/Scripts/Ships/Tests/ModuleDestructionThresholdTests.cs +++ b/Assets/Scripts/Ships/Tests/ModuleDestructionThresholdTests.cs @@ -42,6 +42,8 @@ public class ModuleDestructionThresholdTests : ShipTestBase var ship = ModuleFactory.WireShip(shipGo, Container); + Container.InjectGameObject(shipGo); + return (ship, command, other); } @@ -104,4 +106,4 @@ public IEnumerator CommandModuleBelowPixelThreshold_DestroysShip() Assert.IsTrue(shipGo == null, "Ship should be destroyed when its command module falls below the threshold"); } } -} +} \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/ModuleJointLifecycleTests.cs b/Assets/Scripts/Ships/Tests/ModuleJointLifecycleTests.cs index 21ce1ab5..c0f218bb 100644 --- a/Assets/Scripts/Ships/Tests/ModuleJointLifecycleTests.cs +++ b/Assets/Scripts/Ships/Tests/ModuleJointLifecycleTests.cs @@ -37,6 +37,8 @@ public class ModuleJointLifecycleTests : ShipTestBase var ship = ModuleFactory.WireShip(shipGo, Container); + Container.InjectGameObject(shipGo); + return (ship, command, other); } diff --git a/Assets/Scripts/Ships/Tests/ShipControlAllocatorThrustTests.cs b/Assets/Scripts/Ships/Tests/ShipControlAllocatorThrustTests.cs index fcd5efd1..1a90721a 100644 --- a/Assets/Scripts/Ships/Tests/ShipControlAllocatorThrustTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipControlAllocatorThrustTests.cs @@ -93,6 +93,12 @@ public IEnumerator HorizontalInput_OneRearEngine_UsesAtLeastNinetyPercentThrust( LocalPosition = new Vector2(0f, -5f), LocalRotationZ = 0f, MaxThrust = 10f + }, + new EngineSpec + { + LocalPosition = new Vector2(0f, 5f), + LocalRotationZ = 0f, + MaxThrust = 10f }); yield return WaitForLifecycle(); @@ -143,6 +149,8 @@ public IEnumerator BackwardInput_ForwardFacingEngine_UsesAtMostTenPercentThrust( var ship = ModuleFactory.WireShip(shipGo, Container); + Container.InjectGameObject(shipGo); + return (ship, engines); } } diff --git a/Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs b/Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs index 2d263f31..0e11fdee 100644 --- a/Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs @@ -28,6 +28,8 @@ private Ship CreateShipWithModules(params (int crewNeeded, CrewSkillType mainSki config.crewNeeded, config.mainSkill); } + Container.InjectGameObject(shipGo); + return ModuleFactory.WireShip(shipGo, Container); } diff --git a/Assets/Scripts/Ships/Tests/ShipDestroyAllModulesTests.cs b/Assets/Scripts/Ships/Tests/ShipDestroyAllModulesTests.cs index fa5c90de..a06bf398 100644 --- a/Assets/Scripts/Ships/Tests/ShipDestroyAllModulesTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipDestroyAllModulesTests.cs @@ -155,6 +155,9 @@ private Ship CreateShipWithCommandAndEngine() var ship = ModuleFactory.WireShip(shipGo, Container); ship.InitializeModules(); + + Container.InjectGameObject(shipGo); + return ship; } } diff --git a/Assets/Scripts/Ships/Tests/ShipDestructionJunkTests.cs b/Assets/Scripts/Ships/Tests/ShipDestructionJunkTests.cs index 8b6528a5..71179176 100644 --- a/Assets/Scripts/Ships/Tests/ShipDestructionJunkTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipDestructionJunkTests.cs @@ -37,6 +37,8 @@ public class ShipDestructionJunkTests : ShipTestBase var ship = ModuleFactory.WireShip(shipGo, Container); + Container.InjectGameObject(shipGo); + return (ship, command, other); } diff --git a/Assets/Scripts/Ships/Tests/ShipDisconnectionTests.cs b/Assets/Scripts/Ships/Tests/ShipDisconnectionTests.cs index 01102b72..3b0694a6 100644 --- a/Assets/Scripts/Ships/Tests/ShipDisconnectionTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipDisconnectionTests.cs @@ -39,6 +39,8 @@ private TestShipComponents CreateTwoModuleShip(int moduleWidth = 5, int moduleHe var ship = ModuleFactory.WireShip(shipGo, Container); + Container.InjectGameObject(shipGo); + return new TestShipComponents(ship, commandModule, new List { module2 }); } @@ -60,6 +62,8 @@ private TestShipComponents CreateThreeModuleLinearShip(int moduleWidth = 5, int var ship = ModuleFactory.WireShip(shipGo, Container); + Container.InjectGameObject(shipGo); + return new TestShipComponents(ship, commandModule, new List { module2, module3 }); } @@ -89,6 +93,8 @@ private TestShipComponents CreateShipWithAlternatePaths() var ship = ModuleFactory.WireShip(shipGo, Container); + Container.InjectGameObject(shipGo); + return new TestShipComponents(ship, commandModule, new List { moduleA, moduleB, moduleC }); } @@ -114,6 +120,8 @@ private TestShipComponents CreateVerticalThreeModuleShip(int moduleWidth = 5, in var ship = ModuleFactory.WireShip(shipGo, Container); + Container.InjectGameObject(shipGo); + return new TestShipComponents(ship, commandModule, new List { moduleA, moduleC }); } diff --git a/Assets/Scripts/Ships/Tests/ShipGameplayMovementTests.cs b/Assets/Scripts/Ships/Tests/ShipGameplayMovementTests.cs index 90c54427..d0f2d807 100644 --- a/Assets/Scripts/Ships/Tests/ShipGameplayMovementTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipGameplayMovementTests.cs @@ -28,7 +28,7 @@ public IEnumerator Ship_MovesForward_WhenInstructedToMoveForward() ship.TurnInput = 0f; ship.SasEnabled = false; - yield return SimulateForSeconds(MovementSimulationSeconds); + yield return Utils.SimulateForSeconds(MovementSimulationSeconds); var forwardTravel = Vector2.Dot(ship.GetPosition() - startPosition, forward); Assert.That(forwardTravel, Is.GreaterThan(MinForwardDistance), @@ -46,7 +46,7 @@ public IEnumerator Ship_TurnsRight_WhenInstructedToTurnRight() ship.SasEnabled = false; var heading = new HeadingChangeAccumulator(ship); - yield return SimulateForSeconds(MovementSimulationSeconds, heading.Sample); + yield return Utils.SimulateForSeconds(MovementSimulationSeconds, heading.Sample); Assert.That(heading.TotalDegrees, Is.LessThan(-MinTurnDegrees), () => $"Expected right turn > {MinTurnDegrees}°, got {heading.TotalDegrees:F2}°."); @@ -63,7 +63,7 @@ public IEnumerator Ship_TurnsLeft_WhenInstructedToTurnLeft() ship.SasEnabled = false; var heading = new HeadingChangeAccumulator(ship); - yield return SimulateForSeconds(MovementSimulationSeconds, heading.Sample); + yield return Utils.SimulateForSeconds(MovementSimulationSeconds, heading.Sample); Assert.That(heading.TotalDegrees, Is.GreaterThan(MinTurnDegrees), () => $"Expected left turn > {MinTurnDegrees}°, got {heading.TotalDegrees:F2}°."); @@ -79,13 +79,13 @@ public IEnumerator Ship_SasReachesWithinOnePercentOfDesiredHeading_AfterFiveSeco ship.TurnInput = 0f; ship.SasEnabled = true; - yield return SimulateForSeconds(SasSettleSeconds); + yield return Utils.SimulateForSeconds(SasSettleSeconds); var headingBeforeTargetChange = ship.GetHeadingDegreesForTesting(); var targetHeading = headingBeforeTargetChange + SasHeadingOffsetDegrees; ship.SetSasDesiredHeadingForTesting(targetHeading); - yield return SimulateForSeconds(SasSettleSeconds); + yield return Utils.SimulateForSeconds(SasSettleSeconds); var headingError = Mathf.Abs(Mathf.DeltaAngle(ship.GetHeadingDegreesForTesting(), targetHeading)); var allowedError = Mathf.Abs(SasHeadingOffsetDegrees) * 0.02f; @@ -100,17 +100,6 @@ private MovableShipTestProxy CreateReadyShip() return SmallMovableShipTestFactory.Create(Container, CreatedObjects); } - private static IEnumerator SimulateForSeconds(float seconds, System.Action onFixedStep = null) - { - var elapsed = 0f; - while (elapsed < seconds) - { - yield return new WaitForFixedUpdate(); - elapsed += Time.fixedDeltaTime; - onFixedStep?.Invoke(); - } - } - private sealed class HeadingChangeAccumulator { private readonly MovableShipTestProxy _ship; diff --git a/Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs b/Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs index 0b1afb45..35889202 100644 --- a/Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs @@ -170,6 +170,9 @@ private Ship CreateShipWithCommandAndCannon(GameObject cannonPrefab, string arch var ship = ModuleFactory.WireShip(shipGo, Container); ship.InitializeModules(); + + Container.InjectGameObject(shipGo); + return ship; } @@ -193,6 +196,9 @@ private Ship CreateShipWithScratchEngine() var ship = ModuleFactory.WireShip(shipGo, Container); ship.InitializeModules(); + + Container.InjectGameObject(shipGo); + return ship; } diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/ShipTestBase.cs b/Assets/Scripts/Ships/Tests/TestHelpers/ShipTestBase.cs index b3ccc527..014cb695 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/ShipTestBase.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/ShipTestBase.cs @@ -20,7 +20,7 @@ public virtual void SetUp() { TestRoot = new GameObject("TestRoot"); CreatedObjects.Add(TestRoot); - Container = TestContainerFactory.CreateTestContainer(TestRoot.transform); + Container = TestContainerFactory.CreateTestContainer(); } [TearDown] diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/SmallMovableShipTestFactory.cs b/Assets/Scripts/Ships/Tests/TestHelpers/SmallMovableShipTestFactory.cs index 04cb98dd..8b9bd921 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/SmallMovableShipTestFactory.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/SmallMovableShipTestFactory.cs @@ -36,6 +36,8 @@ public static MovableShipTestProxy Create(DiContainer container, ICollection