add test
1. MaxTargets 上限 2. 战斗中开关不生效 3. AOE 使用“请求时快照”而不是结算时实时状态
This commit is contained in:
parent
76094b711b
commit
2e4108aebc
|
|
@ -67,8 +67,11 @@ namespace CustomComponent
|
||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
GameEntry.Event.Unsubscribe(ShowEntitySuccessEventArgs.EventId, OnShowEntitySuccess);
|
if (GameEntry.Event != null)
|
||||||
GameEntry.Event.Unsubscribe(HideEntityCompleteEventArgs.EventId, OnHideEntityComplete);
|
{
|
||||||
|
GameEntry.Event.Unsubscribe(ShowEntitySuccessEventArgs.EventId, OnShowEntitySuccess);
|
||||||
|
GameEntry.Event.Unsubscribe(HideEntityCompleteEventArgs.EventId, OnHideEntityComplete);
|
||||||
|
}
|
||||||
|
|
||||||
_enemies = null;
|
_enemies = null;
|
||||||
_enemyById = null;
|
_enemyById = null;
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace Simulation.Tests.Editor
|
namespace Simulation.Tests.Editor
|
||||||
{
|
{
|
||||||
public class SimulationWorldTickTests
|
public class SimulationWorldTickTests
|
||||||
{
|
{
|
||||||
private const string GameAssemblyName = "Assembly-CSharp";
|
private const string GameAssemblyName = "Assembly-CSharp";
|
||||||
|
private const string RuntimeAssemblyName = "UnityGameFramework.Runtime";
|
||||||
private const BindingFlags PublicStatic = BindingFlags.Public | BindingFlags.Static;
|
private const BindingFlags PublicStatic = BindingFlags.Public | BindingFlags.Static;
|
||||||
private const BindingFlags PublicInstance = BindingFlags.Public | BindingFlags.Instance;
|
private const BindingFlags PublicInstance = BindingFlags.Public | BindingFlags.Instance;
|
||||||
private const BindingFlags NonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance;
|
private const BindingFlags NonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance;
|
||||||
|
private const BindingFlags NonPublicStatic = BindingFlags.NonPublic | BindingFlags.Static;
|
||||||
|
|
||||||
private static readonly System.Type SimulationWorldType =
|
private static readonly System.Type SimulationWorldType =
|
||||||
System.Type.GetType($"Simulation.SimulationWorld, {GameAssemblyName}");
|
System.Type.GetType($"Simulation.SimulationWorld, {GameAssemblyName}");
|
||||||
|
|
@ -38,6 +43,39 @@ namespace Simulation.Tests.Editor
|
||||||
private static readonly System.Type EnemySeparationSolverProviderType =
|
private static readonly System.Type EnemySeparationSolverProviderType =
|
||||||
System.Type.GetType($"CustomUtility.EnemySeparationSolverProvider, {GameAssemblyName}");
|
System.Type.GetType($"CustomUtility.EnemySeparationSolverProvider, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type EnemyManagerComponentType =
|
||||||
|
System.Type.GetType($"CustomComponent.EnemyManagerComponent, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type PlayerType =
|
||||||
|
System.Type.GetType($"Entity.Player, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type EntityBaseType =
|
||||||
|
System.Type.GetType($"Entity.EntityBase, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type HealthComponentType =
|
||||||
|
System.Type.GetType($"Components.HealthComponent, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type EntityLogicType =
|
||||||
|
System.Type.GetType($"UnityGameFramework.Runtime.EntityLogic, {RuntimeAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type ProcedureComponentType =
|
||||||
|
System.Type.GetType($"UnityGameFramework.Runtime.ProcedureComponent, {RuntimeAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type ProcedureGameType =
|
||||||
|
System.Type.GetType($"Procedure.ProcedureGame, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type GameStateTypeType =
|
||||||
|
System.Type.GetType($"Procedure.GameStateType, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type ProcedureManagerType =
|
||||||
|
System.Type.GetType("GameFramework.Procedure.ProcedureManager, GameFramework");
|
||||||
|
|
||||||
|
private static readonly System.Type ProcedureManagerInterfaceType =
|
||||||
|
System.Type.GetType("GameFramework.Procedure.IProcedureManager, GameFramework");
|
||||||
|
|
||||||
|
private static readonly System.Type FsmOpenGenericType =
|
||||||
|
System.Type.GetType("GameFramework.Fsm.Fsm`1, GameFramework");
|
||||||
|
|
||||||
private static readonly MethodInfo UpsertEnemyMethod =
|
private static readonly MethodInfo UpsertEnemyMethod =
|
||||||
SimulationWorldType?.GetMethod("UpsertEnemy", NonPublicInstance);
|
SimulationWorldType?.GetMethod("UpsertEnemy", NonPublicInstance);
|
||||||
|
|
||||||
|
|
@ -59,6 +97,9 @@ namespace Simulation.Tests.Editor
|
||||||
private static readonly MethodInfo TryGetNearestEnemyEntityIdMethod =
|
private static readonly MethodInfo TryGetNearestEnemyEntityIdMethod =
|
||||||
SimulationWorldType?.GetMethod("TryGetNearestEnemyEntityId", PublicInstance);
|
SimulationWorldType?.GetMethod("TryGetNearestEnemyEntityId", PublicInstance);
|
||||||
|
|
||||||
|
private static readonly MethodInfo TryEnqueueAreaCollisionQueryMethod =
|
||||||
|
SimulationWorldType?.GetMethod("TryEnqueueAreaCollisionQuery", PublicInstance);
|
||||||
|
|
||||||
private static readonly MethodInfo SetUseSimulationMovementMethod =
|
private static readonly MethodInfo SetUseSimulationMovementMethod =
|
||||||
SimulationWorldType?.GetMethod("SetUseSimulationMovement", PublicInstance);
|
SimulationWorldType?.GetMethod("SetUseSimulationMovement", PublicInstance);
|
||||||
|
|
||||||
|
|
@ -89,6 +130,21 @@ namespace Simulation.Tests.Editor
|
||||||
private static readonly PropertyInfo CollisionCandidateCountProperty =
|
private static readonly PropertyInfo CollisionCandidateCountProperty =
|
||||||
SimulationWorldType?.GetProperty("CollisionCandidateCount", PublicInstance);
|
SimulationWorldType?.GetProperty("CollisionCandidateCount", PublicInstance);
|
||||||
|
|
||||||
|
private static readonly PropertyInfo UseSimulationMovementProperty =
|
||||||
|
SimulationWorldType?.GetProperty("UseSimulationMovement", PublicInstance);
|
||||||
|
|
||||||
|
private static readonly PropertyInfo UseJobSimulationProperty =
|
||||||
|
SimulationWorldType?.GetProperty("UseJobSimulation", PublicInstance);
|
||||||
|
|
||||||
|
private static readonly PropertyInfo LastResolvedAreaHitCountProperty =
|
||||||
|
SimulationWorldType?.GetProperty("LastResolvedAreaHitCount", PublicInstance);
|
||||||
|
|
||||||
|
private static readonly FieldInfo CollisionQueryInputsField =
|
||||||
|
SimulationWorldType?.GetField("_collisionQueryInputs", NonPublicInstance);
|
||||||
|
|
||||||
|
private static readonly FieldInfo AreaCollisionRequestsField =
|
||||||
|
SimulationWorldType?.GetField("_areaCollisionRequests", NonPublicInstance);
|
||||||
|
|
||||||
private static readonly MethodInfo EnemyProjectileOnUpdateMethod =
|
private static readonly MethodInfo EnemyProjectileOnUpdateMethod =
|
||||||
EnemyProjectileType?.GetMethod("OnUpdate", NonPublicInstance);
|
EnemyProjectileType?.GetMethod("OnUpdate", NonPublicInstance);
|
||||||
|
|
||||||
|
|
@ -110,6 +166,27 @@ namespace Simulation.Tests.Editor
|
||||||
private static readonly MethodInfo GameEntrySetSimulationWorldMethod =
|
private static readonly MethodInfo GameEntrySetSimulationWorldMethod =
|
||||||
GameEntrySimulationWorldProperty?.GetSetMethod(true);
|
GameEntrySimulationWorldProperty?.GetSetMethod(true);
|
||||||
|
|
||||||
|
private static readonly PropertyInfo GameEntryEnemyManagerProperty =
|
||||||
|
GameEntryType?.GetProperty("EnemyManager", PublicStatic);
|
||||||
|
|
||||||
|
private static readonly MethodInfo GameEntryGetEnemyManagerMethod =
|
||||||
|
GameEntryEnemyManagerProperty?.GetGetMethod(true);
|
||||||
|
|
||||||
|
private static readonly MethodInfo GameEntrySetEnemyManagerMethod =
|
||||||
|
GameEntryEnemyManagerProperty?.GetSetMethod(true);
|
||||||
|
|
||||||
|
private static readonly PropertyInfo GameEntryProcedureProperty =
|
||||||
|
GameEntryType?.GetProperty("Procedure", PublicStatic);
|
||||||
|
|
||||||
|
private static readonly MethodInfo GameEntryGetProcedureMethod =
|
||||||
|
GameEntryProcedureProperty?.GetGetMethod(true);
|
||||||
|
|
||||||
|
private static readonly MethodInfo GameEntrySetProcedureMethod =
|
||||||
|
GameEntryProcedureProperty?.GetSetMethod(true);
|
||||||
|
|
||||||
|
private static readonly MethodInfo HealthComponentOnInitMethod =
|
||||||
|
HealthComponentType?.GetMethod("OnInit", PublicInstance);
|
||||||
|
|
||||||
private static readonly FieldInfo ProjectileMaxDistanceFromPlayerField =
|
private static readonly FieldInfo ProjectileMaxDistanceFromPlayerField =
|
||||||
SimulationWorldType?.GetField("_projectileMaxDistanceFromPlayer", NonPublicInstance);
|
SimulationWorldType?.GetField("_projectileMaxDistanceFromPlayer", NonPublicInstance);
|
||||||
|
|
||||||
|
|
@ -131,6 +208,17 @@ namespace Simulation.Tests.Editor
|
||||||
Assert.NotNull(CampTypeType, "CampType type lookup failed.");
|
Assert.NotNull(CampTypeType, "CampType type lookup failed.");
|
||||||
Assert.NotNull(GameEntryType, "GameEntry type lookup failed.");
|
Assert.NotNull(GameEntryType, "GameEntry type lookup failed.");
|
||||||
Assert.NotNull(EnemySeparationSolverProviderType, "EnemySeparationSolverProvider type lookup failed.");
|
Assert.NotNull(EnemySeparationSolverProviderType, "EnemySeparationSolverProvider type lookup failed.");
|
||||||
|
Assert.NotNull(EnemyManagerComponentType, "EnemyManagerComponent type lookup failed.");
|
||||||
|
Assert.NotNull(PlayerType, "Player type lookup failed.");
|
||||||
|
Assert.NotNull(EntityBaseType, "EntityBase type lookup failed.");
|
||||||
|
Assert.NotNull(HealthComponentType, "HealthComponent type lookup failed.");
|
||||||
|
Assert.NotNull(EntityLogicType, "EntityLogic type lookup failed.");
|
||||||
|
Assert.NotNull(ProcedureComponentType, "ProcedureComponent type lookup failed.");
|
||||||
|
Assert.NotNull(ProcedureGameType, "ProcedureGame type lookup failed.");
|
||||||
|
Assert.NotNull(GameStateTypeType, "GameStateType type lookup failed.");
|
||||||
|
Assert.NotNull(ProcedureManagerType, "ProcedureManager type lookup failed.");
|
||||||
|
Assert.NotNull(ProcedureManagerInterfaceType, "IProcedureManager type lookup failed.");
|
||||||
|
Assert.NotNull(FsmOpenGenericType, "Fsm`1 type lookup failed.");
|
||||||
Assert.NotNull(UpsertEnemyMethod, "UpsertEnemy reflection lookup failed.");
|
Assert.NotNull(UpsertEnemyMethod, "UpsertEnemy reflection lookup failed.");
|
||||||
Assert.NotNull(RemoveEnemyByEntityIdMethod, "RemoveEnemyByEntityId reflection lookup failed.");
|
Assert.NotNull(RemoveEnemyByEntityIdMethod, "RemoveEnemyByEntityId reflection lookup failed.");
|
||||||
Assert.NotNull(UpsertProjectileMethod, "UpsertProjectile reflection lookup failed.");
|
Assert.NotNull(UpsertProjectileMethod, "UpsertProjectile reflection lookup failed.");
|
||||||
|
|
@ -138,6 +226,7 @@ namespace Simulation.Tests.Editor
|
||||||
Assert.NotNull(TryGetEnemyDataMethod, "TryGetEnemyData reflection lookup failed.");
|
Assert.NotNull(TryGetEnemyDataMethod, "TryGetEnemyData reflection lookup failed.");
|
||||||
Assert.NotNull(TickMethod, "Tick reflection lookup failed.");
|
Assert.NotNull(TickMethod, "Tick reflection lookup failed.");
|
||||||
Assert.NotNull(TryGetNearestEnemyEntityIdMethod, "TryGetNearestEnemyEntityId reflection lookup failed.");
|
Assert.NotNull(TryGetNearestEnemyEntityIdMethod, "TryGetNearestEnemyEntityId reflection lookup failed.");
|
||||||
|
Assert.NotNull(TryEnqueueAreaCollisionQueryMethod, "TryEnqueueAreaCollisionQuery reflection lookup failed.");
|
||||||
Assert.NotNull(SetUseSimulationMovementMethod, "SetUseSimulationMovement reflection lookup failed.");
|
Assert.NotNull(SetUseSimulationMovementMethod, "SetUseSimulationMovement reflection lookup failed.");
|
||||||
Assert.NotNull(SetUseJobSimulationMethod, "SetUseJobSimulation reflection lookup failed.");
|
Assert.NotNull(SetUseJobSimulationMethod, "SetUseJobSimulation reflection lookup failed.");
|
||||||
Assert.NotNull(SetUseBurstJobsMethod, "SetUseBurstJobs reflection lookup failed.");
|
Assert.NotNull(SetUseBurstJobsMethod, "SetUseBurstJobs reflection lookup failed.");
|
||||||
|
|
@ -146,6 +235,11 @@ namespace Simulation.Tests.Editor
|
||||||
Assert.NotNull(EnemiesProperty, "Enemies property reflection lookup failed.");
|
Assert.NotNull(EnemiesProperty, "Enemies property reflection lookup failed.");
|
||||||
Assert.NotNull(ProjectilesProperty, "Projectiles property reflection lookup failed.");
|
Assert.NotNull(ProjectilesProperty, "Projectiles property reflection lookup failed.");
|
||||||
Assert.NotNull(CollisionCandidateCountProperty, "CollisionCandidateCount property reflection lookup failed.");
|
Assert.NotNull(CollisionCandidateCountProperty, "CollisionCandidateCount property reflection lookup failed.");
|
||||||
|
Assert.NotNull(UseSimulationMovementProperty, "UseSimulationMovement property reflection lookup failed.");
|
||||||
|
Assert.NotNull(UseJobSimulationProperty, "UseJobSimulation property reflection lookup failed.");
|
||||||
|
Assert.NotNull(LastResolvedAreaHitCountProperty, "LastResolvedAreaHitCount property reflection lookup failed.");
|
||||||
|
Assert.NotNull(CollisionQueryInputsField, "Collision query inputs field reflection lookup failed.");
|
||||||
|
Assert.NotNull(AreaCollisionRequestsField, "Area collision requests field reflection lookup failed.");
|
||||||
Assert.NotNull(ProjectileMaxDistanceFromPlayerField,
|
Assert.NotNull(ProjectileMaxDistanceFromPlayerField,
|
||||||
"Projectile max distance field reflection lookup failed.");
|
"Projectile max distance field reflection lookup failed.");
|
||||||
Assert.NotNull(ProjectileMaxVerticalOffsetFromPlayerField,
|
Assert.NotNull(ProjectileMaxVerticalOffsetFromPlayerField,
|
||||||
|
|
@ -160,6 +254,13 @@ namespace Simulation.Tests.Editor
|
||||||
"GameEntry.SimulationWorld getter reflection lookup failed.");
|
"GameEntry.SimulationWorld getter reflection lookup failed.");
|
||||||
Assert.NotNull(GameEntrySetSimulationWorldMethod,
|
Assert.NotNull(GameEntrySetSimulationWorldMethod,
|
||||||
"GameEntry.SimulationWorld setter reflection lookup failed.");
|
"GameEntry.SimulationWorld setter reflection lookup failed.");
|
||||||
|
Assert.NotNull(GameEntryEnemyManagerProperty, "GameEntry.EnemyManager property lookup failed.");
|
||||||
|
Assert.NotNull(GameEntryGetEnemyManagerMethod, "GameEntry.EnemyManager getter reflection lookup failed.");
|
||||||
|
Assert.NotNull(GameEntrySetEnemyManagerMethod, "GameEntry.EnemyManager setter reflection lookup failed.");
|
||||||
|
Assert.NotNull(GameEntryProcedureProperty, "GameEntry.Procedure property lookup failed.");
|
||||||
|
Assert.NotNull(GameEntryGetProcedureMethod, "GameEntry.Procedure getter reflection lookup failed.");
|
||||||
|
Assert.NotNull(GameEntrySetProcedureMethod, "GameEntry.Procedure setter reflection lookup failed.");
|
||||||
|
Assert.NotNull(HealthComponentOnInitMethod, "HealthComponent.OnInit reflection lookup failed.");
|
||||||
|
|
||||||
_worldGameObject = new GameObject("SimulationWorldTickTests");
|
_worldGameObject = new GameObject("SimulationWorldTickTests");
|
||||||
_worldComponent = _worldGameObject.AddComponent(SimulationWorldType);
|
_worldComponent = _worldGameObject.AddComponent(SimulationWorldType);
|
||||||
|
|
@ -563,6 +664,112 @@ namespace Simulation.Tests.Editor
|
||||||
Assert.That(GetProjectilesCount(), Is.EqualTo(0));
|
Assert.That(GetProjectilesCount(), Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TickProjectiles_LimitsCandidatesToMaxTargets_IncludingPlayerCandidate()
|
||||||
|
{
|
||||||
|
SetUseJobSimulationMethod.Invoke(_worldComponent, new object[] { true });
|
||||||
|
object previousEnemyManager = GetGameEntryEnemyManager();
|
||||||
|
GameObject enemyManagerObject = new GameObject("EnemyManagerMaxTargetsEditMode");
|
||||||
|
GameObject playerObject = new GameObject("PlayerTargetMaxTargetsEditMode");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Component enemyManager = enemyManagerObject.AddComponent(EnemyManagerComponentType);
|
||||||
|
Component player = playerObject.AddComponent(PlayerType);
|
||||||
|
Component healthComponent = playerObject.AddComponent(HealthComponentType);
|
||||||
|
HealthComponentOnInitMethod.Invoke(healthComponent, new object[] { 100, null });
|
||||||
|
SetPrivateField(player, "_healthComponent", healthComponent);
|
||||||
|
SetPrivateField(player, "m_CachedTransform", playerObject.transform);
|
||||||
|
SetPrivateField(player, "m_Available", true);
|
||||||
|
|
||||||
|
object enemyById = Activator.CreateInstance(typeof(Dictionary<,>).MakeGenericType(typeof(int), EntityBaseType));
|
||||||
|
enemyById.GetType().GetMethod("Add")?.Invoke(enemyById, new object[] { -1, player });
|
||||||
|
object enemies = Activator.CreateInstance(typeof(List<>).MakeGenericType(EntityBaseType));
|
||||||
|
enemies.GetType().GetMethod("Add")?.Invoke(enemies, new object[] { player });
|
||||||
|
SetPrivateField(enemyManager, "_enemyById", enemyById);
|
||||||
|
SetPrivateField(enemyManager, "_enemies", enemies);
|
||||||
|
SetGameEntryEnemyManager(enemyManager);
|
||||||
|
|
||||||
|
UpsertEnemy(CreateEnemy(entityId: 5221, position: Vector3.zero, speed: 0f, attackRange: 1f));
|
||||||
|
UpsertProjectile(CreateProjectile(entityId: 5222, position: Vector3.zero, forward: Vector3.forward,
|
||||||
|
velocity: Vector3.zero, speed: 0f, lifeTime: 1f, age: 0f, active: true, remainingLifetime: 1f,
|
||||||
|
state: 0));
|
||||||
|
|
||||||
|
InvokeTick(deltaTime: 0.016f, realDeltaTime: 0.016f, playerPosition: Vector3.zero);
|
||||||
|
|
||||||
|
Assert.That(GetCollisionCandidateCount(), Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SetGameEntryEnemyManager(previousEnemyManager);
|
||||||
|
Object.DestroyImmediate(enemyManagerObject);
|
||||||
|
Object.DestroyImmediate(playerObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SetUseSimulationAndJob_AreIgnored_WhenBattleStateIsActive()
|
||||||
|
{
|
||||||
|
SetUseSimulationMovementMethod.Invoke(_worldComponent, new object[] { true });
|
||||||
|
SetUseJobSimulationMethod.Invoke(_worldComponent, new object[] { false });
|
||||||
|
|
||||||
|
object previousProcedure = GetGameEntryProcedure();
|
||||||
|
GameObject procedureObject = new GameObject("ProcedureGuardEditMode");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Component procedureComponent = procedureObject.AddComponent(ProcedureComponentType);
|
||||||
|
object procedureManager = Activator.CreateInstance(ProcedureManagerType);
|
||||||
|
Type fsmType = FsmOpenGenericType.MakeGenericType(ProcedureManagerInterfaceType);
|
||||||
|
object fsm = Activator.CreateInstance(fsmType);
|
||||||
|
object procedureGame = Activator.CreateInstance(ProcedureGameType);
|
||||||
|
object battleState = Enum.Parse(GameStateTypeType, "Battle");
|
||||||
|
|
||||||
|
SetPrivateField(procedureGame, "_currentGameState", battleState);
|
||||||
|
SetPrivateField(fsm, "m_CurrentState", procedureGame);
|
||||||
|
SetPrivateField(procedureManager, "m_ProcedureFsm", fsm);
|
||||||
|
SetPrivateField(procedureComponent, "m_ProcedureManager", procedureManager);
|
||||||
|
SetGameEntryProcedure(procedureComponent);
|
||||||
|
|
||||||
|
SetUseSimulationMovementMethod.Invoke(_worldComponent, new object[] { false });
|
||||||
|
SetUseJobSimulationMethod.Invoke(_worldComponent, new object[] { true });
|
||||||
|
|
||||||
|
Assert.IsTrue((bool)UseSimulationMovementProperty.GetValue(_worldComponent));
|
||||||
|
Assert.IsFalse((bool)UseJobSimulationProperty.GetValue(_worldComponent));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SetGameEntryProcedure(previousProcedure);
|
||||||
|
Object.DestroyImmediate(procedureObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void EnqueueAreaQuery_CapturesInactiveSourceSnapshot_WhenSourceEntityUnavailable()
|
||||||
|
{
|
||||||
|
SetUseJobSimulationMethod.Invoke(_worldComponent, new object[] { true });
|
||||||
|
UpsertEnemy(CreateEnemy(entityId: 5231, position: Vector3.zero, speed: 0f, attackRange: 1f));
|
||||||
|
|
||||||
|
object[] enqueueArgs = { 99999, 99999, Vector3.zero, 1f, 1 };
|
||||||
|
bool enqueueResult = (bool)TryEnqueueAreaCollisionQueryMethod.Invoke(_worldComponent, enqueueArgs);
|
||||||
|
Assert.IsTrue(enqueueResult);
|
||||||
|
|
||||||
|
object areaCollisionRequests = AreaCollisionRequestsField.GetValue(_worldComponent);
|
||||||
|
Assert.NotNull(areaCollisionRequests);
|
||||||
|
PropertyInfo requestCountProperty = areaCollisionRequests.GetType().GetProperty("Count", PublicInstance);
|
||||||
|
int requestCount = (int)requestCountProperty.GetValue(areaCollisionRequests);
|
||||||
|
Assert.That(requestCount, Is.GreaterThan(0));
|
||||||
|
|
||||||
|
PropertyInfo requestItemProperty = areaCollisionRequests.GetType().GetProperty("Item", PublicInstance);
|
||||||
|
object firstRequest = requestItemProperty.GetValue(areaCollisionRequests, new object[] { 0 });
|
||||||
|
FieldInfo requestSnapshotField =
|
||||||
|
firstRequest.GetType().GetField("SourceWasActiveAtQueryTime", PublicInstance);
|
||||||
|
Assert.NotNull(requestSnapshotField);
|
||||||
|
bool requestSnapshot = (bool)requestSnapshotField.GetValue(firstRequest);
|
||||||
|
Assert.IsFalse(requestSnapshot);
|
||||||
|
|
||||||
|
InvokeTick(deltaTime: 0.016f, realDeltaTime: 0.016f, playerPosition: Vector3.zero);
|
||||||
|
Assert.That(GetLastResolvedAreaHitCount(), Is.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
private object CreateEnemy(int entityId, Vector3 position, float speed, float attackRange,
|
private object CreateEnemy(int entityId, Vector3 position, float speed, float attackRange,
|
||||||
bool avoidEnemyOverlap = false, float enemyBodyRadius = 0.45f, int separationIterations = 1)
|
bool avoidEnemyOverlap = false, float enemyBodyRadius = 0.45f, int separationIterations = 1)
|
||||||
{
|
{
|
||||||
|
|
@ -641,6 +848,26 @@ namespace Simulation.Tests.Editor
|
||||||
GameEntrySetSimulationWorldMethod.Invoke(null, new[] { simulationWorld });
|
GameEntrySetSimulationWorldMethod.Invoke(null, new[] { simulationWorld });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static object GetGameEntryEnemyManager()
|
||||||
|
{
|
||||||
|
return GameEntryGetEnemyManagerMethod.Invoke(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetGameEntryEnemyManager(object enemyManager)
|
||||||
|
{
|
||||||
|
GameEntrySetEnemyManagerMethod.Invoke(null, new[] { enemyManager });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GetGameEntryProcedure()
|
||||||
|
{
|
||||||
|
return GameEntryGetProcedureMethod.Invoke(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetGameEntryProcedure(object procedureComponent)
|
||||||
|
{
|
||||||
|
GameEntrySetProcedureMethod.Invoke(null, new[] { procedureComponent });
|
||||||
|
}
|
||||||
|
|
||||||
private static void InvokeEnemyProjectileUpdate(Component projectileComponent, float elapseSeconds,
|
private static void InvokeEnemyProjectileUpdate(Component projectileComponent, float elapseSeconds,
|
||||||
float realElapseSeconds)
|
float realElapseSeconds)
|
||||||
{
|
{
|
||||||
|
|
@ -689,6 +916,11 @@ namespace Simulation.Tests.Editor
|
||||||
return (int)CollisionCandidateCountProperty.GetValue(_worldComponent);
|
return (int)CollisionCandidateCountProperty.GetValue(_worldComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int GetLastResolvedAreaHitCount()
|
||||||
|
{
|
||||||
|
return (int)LastResolvedAreaHitCountProperty.GetValue(_worldComponent);
|
||||||
|
}
|
||||||
|
|
||||||
private static object GetField(object target, string fieldName)
|
private static object GetField(object target, string fieldName)
|
||||||
{
|
{
|
||||||
FieldInfo field = target.GetType().GetField(fieldName, PublicInstance);
|
FieldInfo field = target.GetType().GetField(fieldName, PublicInstance);
|
||||||
|
|
@ -700,5 +932,23 @@ namespace Simulation.Tests.Editor
|
||||||
FieldInfo field = target.GetType().GetField(fieldName, PublicInstance);
|
FieldInfo field = target.GetType().GetField(fieldName, PublicInstance);
|
||||||
field.SetValue(target, value);
|
field.SetValue(target, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void SetPrivateField(object target, string fieldName, object value)
|
||||||
|
{
|
||||||
|
Type type = target.GetType();
|
||||||
|
while (type != null)
|
||||||
|
{
|
||||||
|
FieldInfo field = type.GetField(fieldName, NonPublicInstance);
|
||||||
|
if (field != null)
|
||||||
|
{
|
||||||
|
field.SetValue(target, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = type.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Fail($"Field '{fieldName}' was not found on type '{target.GetType().FullName}'.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,18 @@
|
||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.TestTools;
|
using UnityEngine.TestTools;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace Simulation.Tests.PlayMode
|
namespace Simulation.Tests.PlayMode
|
||||||
{
|
{
|
||||||
public class SimulationWorldPlayModeTests
|
public class SimulationWorldPlayModeTests
|
||||||
{
|
{
|
||||||
private const string GameAssemblyName = "Assembly-CSharp";
|
private const string GameAssemblyName = "Assembly-CSharp";
|
||||||
|
private const string RuntimeAssemblyName = "UnityGameFramework.Runtime";
|
||||||
private const BindingFlags PublicStatic = BindingFlags.Public | BindingFlags.Static;
|
private const BindingFlags PublicStatic = BindingFlags.Public | BindingFlags.Static;
|
||||||
private const BindingFlags PublicInstance = BindingFlags.Public | BindingFlags.Instance;
|
private const BindingFlags PublicInstance = BindingFlags.Public | BindingFlags.Instance;
|
||||||
private const BindingFlags NonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance;
|
private const BindingFlags NonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance;
|
||||||
|
|
@ -40,6 +44,36 @@ namespace Simulation.Tests.PlayMode
|
||||||
private static readonly System.Type EnemySeparationSolverProviderType =
|
private static readonly System.Type EnemySeparationSolverProviderType =
|
||||||
System.Type.GetType($"CustomUtility.EnemySeparationSolverProvider, {GameAssemblyName}");
|
System.Type.GetType($"CustomUtility.EnemySeparationSolverProvider, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type EnemyManagerComponentType =
|
||||||
|
System.Type.GetType($"CustomComponent.EnemyManagerComponent, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type PlayerType =
|
||||||
|
System.Type.GetType($"Entity.Player, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type EntityBaseType =
|
||||||
|
System.Type.GetType($"Entity.EntityBase, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type HealthComponentType =
|
||||||
|
System.Type.GetType($"Components.HealthComponent, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type ProcedureComponentType =
|
||||||
|
System.Type.GetType($"UnityGameFramework.Runtime.ProcedureComponent, {RuntimeAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type ProcedureGameType =
|
||||||
|
System.Type.GetType($"Procedure.ProcedureGame, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type GameStateTypeType =
|
||||||
|
System.Type.GetType($"Procedure.GameStateType, {GameAssemblyName}");
|
||||||
|
|
||||||
|
private static readonly System.Type ProcedureManagerType =
|
||||||
|
System.Type.GetType("GameFramework.Procedure.ProcedureManager, GameFramework");
|
||||||
|
|
||||||
|
private static readonly System.Type ProcedureManagerInterfaceType =
|
||||||
|
System.Type.GetType("GameFramework.Procedure.IProcedureManager, GameFramework");
|
||||||
|
|
||||||
|
private static readonly System.Type FsmOpenGenericType =
|
||||||
|
System.Type.GetType("GameFramework.Fsm.Fsm`1, GameFramework");
|
||||||
|
|
||||||
private static readonly MethodInfo UpsertEnemyMethod =
|
private static readonly MethodInfo UpsertEnemyMethod =
|
||||||
SimulationWorldType?.GetMethod("UpsertEnemy", NonPublicInstance);
|
SimulationWorldType?.GetMethod("UpsertEnemy", NonPublicInstance);
|
||||||
|
|
||||||
|
|
@ -61,6 +95,9 @@ namespace Simulation.Tests.PlayMode
|
||||||
private static readonly MethodInfo TryGetNearestEnemyEntityIdMethod =
|
private static readonly MethodInfo TryGetNearestEnemyEntityIdMethod =
|
||||||
SimulationWorldType?.GetMethod("TryGetNearestEnemyEntityId", PublicInstance);
|
SimulationWorldType?.GetMethod("TryGetNearestEnemyEntityId", PublicInstance);
|
||||||
|
|
||||||
|
private static readonly MethodInfo TryEnqueueAreaCollisionQueryMethod =
|
||||||
|
SimulationWorldType?.GetMethod("TryEnqueueAreaCollisionQuery", PublicInstance);
|
||||||
|
|
||||||
private static readonly MethodInfo SetUseSimulationMovementMethod =
|
private static readonly MethodInfo SetUseSimulationMovementMethod =
|
||||||
SimulationWorldType?.GetMethod("SetUseSimulationMovement", PublicInstance);
|
SimulationWorldType?.GetMethod("SetUseSimulationMovement", PublicInstance);
|
||||||
|
|
||||||
|
|
@ -91,6 +128,21 @@ namespace Simulation.Tests.PlayMode
|
||||||
private static readonly PropertyInfo CollisionCandidateCountProperty =
|
private static readonly PropertyInfo CollisionCandidateCountProperty =
|
||||||
SimulationWorldType?.GetProperty("CollisionCandidateCount", PublicInstance);
|
SimulationWorldType?.GetProperty("CollisionCandidateCount", PublicInstance);
|
||||||
|
|
||||||
|
private static readonly PropertyInfo UseSimulationMovementProperty =
|
||||||
|
SimulationWorldType?.GetProperty("UseSimulationMovement", PublicInstance);
|
||||||
|
|
||||||
|
private static readonly PropertyInfo UseJobSimulationProperty =
|
||||||
|
SimulationWorldType?.GetProperty("UseJobSimulation", PublicInstance);
|
||||||
|
|
||||||
|
private static readonly PropertyInfo LastResolvedAreaHitCountProperty =
|
||||||
|
SimulationWorldType?.GetProperty("LastResolvedAreaHitCount", PublicInstance);
|
||||||
|
|
||||||
|
private static readonly FieldInfo CollisionQueryInputsField =
|
||||||
|
SimulationWorldType?.GetField("_collisionQueryInputs", NonPublicInstance);
|
||||||
|
|
||||||
|
private static readonly FieldInfo AreaCollisionRequestsField =
|
||||||
|
SimulationWorldType?.GetField("_areaCollisionRequests", NonPublicInstance);
|
||||||
|
|
||||||
private static readonly MethodInfo EnemyProjectileOnUpdateMethod =
|
private static readonly MethodInfo EnemyProjectileOnUpdateMethod =
|
||||||
EnemyProjectileType?.GetMethod("OnUpdate", NonPublicInstance);
|
EnemyProjectileType?.GetMethod("OnUpdate", NonPublicInstance);
|
||||||
|
|
||||||
|
|
@ -112,6 +164,27 @@ namespace Simulation.Tests.PlayMode
|
||||||
private static readonly MethodInfo GameEntrySetSimulationWorldMethod =
|
private static readonly MethodInfo GameEntrySetSimulationWorldMethod =
|
||||||
GameEntrySimulationWorldProperty?.GetSetMethod(true);
|
GameEntrySimulationWorldProperty?.GetSetMethod(true);
|
||||||
|
|
||||||
|
private static readonly PropertyInfo GameEntryEnemyManagerProperty =
|
||||||
|
GameEntryType?.GetProperty("EnemyManager", PublicStatic);
|
||||||
|
|
||||||
|
private static readonly MethodInfo GameEntryGetEnemyManagerMethod =
|
||||||
|
GameEntryEnemyManagerProperty?.GetGetMethod(true);
|
||||||
|
|
||||||
|
private static readonly MethodInfo GameEntrySetEnemyManagerMethod =
|
||||||
|
GameEntryEnemyManagerProperty?.GetSetMethod(true);
|
||||||
|
|
||||||
|
private static readonly PropertyInfo GameEntryProcedureProperty =
|
||||||
|
GameEntryType?.GetProperty("Procedure", PublicStatic);
|
||||||
|
|
||||||
|
private static readonly MethodInfo GameEntryGetProcedureMethod =
|
||||||
|
GameEntryProcedureProperty?.GetGetMethod(true);
|
||||||
|
|
||||||
|
private static readonly MethodInfo GameEntrySetProcedureMethod =
|
||||||
|
GameEntryProcedureProperty?.GetSetMethod(true);
|
||||||
|
|
||||||
|
private static readonly MethodInfo HealthComponentOnInitMethod =
|
||||||
|
HealthComponentType?.GetMethod("OnInit", PublicInstance);
|
||||||
|
|
||||||
private static readonly FieldInfo ProjectileMaxDistanceFromPlayerField =
|
private static readonly FieldInfo ProjectileMaxDistanceFromPlayerField =
|
||||||
SimulationWorldType?.GetField("_projectileMaxDistanceFromPlayer", NonPublicInstance);
|
SimulationWorldType?.GetField("_projectileMaxDistanceFromPlayer", NonPublicInstance);
|
||||||
|
|
||||||
|
|
@ -133,6 +206,16 @@ namespace Simulation.Tests.PlayMode
|
||||||
Assert.NotNull(CampTypeType, "CampType type lookup failed.");
|
Assert.NotNull(CampTypeType, "CampType type lookup failed.");
|
||||||
Assert.NotNull(GameEntryType, "GameEntry type lookup failed.");
|
Assert.NotNull(GameEntryType, "GameEntry type lookup failed.");
|
||||||
Assert.NotNull(EnemySeparationSolverProviderType, "EnemySeparationSolverProvider type lookup failed.");
|
Assert.NotNull(EnemySeparationSolverProviderType, "EnemySeparationSolverProvider type lookup failed.");
|
||||||
|
Assert.NotNull(EnemyManagerComponentType, "EnemyManagerComponent type lookup failed.");
|
||||||
|
Assert.NotNull(PlayerType, "Player type lookup failed.");
|
||||||
|
Assert.NotNull(EntityBaseType, "EntityBase type lookup failed.");
|
||||||
|
Assert.NotNull(HealthComponentType, "HealthComponent type lookup failed.");
|
||||||
|
Assert.NotNull(ProcedureComponentType, "ProcedureComponent type lookup failed.");
|
||||||
|
Assert.NotNull(ProcedureGameType, "ProcedureGame type lookup failed.");
|
||||||
|
Assert.NotNull(GameStateTypeType, "GameStateType type lookup failed.");
|
||||||
|
Assert.NotNull(ProcedureManagerType, "ProcedureManager type lookup failed.");
|
||||||
|
Assert.NotNull(ProcedureManagerInterfaceType, "IProcedureManager type lookup failed.");
|
||||||
|
Assert.NotNull(FsmOpenGenericType, "Fsm`1 type lookup failed.");
|
||||||
Assert.NotNull(UpsertEnemyMethod, "UpsertEnemy reflection lookup failed.");
|
Assert.NotNull(UpsertEnemyMethod, "UpsertEnemy reflection lookup failed.");
|
||||||
Assert.NotNull(RemoveEnemyByEntityIdMethod, "RemoveEnemyByEntityId reflection lookup failed.");
|
Assert.NotNull(RemoveEnemyByEntityIdMethod, "RemoveEnemyByEntityId reflection lookup failed.");
|
||||||
Assert.NotNull(UpsertProjectileMethod, "UpsertProjectile reflection lookup failed.");
|
Assert.NotNull(UpsertProjectileMethod, "UpsertProjectile reflection lookup failed.");
|
||||||
|
|
@ -140,6 +223,7 @@ namespace Simulation.Tests.PlayMode
|
||||||
Assert.NotNull(TryGetEnemyDataMethod, "TryGetEnemyData reflection lookup failed.");
|
Assert.NotNull(TryGetEnemyDataMethod, "TryGetEnemyData reflection lookup failed.");
|
||||||
Assert.NotNull(TickMethod, "Tick reflection lookup failed.");
|
Assert.NotNull(TickMethod, "Tick reflection lookup failed.");
|
||||||
Assert.NotNull(TryGetNearestEnemyEntityIdMethod, "TryGetNearestEnemyEntityId reflection lookup failed.");
|
Assert.NotNull(TryGetNearestEnemyEntityIdMethod, "TryGetNearestEnemyEntityId reflection lookup failed.");
|
||||||
|
Assert.NotNull(TryEnqueueAreaCollisionQueryMethod, "TryEnqueueAreaCollisionQuery reflection lookup failed.");
|
||||||
Assert.NotNull(SetUseSimulationMovementMethod, "SetUseSimulationMovement reflection lookup failed.");
|
Assert.NotNull(SetUseSimulationMovementMethod, "SetUseSimulationMovement reflection lookup failed.");
|
||||||
Assert.NotNull(SetUseJobSimulationMethod, "SetUseJobSimulation reflection lookup failed.");
|
Assert.NotNull(SetUseJobSimulationMethod, "SetUseJobSimulation reflection lookup failed.");
|
||||||
Assert.NotNull(SetUseBurstJobsMethod, "SetUseBurstJobs reflection lookup failed.");
|
Assert.NotNull(SetUseBurstJobsMethod, "SetUseBurstJobs reflection lookup failed.");
|
||||||
|
|
@ -148,6 +232,11 @@ namespace Simulation.Tests.PlayMode
|
||||||
Assert.NotNull(EnemiesProperty, "Enemies property reflection lookup failed.");
|
Assert.NotNull(EnemiesProperty, "Enemies property reflection lookup failed.");
|
||||||
Assert.NotNull(ProjectilesProperty, "Projectiles property reflection lookup failed.");
|
Assert.NotNull(ProjectilesProperty, "Projectiles property reflection lookup failed.");
|
||||||
Assert.NotNull(CollisionCandidateCountProperty, "CollisionCandidateCount property reflection lookup failed.");
|
Assert.NotNull(CollisionCandidateCountProperty, "CollisionCandidateCount property reflection lookup failed.");
|
||||||
|
Assert.NotNull(UseSimulationMovementProperty, "UseSimulationMovement property reflection lookup failed.");
|
||||||
|
Assert.NotNull(UseJobSimulationProperty, "UseJobSimulation property reflection lookup failed.");
|
||||||
|
Assert.NotNull(LastResolvedAreaHitCountProperty, "LastResolvedAreaHitCount property reflection lookup failed.");
|
||||||
|
Assert.NotNull(CollisionQueryInputsField, "Collision query inputs field reflection lookup failed.");
|
||||||
|
Assert.NotNull(AreaCollisionRequestsField, "Area collision requests field reflection lookup failed.");
|
||||||
Assert.NotNull(ProjectileMaxDistanceFromPlayerField,
|
Assert.NotNull(ProjectileMaxDistanceFromPlayerField,
|
||||||
"Projectile max distance field reflection lookup failed.");
|
"Projectile max distance field reflection lookup failed.");
|
||||||
Assert.NotNull(ProjectileMaxVerticalOffsetFromPlayerField,
|
Assert.NotNull(ProjectileMaxVerticalOffsetFromPlayerField,
|
||||||
|
|
@ -162,6 +251,13 @@ namespace Simulation.Tests.PlayMode
|
||||||
"GameEntry.SimulationWorld getter reflection lookup failed.");
|
"GameEntry.SimulationWorld getter reflection lookup failed.");
|
||||||
Assert.NotNull(GameEntrySetSimulationWorldMethod,
|
Assert.NotNull(GameEntrySetSimulationWorldMethod,
|
||||||
"GameEntry.SimulationWorld setter reflection lookup failed.");
|
"GameEntry.SimulationWorld setter reflection lookup failed.");
|
||||||
|
Assert.NotNull(GameEntryEnemyManagerProperty, "GameEntry.EnemyManager property lookup failed.");
|
||||||
|
Assert.NotNull(GameEntryGetEnemyManagerMethod, "GameEntry.EnemyManager getter reflection lookup failed.");
|
||||||
|
Assert.NotNull(GameEntrySetEnemyManagerMethod, "GameEntry.EnemyManager setter reflection lookup failed.");
|
||||||
|
Assert.NotNull(GameEntryProcedureProperty, "GameEntry.Procedure property lookup failed.");
|
||||||
|
Assert.NotNull(GameEntryGetProcedureMethod, "GameEntry.Procedure getter reflection lookup failed.");
|
||||||
|
Assert.NotNull(GameEntrySetProcedureMethod, "GameEntry.Procedure setter reflection lookup failed.");
|
||||||
|
Assert.NotNull(HealthComponentOnInitMethod, "HealthComponent.OnInit reflection lookup failed.");
|
||||||
|
|
||||||
_worldGameObject = new GameObject("SimulationWorldPlayModeTests");
|
_worldGameObject = new GameObject("SimulationWorldPlayModeTests");
|
||||||
_worldComponent = _worldGameObject.AddComponent(SimulationWorldType);
|
_worldComponent = _worldGameObject.AddComponent(SimulationWorldType);
|
||||||
|
|
@ -595,6 +691,117 @@ namespace Simulation.Tests.PlayMode
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator TickProjectiles_LimitsCandidatesToMaxTargets_IncludingPlayerCandidate()
|
||||||
|
{
|
||||||
|
SetUseJobSimulationMethod.Invoke(_worldComponent, new object[] { true });
|
||||||
|
object previousEnemyManager = GetGameEntryEnemyManager();
|
||||||
|
GameObject enemyManagerObject = new GameObject("EnemyManagerMaxTargetsPlayMode");
|
||||||
|
GameObject playerObject = new GameObject("PlayerTargetMaxTargetsPlayMode");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Component enemyManager = enemyManagerObject.AddComponent(EnemyManagerComponentType);
|
||||||
|
Component player = playerObject.AddComponent(PlayerType);
|
||||||
|
Component healthComponent = playerObject.AddComponent(HealthComponentType);
|
||||||
|
HealthComponentOnInitMethod.Invoke(healthComponent, new object[] { 100, null });
|
||||||
|
SetPrivateField(player, "_healthComponent", healthComponent);
|
||||||
|
SetPrivateField(player, "m_CachedTransform", playerObject.transform);
|
||||||
|
SetPrivateField(player, "m_Available", true);
|
||||||
|
|
||||||
|
object enemyById = Activator.CreateInstance(typeof(Dictionary<,>).MakeGenericType(typeof(int), EntityBaseType));
|
||||||
|
enemyById.GetType().GetMethod("Add")?.Invoke(enemyById, new object[] { -1, player });
|
||||||
|
object enemies = Activator.CreateInstance(typeof(List<>).MakeGenericType(EntityBaseType));
|
||||||
|
enemies.GetType().GetMethod("Add")?.Invoke(enemies, new object[] { player });
|
||||||
|
SetPrivateField(enemyManager, "_enemyById", enemyById);
|
||||||
|
SetPrivateField(enemyManager, "_enemies", enemies);
|
||||||
|
SetGameEntryEnemyManager(enemyManager);
|
||||||
|
|
||||||
|
UpsertEnemy(CreateEnemy(entityId: 5521, position: Vector3.zero, speed: 0f, attackRange: 1f));
|
||||||
|
UpsertProjectile(CreateProjectile(entityId: 5522, position: Vector3.zero, forward: Vector3.forward,
|
||||||
|
velocity: Vector3.zero, speed: 0f, lifeTime: 1f, age: 0f, active: true, remainingLifetime: 1f,
|
||||||
|
state: 0));
|
||||||
|
|
||||||
|
InvokeTick(deltaTime: 0.016f, realDeltaTime: 0.016f, playerPosition: Vector3.zero);
|
||||||
|
|
||||||
|
Assert.That(GetCollisionCandidateCount(), Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SetGameEntryEnemyManager(previousEnemyManager);
|
||||||
|
Object.Destroy(enemyManagerObject);
|
||||||
|
Object.Destroy(playerObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator SetUseSimulationAndJob_AreIgnored_WhenBattleStateIsActive()
|
||||||
|
{
|
||||||
|
SetUseSimulationMovementMethod.Invoke(_worldComponent, new object[] { true });
|
||||||
|
SetUseJobSimulationMethod.Invoke(_worldComponent, new object[] { false });
|
||||||
|
|
||||||
|
object previousProcedure = GetGameEntryProcedure();
|
||||||
|
GameObject procedureObject = new GameObject("ProcedureGuardPlayMode");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Component procedureComponent = procedureObject.AddComponent(ProcedureComponentType);
|
||||||
|
object procedureManager = Activator.CreateInstance(ProcedureManagerType);
|
||||||
|
Type fsmType = FsmOpenGenericType.MakeGenericType(ProcedureManagerInterfaceType);
|
||||||
|
object fsm = Activator.CreateInstance(fsmType);
|
||||||
|
object procedureGame = Activator.CreateInstance(ProcedureGameType);
|
||||||
|
object battleState = Enum.Parse(GameStateTypeType, "Battle");
|
||||||
|
|
||||||
|
SetPrivateField(procedureGame, "_currentGameState", battleState);
|
||||||
|
SetPrivateField(fsm, "m_CurrentState", procedureGame);
|
||||||
|
SetPrivateField(procedureManager, "m_ProcedureFsm", fsm);
|
||||||
|
SetPrivateField(procedureComponent, "m_ProcedureManager", procedureManager);
|
||||||
|
SetGameEntryProcedure(procedureComponent);
|
||||||
|
|
||||||
|
SetUseSimulationMovementMethod.Invoke(_worldComponent, new object[] { false });
|
||||||
|
SetUseJobSimulationMethod.Invoke(_worldComponent, new object[] { true });
|
||||||
|
|
||||||
|
Assert.IsTrue((bool)UseSimulationMovementProperty.GetValue(_worldComponent));
|
||||||
|
Assert.IsFalse((bool)UseJobSimulationProperty.GetValue(_worldComponent));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SetGameEntryProcedure(previousProcedure);
|
||||||
|
Object.Destroy(procedureObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator EnqueueAreaQuery_CapturesInactiveSourceSnapshot_WhenSourceEntityUnavailable()
|
||||||
|
{
|
||||||
|
SetUseJobSimulationMethod.Invoke(_worldComponent, new object[] { true });
|
||||||
|
UpsertEnemy(CreateEnemy(entityId: 5531, position: Vector3.zero, speed: 0f, attackRange: 1f));
|
||||||
|
|
||||||
|
object[] enqueueArgs = { 99999, 99999, Vector3.zero, 1f, 1 };
|
||||||
|
bool enqueueResult = (bool)TryEnqueueAreaCollisionQueryMethod.Invoke(_worldComponent, enqueueArgs);
|
||||||
|
Assert.IsTrue(enqueueResult);
|
||||||
|
|
||||||
|
object areaCollisionRequests = AreaCollisionRequestsField.GetValue(_worldComponent);
|
||||||
|
Assert.NotNull(areaCollisionRequests);
|
||||||
|
PropertyInfo requestCountProperty = areaCollisionRequests.GetType().GetProperty("Count", PublicInstance);
|
||||||
|
int requestCount = (int)requestCountProperty.GetValue(areaCollisionRequests);
|
||||||
|
Assert.That(requestCount, Is.GreaterThan(0));
|
||||||
|
|
||||||
|
PropertyInfo requestItemProperty = areaCollisionRequests.GetType().GetProperty("Item", PublicInstance);
|
||||||
|
object firstRequest = requestItemProperty.GetValue(areaCollisionRequests, new object[] { 0 });
|
||||||
|
FieldInfo requestSnapshotField =
|
||||||
|
firstRequest.GetType().GetField("SourceWasActiveAtQueryTime", PublicInstance);
|
||||||
|
Assert.NotNull(requestSnapshotField);
|
||||||
|
bool requestSnapshot = (bool)requestSnapshotField.GetValue(firstRequest);
|
||||||
|
Assert.IsFalse(requestSnapshot);
|
||||||
|
|
||||||
|
InvokeTick(deltaTime: 0.016f, realDeltaTime: 0.016f, playerPosition: Vector3.zero);
|
||||||
|
Assert.That(GetLastResolvedAreaHitCount(), Is.EqualTo(0));
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
private object CreateEnemy(int entityId, Vector3 position, float speed, float attackRange,
|
private object CreateEnemy(int entityId, Vector3 position, float speed, float attackRange,
|
||||||
bool avoidEnemyOverlap = false, float enemyBodyRadius = 0.45f, int separationIterations = 1)
|
bool avoidEnemyOverlap = false, float enemyBodyRadius = 0.45f, int separationIterations = 1)
|
||||||
{
|
{
|
||||||
|
|
@ -673,6 +880,26 @@ namespace Simulation.Tests.PlayMode
|
||||||
GameEntrySetSimulationWorldMethod.Invoke(null, new[] { simulationWorld });
|
GameEntrySetSimulationWorldMethod.Invoke(null, new[] { simulationWorld });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static object GetGameEntryEnemyManager()
|
||||||
|
{
|
||||||
|
return GameEntryGetEnemyManagerMethod.Invoke(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetGameEntryEnemyManager(object enemyManager)
|
||||||
|
{
|
||||||
|
GameEntrySetEnemyManagerMethod.Invoke(null, new[] { enemyManager });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GetGameEntryProcedure()
|
||||||
|
{
|
||||||
|
return GameEntryGetProcedureMethod.Invoke(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetGameEntryProcedure(object procedureComponent)
|
||||||
|
{
|
||||||
|
GameEntrySetProcedureMethod.Invoke(null, new[] { procedureComponent });
|
||||||
|
}
|
||||||
|
|
||||||
private static void InvokeEnemyProjectileUpdate(Component projectileComponent, float elapseSeconds,
|
private static void InvokeEnemyProjectileUpdate(Component projectileComponent, float elapseSeconds,
|
||||||
float realElapseSeconds)
|
float realElapseSeconds)
|
||||||
{
|
{
|
||||||
|
|
@ -721,6 +948,11 @@ namespace Simulation.Tests.PlayMode
|
||||||
return (int)CollisionCandidateCountProperty.GetValue(_worldComponent);
|
return (int)CollisionCandidateCountProperty.GetValue(_worldComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int GetLastResolvedAreaHitCount()
|
||||||
|
{
|
||||||
|
return (int)LastResolvedAreaHitCountProperty.GetValue(_worldComponent);
|
||||||
|
}
|
||||||
|
|
||||||
private static object GetField(object target, string fieldName)
|
private static object GetField(object target, string fieldName)
|
||||||
{
|
{
|
||||||
FieldInfo field = target.GetType().GetField(fieldName, PublicInstance);
|
FieldInfo field = target.GetType().GetField(fieldName, PublicInstance);
|
||||||
|
|
@ -732,5 +964,23 @@ namespace Simulation.Tests.PlayMode
|
||||||
FieldInfo field = target.GetType().GetField(fieldName, PublicInstance);
|
FieldInfo field = target.GetType().GetField(fieldName, PublicInstance);
|
||||||
field.SetValue(target, value);
|
field.SetValue(target, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void SetPrivateField(object target, string fieldName, object value)
|
||||||
|
{
|
||||||
|
Type type = target.GetType();
|
||||||
|
while (type != null)
|
||||||
|
{
|
||||||
|
FieldInfo field = type.GetField(fieldName, NonPublicInstance);
|
||||||
|
if (field != null)
|
||||||
|
{
|
||||||
|
field.SetValue(target, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = type.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Fail($"Field '{fieldName}' was not found on type '{target.GetType().FullName}'.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue