protected override void OnUpdate() { var race = GetSingleton <Race>(); if (!race.IsInProgress()) { return; } var updateCarLapSystem = EntityManager.World.GetExistingSystem <UpdateCarLapProgress>(); var controlPoints = updateCarLapSystem.ControlPoints; Dependency = Entities.WithAll <Car>().ForEach((ref Car car, ref CarInputs inputs, in AI opponent, in LocalToWorld localToWorld, in LapProgress lapProgress, in Translation translation) => { var controlPointIndex = lapProgress.CurrentControlPoint; var controlPointProgress = lapProgress.CurrentControlPointProgress; var firstControlPointIndex = controlPointIndex == 0 ? controlPoints.Length - 1 : controlPointIndex - 1; var closestPoint = SplineUtils.GetPoint(controlPoints, firstControlPointIndex, controlPointProgress); var tangent = SplineUtils.GetTangent(controlPoints, firstControlPointIndex, controlPointProgress); var targetPoint = closestPoint + tangent * 4f + math.cross(tangent, new float3(0f, 1f, 0f)) * opponent.NormalDistanceFromTrack; var current = new float2(translation.Value.x, translation.Value.z); var target = new float2(targetPoint.x, targetPoint.z); var wantedDirection = target - current; var currentDirection = new float2(localToWorld.Forward.x, localToWorld.Forward.z); var angleCurrentDirection = math.atan2(currentDirection.y, currentDirection.x); angleCurrentDirection = math.degrees(angleCurrentDirection); var angleWantedDirection = math.atan2(wantedDirection.y, wantedDirection.x); angleWantedDirection = math.degrees(angleWantedDirection); var angleDiff = angleWantedDirection - angleCurrentDirection; // Steer the car to follow the curve of the track if (angleDiff < 180f && angleDiff > -180f) { inputs.HorizontalAxis = angleDiff > 0f ? -1f : 1f; } else { inputs.HorizontalAxis = angleDiff > 0f ? 1f : -1f; } // AI cars always accelerate to full speed inputs.AccelerationAxis = 1f; }).WithReadOnly(controlPoints).ScheduleParallel(Dependency);
void DrawCurve(float3[] controlPoints) { var lineCount = 50; for (int i = 1; i <= lineCount; i++) { var previousRatio = (i - 1) / (float)lineCount; var ratio = i / (float)lineCount; using (NativeArray <float3> points = new NativeArray <float3>(controlPoints, Allocator.Temp)) { var previousPosition = SplineUtils.GetPoint(points, 0, previousRatio); var currentPosition = SplineUtils.GetPoint(points, 0, ratio); Gizmos.DrawLine(previousPosition, currentPosition); } } }
protected override JobHandle OnUpdate(JobHandle inputDeps) { var race = GetSingleton <Race>(); if (!race.IsRaceStarted) { return(inputDeps); } var updateCarLapSystem = World.GetExistingSystem <UpdateCarLapProgress>(); if (!updateCarLapSystem.AreControlPointsInitialized) { return(inputDeps); } var controlPoints = updateCarLapSystem.ControlPoints; return(Entities.ForEach((ref LapProgress lapProgress, ref Translation translation) => { var controlPointIndex = lapProgress.CurrentControlPoint; var controlPointProgress = lapProgress.CurrentControlPointProgress; var firstControlPointIndex = controlPointIndex == 0 ? controlPoints.Length - 1 : controlPointIndex - 1; var closestPoint = SplineUtils.GetPoint(controlPoints, firstControlPointIndex, controlPointProgress); var distanceFromCenterOfTrackSq = math.distancesq(closestPoint, translation.Value); var maxDistanceFromCenterOfRoad = 6.4f; if (distanceFromCenterOfTrackSq > maxDistanceFromCenterOfRoad * maxDistanceFromCenterOfRoad) { var clampedPosition = closestPoint + math.normalize(translation.Value - closestPoint) * maxDistanceFromCenterOfRoad; translation.Value.xz = clampedPosition.xz; } }).WithReadOnly(controlPoints).Schedule(inputDeps)); }