forked from Unity-Technologies/EntityComponentSystemSamples
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathNewBallMovementSystem.cs
84 lines (75 loc) · 3.16 KB
/
NewBallMovementSystem.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using Tutorials.Kickball.Execute;
using Tutorials.Kickball.Step1;
using Tutorials.Kickball.Step2;
using Tutorials.Kickball.Step3;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
namespace Tutorials.Kickball.Step4
{
[UpdateBefore(typeof(TransformSystemGroup))]
public partial struct NewBallMovementSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<NewBallMovement>();
state.RequireForUpdate<Config>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var config = SystemAPI.GetSingleton<Config>();
var obstacleQuery = SystemAPI.QueryBuilder().WithAll<LocalTransform, Obstacle>().Build();
var minDist = config.ObstacleRadius + 0.5f; // the ball radius is 0.5f
var job = new BallMovementJob
{
ObstacleTransforms = obstacleQuery.ToComponentDataArray<LocalTransform>(state.WorldUpdateAllocator),
DecayFactor = config.BallVelocityDecay * SystemAPI.Time.DeltaTime,
DeltaTime = SystemAPI.Time.DeltaTime,
MinDistToObstacleSQ = minDist * minDist
};
job.ScheduleParallel();
}
}
// The implicit query of this IJobEntity matches all entities having LocalTransform, Velocity, and Ball components.
[WithAll(typeof(Ball))]
[WithDisabled(typeof(Carry))] // Relevant in Step 5
[BurstCompile]
public partial struct BallMovementJob : IJobEntity
{
[ReadOnly] public NativeArray<LocalTransform> ObstacleTransforms;
public float DecayFactor;
public float DeltaTime;
public float MinDistToObstacleSQ;
public void Execute(ref LocalTransform transform, ref Velocity velocity)
{
if (velocity.Value.Equals(float2.zero))
{
return;
}
var magnitude = math.length(velocity.Value);
var newPosition = transform.Position +
new float3(velocity.Value.x, 0, velocity.Value.y) * DeltaTime;
foreach (var obstacleTransform in ObstacleTransforms)
{
if (math.distancesq(newPosition, obstacleTransform.Position) <= MinDistToObstacleSQ)
{
newPosition = DeflectBall(transform.Position, obstacleTransform.Position, ref velocity, magnitude, DeltaTime);
break;
}
}
transform.Position = newPosition;
var newMagnitude = math.max(magnitude - DecayFactor, 0);
velocity.Value = math.normalizesafe(velocity.Value) * newMagnitude;
}
private float3 DeflectBall(float3 ballPos, float3 obstaclePos, ref Velocity velocity, float magnitude, float dt)
{
var obstacleToBallVector = math.normalize((ballPos - obstaclePos).xz);
velocity.Value = math.reflect(math.normalize(velocity.Value), obstacleToBallVector) * magnitude;
return ballPos + new float3(velocity.Value.x, 0, velocity.Value.y) * dt;
}
}
}