Files
vampire-like/Assets/GameMain/Scripts/Runtime/CustomComponent/Simulation/Systems/EnemyMovementSystem.cs
T

95 lines
3.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
namespace SepCore.Simulation
{
internal static class EnemyMovementSystem
{
// 读写集:R EnemyTransform / EnemyMoveInput / EnemyAttack;W EnemyTransform / EnemyBehavior
public static JobHandle Schedule(EnemyStore enemies, float deltaTime, float3 playerPosition,
JobHandle dependency)
{
int enemyCount = enemies.Count;
if (enemyCount == 0)
{
return dependency;
}
EnemyMovementJob job = new EnemyMovementJob
{
Transforms = enemies.Transform.Data.AsArray(),
MoveInputs = enemies.MoveInput.Data.AsArray(),
Attacks = enemies.Attack.Data.AsArray(),
Behaviors = enemies.Behavior.Data.AsArray(),
DeltaTime = deltaTime,
PlayerPosition = playerPosition
};
return job.Schedule(enemyCount, 64, dependency);
}
}
[BurstCompile]
internal struct EnemyMovementJob : IJobParallelFor
{
public NativeArray<EnemyTransformSim> Transforms;
[ReadOnly] public NativeArray<EnemyMoveInputSim> MoveInputs;
[ReadOnly] public NativeArray<EnemyAttackSim> Attacks;
public NativeArray<EnemyBehaviorSim> Behaviors;
public float DeltaTime;
public float3 PlayerPosition;
public void Execute(int index)
{
EnemyMoveInputSim moveInput = MoveInputs[index];
EnemyAttackSim attack = Attacks[index];
EnemyTransformSim transform = Transforms[index];
float attackRange = attack.AttackRange > 0f ? attack.AttackRange : EnemyAttackSim.DefaultAttackRange;
float attackRangeSqr = attackRange * attackRange;
float3 currentPosition = transform.Position;
float3 horizontalPosition = new float3(currentPosition.x, 0f, currentPosition.z);
float3 toPlayer = PlayerPosition - horizontalPosition;
float sqrDistance = math.lengthsq(toPlayer);
bool isInAttackRange = sqrDistance <= attackRangeSqr;
bool canChase = !isInAttackRange && moveInput.Speed > 0f && sqrDistance > float.Epsilon;
float3 forward = transform.Forward;
float3 desiredPosition = currentPosition;
quaternion rotation = transform.Rotation;
if (canChase)
{
forward = math.normalizesafe(toPlayer, forward);
desiredPosition = currentPosition + forward * moveInput.Speed * DeltaTime;
if (math.lengthsq(forward) > float.Epsilon)
{
rotation = quaternion.LookRotationSafe(forward, math.up());
}
}
int nextState;
if (isInAttackRange)
{
nextState = EnemyBehaviorSim.StateInAttackRange;
}
else if (canChase)
{
nextState = EnemyBehaviorSim.StateChasing;
}
else
{
nextState = EnemyBehaviorSim.StateIdle;
}
transform.Position = desiredPosition;
transform.Forward = forward;
transform.Rotation = rotation;
Transforms[index] = transform;
Behaviors[index] = new EnemyBehaviorSim { State = nextState };
}
}
}