protected override void OnUpdate()
    {
        var ecb = bi_ECB.CreateCommandBuffer().AsParallelWriter();

        elapsedTime += Time.DeltaTime;
        if (elapsedTime > UnitManager.instance.spawnEvery)
        {
            elapsedTime = 0;
            Entities
            .WithBurst(synchronousCompilation: true)
            .ForEach((Entity e, int entityInQueryIndex, in Unit_Initializer_Component uic, in LocalToWorld ltw) =>
            {
                for (int i = 0; i < uic.xGridCount; i++)
                {
                    for (int j = 0; j < uic.zGridCount; j++)
                    {
                        Entity defEntity = ecb.Instantiate(entityInQueryIndex, uic.prefabToSpawn);
                        float3 position  = new float3(i * uic.xPadding, uic.baseOffset, j * uic.zPadding) + uic.currentPosition;
                        ecb.SetComponent(entityInQueryIndex, defEntity, new Translation {
                            Value = position
                        });
                        ecb.AddComponent <Unit_Component>(entityInQueryIndex, defEntity);
                        ecb.AddBuffer <Unit_Buffer>(entityInQueryIndex, defEntity);

                        Unit_Component uc     = new Unit_Component();
                        uc.fromLocation       = position;
                        uc.toLocation         = new float3(position.x, position.y, position.z + uic.destinationDistanceZAxis);
                        uc.currentBufferIndex = 0;
                        uc.speed = (float)new Random(uic.seed + (uint)(i * j)).NextDouble(uic.minSpeed, uic.maxSpeed);
                        uc.minDistanceReached = uic.minDistanceReached;
                        ecb.SetComponent(entityInQueryIndex, defEntity, uc);
                    }
                }
                //ecb.DestroyEntity(entityInQueryIndex, e);
            }).ScheduleParallel();
    protected override void OnUpdate()
    {
        float deltaTime = Time.DeltaTime;
        int   i         = 0;

        Entities.
        WithNone <Unit_Routed>().
        WithoutBurst().
        WithStructuralChanges().
        ForEach((Entity e, ref Unit_Component uc, ref DynamicBuffer <Unit_Buffer> ub) =>
        {
            if (i <= UnitManager.instance.maxEntitiesRoutedPerFrame)
            {
                int fromKey = ((int)uc.fromLocation.x + (int)uc.fromLocation.y + (int)uc.fromLocation.z) * UnitManager.instance.maxPathSize;
                int toKey   = ((int)uc.toLocation.x + (int)uc.toLocation.y + (int)uc.toLocation.z) * UnitManager.instance.maxPathSize;
                int key     = fromKey + toKey;
                //Cached path
                if (UnitManager.instance.useCache && allPaths.ContainsKey(key) && !uc.routed)
                {
                    allPaths.TryGetValue(key, out float3[] cachedPath);
                    for (int h = 0; h < cachedPath.Length; h++)
                    {
                        ub.Add(new Unit_Buffer {
                            wayPoints = cachedPath[h]
                        });
                    }
                    uc.routed          = true;
                    uc.usingCachedPath = true;
                    EntityManager.AddComponent <Unit_Routed>(e);
                    return;
                }
                //Job
                else if (!uc.routed)
                {
                    NavMeshQuery currentQuery = new NavMeshQuery(navMeshWorld, Allocator.Persistent, UnitManager.instance.maxPathNodePoolSize);
                    SinglePathFindingJob spfj = new SinglePathFindingJob()
                    {
                        query            = currentQuery,
                        nml_FromLocation = uc.nml_FromLocation,
                        nml_ToLocation   = uc.nml_ToLocation,
                        fromLocation     = uc.fromLocation,
                        toLocation       = uc.toLocation,
                        extents          = extents,
                        maxIteration     = UnitManager.instance.maxIterations,
                        result           = results[i],
                        statusOutput     = statusOutputs[i],
                        maxPathSize      = UnitManager.instance.maxPathSize,
                        ub = ub
                    };
                    routedEntities.Add(e);
                    queries.Add(currentQuery);
                    jobHandles.Add(spfj.Schedule());
                }
                i++;
            }
            else
            {
                return;
            }
        }).Run();

        int n = 0;
        NativeArray <JobHandle> jhs = new NativeArray <JobHandle>(jobHandles.Count, Allocator.Temp);

        foreach (JobHandle jh in jobHandles)
        {
            jhs[n] = jh;
            n++;
        }
        JobHandle.CompleteAll(jhs);
        jhs.Dispose();

        int j = 0;

        foreach (JobHandle jh in jobHandles)
        {
            if (statusOutputs[j][0] == 1)
            {
                if (UnitManager.instance.useCache && !allPaths.ContainsKey(statusOutputs[j][1]))
                {
                    float3[] wayPoints = new float3[statusOutputs[j][2]];
                    for (int k = 0; k < statusOutputs[j][2]; k++)
                    {
                        wayPoints[k] = results[j][k];
                    }
                    if (wayPoints.Length > 0)
                    {
                        allPaths.Add(statusOutputs[j][1], wayPoints);
                    }
                }
                Unit_Component uc = EntityManager.GetComponentData <Unit_Component>(routedEntities[j]);
                uc.routed = true;
                EntityManager.SetComponentData <Unit_Component>(routedEntities[j], uc);
                EntityManager.AddComponent <Unit_Routed>(routedEntities[j]);
            }
            queries[j].Dispose();
            j++;
        }
        routedEntities.Clear();
        jobHandles.Clear();
        queries.Clear();

        //Movement
        Entities
        .WithAll <Unit_Routed>().ForEach((ref Unit_Component uc, ref DynamicBuffer <Unit_Buffer> ub, ref Translation trans) =>
        {
            if (ub.Length > 0 && uc.routed)
            {
                uc.waypointDirection = math.normalize(ub[uc.currentBufferIndex].wayPoints - trans.Value);
                trans.Value         += uc.waypointDirection * uc.speed * deltaTime;
                if (!uc.reached && math.distance(trans.Value, ub[uc.currentBufferIndex].wayPoints) <= uc.minDistanceReached && uc.currentBufferIndex < ub.Length - 1)
                {
                    uc.currentBufferIndex = uc.currentBufferIndex + 1;
                    if (uc.currentBufferIndex == ub.Length - 1)
                    {
                        uc.reached = true;
                    }
                }
                else if (uc.reached && math.distance(trans.Value, ub[uc.currentBufferIndex].wayPoints) <= uc.minDistanceReached && uc.currentBufferIndex > 0)
                {
                    uc.currentBufferIndex = uc.currentBufferIndex - 1;
                    if (uc.currentBufferIndex == 0)
                    {
                        uc.reached = false;
                    }
                }
            }
        }).ScheduleParallel();
    }