static void HandleCompletePath(ComponentDataFromEntity <LocalToWorld> localToWorldFromEntity, Entity entity, Rotation rotation, ref NavAgent agent, Parent surface, Translation translation, PhysicsWorld physicsWorld, float elapsedSeconds, EntityCommandBuffer.ParallelWriter commandBuffer, int entityInQueryIndex, NavSettings settings) { var rayInput = new RaycastInput { Start = localToWorldFromEntity[entity].Position + agent.Offset, End = math.forward(rotation.Value) * settings.ObstacleRaycastDistanceMax, Filter = new CollisionFilter { BelongsTo = NavUtil.ToBitMask(settings.ColliderLayer), CollidesWith = NavUtil.ToBitMask(settings.ObstacleLayer) } }; if ( !surface.Value.Equals(agent.DestinationSurface) && !NavUtil.ApproxEquals(translation.Value, agent.LocalDestination, settings.StoppingDistance) && !physicsWorld.CastRay(rayInput, out _) ) { agent.JumpSeconds = elapsedSeconds; commandBuffer.RemoveComponent <NavWalking>(entityInQueryIndex, entity); commandBuffer.RemoveComponent <NavSteering>(entityInQueryIndex, entity); commandBuffer.AddComponent <NavJumping>(entityInQueryIndex, entity); commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity); return; } commandBuffer.RemoveComponent <NavWalking>(entityInQueryIndex, entity); commandBuffer.RemoveComponent <NavSteering>(entityInQueryIndex, entity); commandBuffer.RemoveComponent <NavDestination>(entityInQueryIndex, entity); }
protected override void OnUpdate() { var commandBuffer = barrier.CreateCommandBuffer().AsParallelWriter(); var elapsedSeconds = (float)Time.ElapsedTime; var deltaSeconds = Time.DeltaTime; var physicsWorld = buildPhysicsWorld.PhysicsWorld; var settings = navSystem.Settings; var pathBufferFromEntity = GetBufferFromEntity <NavPathBufferElement>(); var localToWorldFromEntity = GetComponentDataFromEntity <LocalToWorld>(true); var fallingFromEntity = GetComponentDataFromEntity <NavFalling>(true); var jumpingFromEntity = GetComponentDataFromEntity <NavJumping>(true); var flockingFromEntity = GetComponentDataFromEntity <NavFlocking>(true); Entities .WithNone <NavProblem, NavPlanning>() .WithAll <NavWalking, LocalToParent>() .WithReadOnly(localToWorldFromEntity) .WithReadOnly(physicsWorld) .WithReadOnly(jumpingFromEntity) .WithReadOnly(fallingFromEntity) .WithReadOnly(flockingFromEntity) .WithNativeDisableParallelForRestriction(pathBufferFromEntity) .ForEach((Entity entity, int entityInQueryIndex, ref NavAgent agent, ref Translation translation, ref NavSteering navSteering, ref Rotation rotation, in Parent surface) => { if (!pathBufferFromEntity.HasComponent(entity) || agent.DestinationSurface.Equals(Entity.Null)) { return; } var pathBuffer = pathBufferFromEntity[entity]; if (pathBuffer.Length == 0) { HandleCompletePath(localToWorldFromEntity, entity, rotation, ref agent, surface, translation, physicsWorld, elapsedSeconds, commandBuffer, entityInQueryIndex, settings); return; } var pathBufferIndex = pathBuffer.Length - 1; if (NavUtil.ApproxEquals(translation.Value, pathBuffer[pathBufferIndex].Value, settings.StoppingDistance)) { pathBuffer.RemoveAt(pathBufferIndex); } if (pathBuffer.Length == 0) { return; } pathBufferIndex = pathBuffer.Length - 1; var heading = math.normalizesafe(pathBuffer[pathBufferIndex].Value - translation.Value); if ( !jumpingFromEntity.HasComponent(entity) && !fallingFromEntity.HasComponent(entity) && flockingFromEntity.HasComponent(entity) ) { navSteering.AgentAvoidanceSteering.y = navSteering.SeparationSteering.y = navSteering.AlignmentSteering.y = navSteering.CohesionSteering.y = 0; heading = math.normalizesafe( heading + navSteering.AgentAvoidanceSteering + navSteering.SeparationSteering + navSteering.AlignmentSteering + navSteering.CohesionSteering ); if (!navSteering.CollisionAvoidanceSteering.Equals(float3.zero)) { heading = math.normalizesafe(heading + navSteering.CollisionAvoidanceSteering); } } navSteering.CurrentHeading = heading; }) .WithName("NavSteeringJob") .ScheduleParallel(); barrier.AddJobHandleForProducer(Dependency); buildPhysicsWorld.AddInputDependencyToComplete(Dependency); var jumpBufferFromEntity = GetBufferFromEntity <NavJumpBufferElement>(); Entities .WithNone <NavProblem>() .WithAny <NavFalling, NavJumping>() .WithAll <LocalToParent>() .WithReadOnly(fallingFromEntity) .WithReadOnly(jumpBufferFromEntity) .WithReadOnly(localToWorldFromEntity) .ForEach((Entity entity, int entityInQueryIndex, ref Translation translation, in NavAgent agent, in Parent surface) => { if (agent.DestinationSurface.Equals(Entity.Null)) { return; } commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity); if (!jumpBufferFromEntity.HasComponent(entity)) { return; } var jumpBuffer = jumpBufferFromEntity[entity]; if (jumpBuffer.Length == 0 && !fallingFromEntity.HasComponent(entity)) { return; } var destinationSurfaceLocalToWorld = localToWorldFromEntity[agent.DestinationSurface]; var worldDestination = agent.LocalDestination.ToWorld(destinationSurfaceLocalToWorld); var velocity = math.distance(translation.Value, worldDestination) / (math.sin(2 * math.radians(agent.JumpDegrees)) / agent.JumpGravity); var yVelocity = math.sqrt(velocity) * math.sin(math.radians(agent.JumpDegrees)); var waypoint = translation.Value + math.up() * float.NegativeInfinity; if (!fallingFromEntity.HasComponent(entity)) { var xVelocity = math.sqrt(velocity) * math.cos(math.radians(agent.JumpDegrees)) * agent.JumpSpeedMultiplierX; var surfaceLocalToWorld = localToWorldFromEntity[surface.Value]; waypoint = jumpBuffer[0].Value .ToWorld(destinationSurfaceLocalToWorld) .ToLocal(surfaceLocalToWorld); translation.Value.MoveTowards(waypoint, xVelocity * deltaSeconds); } translation.Value.y += (yVelocity - (elapsedSeconds - agent.JumpSeconds) * agent.JumpGravity) * deltaSeconds * agent.JumpSpeedMultiplierY; if (elapsedSeconds - agent.JumpSeconds >= settings.JumpSecondsMax) { commandBuffer.RemoveComponent <NavJumping>(entityInQueryIndex, entity); commandBuffer.AddComponent <NavFalling>(entityInQueryIndex, entity); } if (!NavUtil.ApproxEquals(translation.Value, waypoint, 1)) { return; } commandBuffer.AddComponent <NavNeedsSurface>(entityInQueryIndex, entity); commandBuffer.RemoveComponent <NavJumping>(entityInQueryIndex, entity); })
protected override void OnUpdate() { var commandBuffer = barrier.CreateCommandBuffer().AsParallelWriter(); var elapsedSeconds = (float)Time.ElapsedTime; var deltaSeconds = Time.DeltaTime; var physicsWorld = buildPhysicsWorld.PhysicsWorld; var settings = navSystem.Settings; var pathBufferFromEntity = GetBufferFromEntity <NavPathBufferElement>(); var localToWorldFromEntity = GetComponentDataFromEntity <LocalToWorld>(true); Entities .WithNone <NavProblem, NavPlanning>() .WithAll <NavWalking, LocalToParent>() .WithReadOnly(localToWorldFromEntity) .WithReadOnly(physicsWorld) .WithNativeDisableParallelForRestriction(pathBufferFromEntity) .ForEach((Entity entity, int entityInQueryIndex, ref NavAgent agent, ref Translation translation, ref Rotation rotation, in Parent surface) => { if (!pathBufferFromEntity.HasComponent(entity) || agent.DestinationSurface.Equals(Entity.Null)) { return; } var pathBuffer = pathBufferFromEntity[entity]; if (pathBuffer.Length == 0) { HandleCompletePath(localToWorldFromEntity, entity, rotation, ref agent, ref pathBuffer, surface, translation, physicsWorld, elapsedSeconds, commandBuffer, entityInQueryIndex, settings); return; } var pathBufferIndex = pathBuffer.Length - 1; if (NavUtil.ApproxEquals(translation.Value, pathBuffer[pathBufferIndex].Value, settings.StoppingDistance)) { pathBuffer.RemoveAt(pathBufferIndex); } if (pathBuffer.Length == 0) { return; } pathBufferIndex = pathBuffer.Length - 1; translation.Value = Vector3.MoveTowards(translation.Value, pathBuffer[pathBufferIndex].Value, agent.TranslationSpeed * deltaSeconds); var lookAt = NavUtil.MultiplyPoint3x4( // To world (from local in terms of destination surface). localToWorldFromEntity[agent.DestinationSurface].Value, pathBuffer[pathBufferIndex].Value ); lookAt = NavUtil.MultiplyPoint3x4( // To local (in terms of agent's current surface). math.inverse(localToWorldFromEntity[surface.Value].Value), lookAt ); lookAt.y = translation.Value.y; var lookRotation = quaternion.LookRotationSafe(lookAt - translation.Value, math.up()); if (math.length(agent.SurfacePointNormal) > 0.01f) { lookRotation = Quaternion.FromToRotation(math.up(), agent.SurfacePointNormal) * lookRotation; } rotation.Value = math.slerp(rotation.Value, lookRotation, deltaSeconds / agent.RotationSpeed); }) .WithName("NavWalkJob") .ScheduleParallel(); barrier.AddJobHandleForProducer(Dependency); buildPhysicsWorld.AddInputDependency(Dependency); var jumpBufferFromEntity = GetBufferFromEntity <NavJumpBufferElement>(); var fallingFromEntity = GetComponentDataFromEntity <NavFalling>(); Entities .WithNone <NavProblem>() .WithAny <NavFalling, NavJumping>() .WithAll <LocalToParent>() .WithReadOnly(fallingFromEntity) .WithReadOnly(jumpBufferFromEntity) .WithReadOnly(localToWorldFromEntity) .ForEach((Entity entity, int entityInQueryIndex, ref Translation translation, in NavAgent agent, in Parent surface) => { if (agent.DestinationSurface.Equals(Entity.Null)) { return; } commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity); if (!jumpBufferFromEntity.HasComponent(entity)) { return; } var jumpBuffer = jumpBufferFromEntity[entity]; if (jumpBuffer.Length == 0 && !fallingFromEntity.HasComponent(entity)) { return; } var destination = NavUtil.MultiplyPoint3x4( localToWorldFromEntity[agent.DestinationSurface].Value, agent.LocalDestination ); var velocity = Vector3.Distance(translation.Value, destination) / (math.sin(2 * math.radians(agent.JumpDegrees)) / agent.JumpGravity); var yVelocity = math.sqrt(velocity) * math.sin(math.radians(agent.JumpDegrees)); var waypoint = translation.Value + math.up() * float.NegativeInfinity; if (!fallingFromEntity.HasComponent(entity)) { var xVelocity = math.sqrt(velocity) * math.cos(math.radians(agent.JumpDegrees)) * agent.JumpSpeedMultiplierX; waypoint = NavUtil.MultiplyPoint3x4( // To world (from local in terms of destination surface). localToWorldFromEntity[agent.DestinationSurface].Value, jumpBuffer[0].Value ); waypoint = NavUtil.MultiplyPoint3x4( // To local (in terms of agent's current surface). math.inverse(localToWorldFromEntity[surface.Value].Value), waypoint ); translation.Value = Vector3.MoveTowards(translation.Value, waypoint, xVelocity * deltaSeconds); } translation.Value.y += (yVelocity - (elapsedSeconds - agent.JumpSeconds) * agent.JumpGravity) * deltaSeconds * agent.JumpSpeedMultiplierY; if (elapsedSeconds - agent.JumpSeconds >= settings.JumpSecondsMax) { commandBuffer.RemoveComponent <NavJumping>(entityInQueryIndex, entity); commandBuffer.AddComponent <NavFalling>(entityInQueryIndex, entity); } if (!NavUtil.ApproxEquals(translation.Value, waypoint, 1)) { return; } commandBuffer.AddComponent <NavNeedsSurface>(entityInQueryIndex, entity); commandBuffer.RemoveComponent <NavJumping>(entityInQueryIndex, entity); })
protected override void OnUpdate() { var commandBuffer = barrier.CreateCommandBuffer().AsParallelWriter(); var elapsedSeconds = (float)Time.ElapsedTime; var deltaSeconds = Time.DeltaTime; var physicsWorld = buildPhysicsWorld.PhysicsWorld; var pathBufferFromEntity = GetBufferFromEntity <NavPathBufferElement>(true); var localToWorldFromEntity = GetComponentDataFromEntity <LocalToWorld>(true); Dependency = JobHandle.CombineDependencies(Dependency, buildPhysicsWorld.GetOutputDependency()); Entities .WithNone <NavHasProblem, NavPlanning, NavJumping>() .WithAll <NavLerping, LocalToParent>() .WithReadOnly(pathBufferFromEntity) .WithReadOnly(localToWorldFromEntity) .WithReadOnly(physicsWorld) .ForEach((Entity entity, int entityInQueryIndex, ref NavAgent agent, ref Translation translation, ref Rotation rotation, in Parent surface) => { if (!pathBufferFromEntity.HasComponent(entity) || agent.DestinationSurface.Equals(Entity.Null)) { return; } var pathBuffer = pathBufferFromEntity[entity]; if (pathBuffer.Length == 0) { return; } if (agent.PathBufferIndex >= pathBuffer.Length) { --agent.PathBufferIndex; return; } var localDestination = agent.LocalDestination; var localWaypoint = pathBuffer[agent.PathBufferIndex].Value; if ( NavUtil.ApproxEquals(translation.Value, localWaypoint, 1) && ++agent.PathBufferIndex > pathBuffer.Length - 1 ) { var rayInput = new RaycastInput { Start = localToWorldFromEntity[entity].Position + agent.Offset, End = math.forward(rotation.Value) * NavConstants.OBSTACLE_RAYCAST_DISTANCE_MAX, Filter = new CollisionFilter { BelongsTo = NavUtil.ToBitMask(NavConstants.COLLIDER_LAYER), CollidesWith = NavUtil.ToBitMask(NavConstants.OBSTACLE_LAYER) } }; if ( !surface.Value.Equals(agent.DestinationSurface) && !NavUtil.ApproxEquals(translation.Value, localDestination, 1) && !physicsWorld.CastRay(rayInput, out RaycastHit hit) ) { agent.JumpSeconds = elapsedSeconds; commandBuffer.AddComponent <NavJumping>(entityInQueryIndex, entity); commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity); return; } commandBuffer.RemoveComponent <NavLerping>(entityInQueryIndex, entity); commandBuffer.RemoveComponent <NavNeedsDestination>(entityInQueryIndex, entity); agent.PathBufferIndex = 0; return; } translation.Value = Vector3.MoveTowards(translation.Value, localWaypoint, agent.TranslationSpeed * deltaSeconds); var lookAt = NavUtil.MultiplyPoint3x4( // To world (from local in terms of destination surface). localToWorldFromEntity[agent.DestinationSurface].Value, localWaypoint ); lookAt = NavUtil.MultiplyPoint3x4( // To local (in terms of agent's current surface). math.inverse(localToWorldFromEntity[surface.Value].Value), lookAt ); lookAt.y = translation.Value.y; var lookRotation = quaternion.LookRotationSafe(lookAt - translation.Value, math.up()); if (math.length(agent.SurfacePointNormal) > 0.01f) { lookRotation = Quaternion.FromToRotation(math.up(), agent.SurfacePointNormal) * lookRotation; } rotation.Value = math.slerp(rotation.Value, lookRotation, deltaSeconds / agent.RotationSpeed); }) .WithName("NavWalkJob") .ScheduleParallel(); barrier.AddJobHandleForProducer(Dependency); var jumpBufferFromEntity = GetBufferFromEntity <NavJumpBufferElement>(); var fallingFromEntity = GetComponentDataFromEntity <NavFalling>(); Entities .WithNone <NavHasProblem>() .WithAny <NavFalling, NavJumping>() .WithAll <LocalToParent>() .WithReadOnly(fallingFromEntity) .WithReadOnly(jumpBufferFromEntity) .WithReadOnly(localToWorldFromEntity) .ForEach((Entity entity, int entityInQueryIndex, ref Translation translation, in NavAgent agent, in Parent surface) => { if (agent.DestinationSurface.Equals(Entity.Null)) { return; } commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity); if (!jumpBufferFromEntity.HasComponent(entity)) { return; } var jumpBuffer = jumpBufferFromEntity[entity]; if (jumpBuffer.Length == 0 && !fallingFromEntity.HasComponent(entity)) { return; } var destination = NavUtil.MultiplyPoint3x4( localToWorldFromEntity[agent.DestinationSurface].Value, agent.LocalDestination ); var velocity = Vector3.Distance(translation.Value, destination) / (math.sin(2 * math.radians(agent.JumpDegrees)) / agent.JumpGravity); var yVelocity = math.sqrt(velocity) * math.sin(math.radians(agent.JumpDegrees)); var waypoint = translation.Value + math.up() * float.NegativeInfinity; if (!fallingFromEntity.HasComponent(entity)) { var xVelocity = math.sqrt(velocity) * math.cos(math.radians(agent.JumpDegrees)) * agent.JumpSpeedMultiplierX; waypoint = NavUtil.MultiplyPoint3x4( // To world (from local in terms of destination surface). localToWorldFromEntity[agent.DestinationSurface].Value, jumpBuffer[0].Value ); waypoint = NavUtil.MultiplyPoint3x4( // To local (in terms of agent's current surface). math.inverse(localToWorldFromEntity[surface.Value].Value), waypoint ); translation.Value = Vector3.MoveTowards(translation.Value, waypoint, xVelocity * deltaSeconds); } translation.Value.y += (yVelocity - (elapsedSeconds - agent.JumpSeconds) * agent.JumpGravity) * deltaSeconds * agent.JumpSpeedMultiplierY; if (elapsedSeconds - agent.JumpSeconds >= NavConstants.JUMP_SECONDS_MAX) { commandBuffer.RemoveComponent <NavJumping>(entityInQueryIndex, entity); commandBuffer.AddComponent <NavFalling>(entityInQueryIndex, entity); } if (!NavUtil.ApproxEquals(translation.Value, waypoint, 1)) { return; } commandBuffer.AddComponent <NavNeedsSurface>(entityInQueryIndex, entity); commandBuffer.RemoveComponent <NavJumping>(entityInQueryIndex, entity); })
protected override void OnUpdate() { var commandBuffer = barrier.CreateCommandBuffer().AsParallelWriter(); var elapsedSeconds = (float)Time.ElapsedTime; var localToWorldFromEntity = GetComponentDataFromEntity <LocalToWorld>(true); var physicsWorld = buildPhysicsWorld.PhysicsWorld; var settings = navSystem.Settings; Entities .WithNone <NavProblem>() .WithChangeFilter <NavDestination>() .WithReadOnly(localToWorldFromEntity) .WithReadOnly(physicsWorld) .ForEach((Entity entity, int entityInQueryIndex, ref NavAgent agent, in NavDestination destination) => { if (elapsedSeconds - agent.DestinationSeconds < settings.DestinationRateLimitSeconds) { commandBuffer.AddComponent <NavDestination>(entityInQueryIndex, entity, destination); // So that the change filter applies next frame. return; } var collider = SphereCollider.Create( new SphereGeometry() { Center = destination.WorldPoint, Radius = settings.DestinationSurfaceColliderRadius }, new CollisionFilter() { BelongsTo = NavUtil.ToBitMask(settings.ColliderLayer), CollidesWith = NavUtil.ToBitMask(settings.SurfaceLayer), } ); unsafe { var castInput = new ColliderCastInput() { Collider = (Collider *)collider.GetUnsafePtr(), Orientation = quaternion.identity }; if (!physicsWorld.CastCollider(castInput, out ColliderCastHit hit)) { commandBuffer.RemoveComponent <NavDestination>(entityInQueryIndex, entity); // Ignore invalid destinations. return; } var localDestination = destination.WorldPoint.ToLocal(localToWorldFromEntity[hit.Entity]) + agent.Offset; if (NavUtil.ApproxEquals(localDestination, agent.LocalDestination, destination.Tolerance)) { return; } if (destination.Teleport) { commandBuffer.SetComponent <Parent>(entityInQueryIndex, entity, new Parent { Value = hit.Entity }); commandBuffer.SetComponent <Translation>(entityInQueryIndex, entity, new Translation { Value = localDestination }); commandBuffer.RemoveComponent <NavDestination>(entityInQueryIndex, entity); return; } agent.DestinationSurface = physicsWorld.Bodies[hit.RigidBodyIndex].Entity; agent.LocalDestination = localDestination; agent.DestinationSeconds = elapsedSeconds; commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity); } }) .WithName("CreateDestinationJob") .ScheduleParallel(); barrier.AddJobHandleForProducer(Dependency); buildPhysicsWorld.AddInputDependencyToComplete(Dependency); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { var commandBuffer = barrier.CreateCommandBuffer().ToConcurrent(); var elapsedSeconds = (float)Time.ElapsedTime; var deltaSeconds = Time.DeltaTime; var physicsWorld = buildPhysicsWorldSystem.PhysicsWorld; var pathBufferFromEntity = GetBufferFromEntity <NavPathBufferElement>(true); var localToWorldFromEntity = GetComponentDataFromEntity <LocalToWorld>(true); var avoidantFromEntity = GetComponentDataFromEntity <NavAvoidant>(true); var walkJob = Entities .WithNone <NavPlanning, NavJumping>() .WithAll <NavLerping, Parent, LocalToParent>() .WithReadOnly(pathBufferFromEntity) .WithReadOnly(localToWorldFromEntity) .WithReadOnly(avoidantFromEntity) .ForEach((Entity entity, int entityInQueryIndex, ref NavAgent agent, ref Translation translation, ref Rotation rotation) => { var pathBuffer = pathBufferFromEntity[entity]; if (pathBuffer.Length == 0) { return; } if (agent.PathBufferIndex >= pathBuffer.Length) { --agent.PathBufferIndex; return; } var destination = pathBuffer[agent.PathBufferIndex].Value; if (!agent.DestinationSurface.Equals(Entity.Null)) { agent.WorldDestination = NavUtil.MultiplyPoint3x4( localToWorldFromEntity[agent.DestinationSurface].Value, agent.LocalDestination ); } var avoidant = avoidantFromEntity.Exists(entity); var worldDestination = avoidant ? agent.AvoidanceDestination : agent.WorldDestination; var worldPosition = localToWorldFromEntity[entity].Position; if ( NavUtil.ApproxEquals(translation.Value, destination, 1) && ++agent.PathBufferIndex > pathBuffer.Length - 1 ) { if (!avoidant) { var rayInput = new RaycastInput { Start = translation.Value, End = math.forward(rotation.Value) * NavConstants.OBSTACLE_RAYCAST_DISTANCE_MAX, Filter = CollisionFilter.Default }; if ( !physicsWorld.CastRay(rayInput, out RaycastHit hit) && !NavUtil.ApproxEquals(worldPosition, worldDestination, 1) ) { agent.JumpSeconds = elapsedSeconds; commandBuffer.AddComponent <NavJumping>(entityInQueryIndex, entity); commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity); return; } } commandBuffer.RemoveComponent <NavLerping>(entityInQueryIndex, entity); if (avoidant) { commandBuffer.RemoveComponent <NavAvoidant>(entityInQueryIndex, entity); commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity); } agent.PathBufferIndex = 0; return; } var lookAt = worldDestination; lookAt.y = worldPosition.y; rotation.Value = quaternion.LookRotationSafe(lookAt - worldPosition, math.up()); translation.Value = Vector3.MoveTowards(translation.Value, destination, agent.TranslationSpeed * deltaSeconds); agent.LastDestination = agent.WorldDestination; }) .WithName("NavWalkJob") .Schedule( JobHandle.CombineDependencies( inputDeps, buildPhysicsWorldSystem.FinalJobHandle ) ); var jumpBufferFromEntity = GetBufferFromEntity <NavJumpBufferElement>(); var fallingFromEntity = GetComponentDataFromEntity <NavFalling>(); var artificialGravityJob = Entities .WithAny <NavFalling, NavJumping>() .WithAll <Parent, LocalToParent>() .WithReadOnly(fallingFromEntity) .WithNativeDisableParallelForRestriction(jumpBufferFromEntity) .ForEach((Entity entity, int entityInQueryIndex, ref NavAgent agent, ref Translation translation) => { commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity); // For sticking the landing. var jumpBuffer = jumpBufferFromEntity[entity]; if (jumpBuffer.Length == 0 && !fallingFromEntity.Exists(entity)) { return; } var velocity = Vector3.Distance(translation.Value, agent.WorldDestination) / (math.sin(2 * math.radians(agent.JumpDegrees)) / agent.JumpGravity); var yVelocity = math.sqrt(velocity) * math.sin(math.radians(agent.JumpDegrees)); var destination = translation.Value + math.up() * float.NegativeInfinity; if (!fallingFromEntity.Exists(entity)) { var xVelocity = math.sqrt(velocity) * math.cos(math.radians(agent.JumpDegrees)); destination = jumpBuffer[0].Value; translation.Value = Vector3.MoveTowards(translation.Value, destination, xVelocity * deltaSeconds); } translation.Value.y += (yVelocity - (elapsedSeconds - agent.JumpSeconds) * agent.JumpGravity) * deltaSeconds; if (elapsedSeconds - agent.JumpSeconds >= NavConstants.JUMP_SECONDS_MAX) { commandBuffer.RemoveComponent <NavJumping>(entityInQueryIndex, entity); commandBuffer.AddComponent <NavFalling>(entityInQueryIndex, entity); } if (!NavUtil.ApproxEquals(translation.Value, destination, 1)) { return; } commandBuffer.AddComponent <NavNeedsSurface>(entityInQueryIndex, entity); commandBuffer.RemoveComponent <NavJumping>(entityInQueryIndex, entity); jumpBuffer.Clear(); }) .WithName("NavArtificialGravityJob") .Schedule(walkJob); barrier.AddJobHandleForProducer(artificialGravityJob); return(artificialGravityJob); }