protected override void OnUpdate()
    {
        float deltaTime = Time.DeltaTime;

        EntityQuery eq = GetEntityQuery(typeof(UnitV2_Component));

        cellVsEntityPositions.Clear();
        if (eq.CalculateEntityCount() > cellVsEntityPositions.Capacity)
        {
            cellVsEntityPositions.Capacity = eq.CalculateEntityCount();
        }

        NativeMultiHashMap <int, float3> .ParallelWriter cellVsEntityPositionsParallel = cellVsEntityPositions.AsParallelWriter();
        Entities
        .ForEach((ref UnitV2_Component uc, ref Translation trans) =>
        {
            cellVsEntityPositionsParallel.Add(GetUniqueKeyForPosition(trans.Value, 25), trans.Value);
        }).ScheduleParallel();

        //Resolve All Collisions in current cell and provide average avoidance direction

        /*NativeMultiHashMap<int, float3> cellVsEntityPositionsForJob = cellVsEntityPositions;
         * Entities
         *  .WithReadOnly(cellVsEntityPositionsForJob)
         *  .ForEach((ref UnitV2_Component uc, ref Translation trans) =>
         *  {
         *      int key = GetUniqueKeyForPosition(trans.Value, 25);
         *      NativeMultiHashMapIterator<int> nmhKeyIterator;
         *      float3 currentLocationToCheck;
         *      float distanceThreshold = 1.5f;
         *      float currentDistance;
         *      int total = 0;
         *      uc.avoidanceDirection = float3.zero;
         *      if (cellVsEntityPositionsForJob.TryGetFirstValue(key, out currentLocationToCheck, out nmhKeyIterator))
         *      {
         *          do
         *          {
         *              if (!trans.Value.Equals(currentLocationToCheck))
         *              {
         *                  currentDistance = math.sqrt(math.lengthsq(trans.Value - currentLocationToCheck));
         *                  if (currentDistance < distanceThreshold)
         *                  {
         *                      float3 distanceFromTo = trans.Value - currentLocationToCheck;
         *                      uc.avoidanceDirection = uc.avoidanceDirection + math.normalize(distanceFromTo / currentDistance);
         *                      total++;
         *                  }
         *                  //Debug
         *                  if (math.sqrt(math.lengthsq(trans.Value - currentLocationToCheck)) < 0.05f)
         *                  {
         *                      uc.timeStamp = 60;
         *                      uc.collided = true;
         *                  }
         *                  if (uc.collided)
         *                  {
         *                      uc.timeStamp = uc.timeStamp - deltaTime;
         *                  }
         *                  if (uc.timeStamp <= 0)
         *                  {
         *                      uc.collided = false;
         *                  }
         *              }
         *          } while (cellVsEntityPositionsForJob.TryGetNextValue(out currentLocationToCheck, ref nmhKeyIterator));
         *          if (total > 0)
         *          {
         *              uc.avoidanceDirection = uc.avoidanceDirection / total;
         *          }
         *      }
         *  }).ScheduleParallel();*/

        //Resolve nearest collision
        NativeMultiHashMap <int, float3> cellVsEntityPositionsForJob = cellVsEntityPositions;

        Entities
        .WithReadOnly(cellVsEntityPositionsForJob)
        .ForEach((ref UnitV2_Component uc, ref Translation trans) =>
        {
            int key = GetUniqueKeyForPosition(trans.Value, 25);
            NativeMultiHashMapIterator <int> nmhKeyIterator;
            float3 currentLocationToCheck;
            float currentDistance = 1.5f;
            int total             = 0;
            uc.avoidanceDirection = float3.zero;
            if (cellVsEntityPositionsForJob.TryGetFirstValue(key, out currentLocationToCheck, out nmhKeyIterator))
            {
                do
                {
                    if (!trans.Value.Equals(currentLocationToCheck))
                    {
                        if (currentDistance > math.sqrt(math.lengthsq(trans.Value - currentLocationToCheck)))
                        {
                            currentDistance       = math.sqrt(math.lengthsq(trans.Value - currentLocationToCheck));
                            float3 distanceFromTo = trans.Value - currentLocationToCheck;
                            uc.avoidanceDirection = math.normalize(distanceFromTo / currentDistance);
                            total++;
                        }
                        //Debug
                        if (math.sqrt(math.lengthsq(trans.Value - currentLocationToCheck)) < 0.05f)
                        {
                            uc.timeStamp = 60;
                            uc.collided  = true;
                        }
                        if (uc.collided)
                        {
                            uc.timeStamp = uc.timeStamp - deltaTime;
                        }
                        if (uc.timeStamp <= 0)
                        {
                            uc.collided = false;
                        }
                    }
                } while (cellVsEntityPositionsForJob.TryGetNextValue(out currentLocationToCheck, ref nmhKeyIterator));
                if (total > 0)
                {
                    uc.avoidanceDirection = uc.avoidanceDirection / total;
                }
            }
        }).ScheduleParallel();

        Entities
        .ForEach((ref UnitV2_Component uc, ref DynamicBuffer <Unit_Buffer> ub, ref Translation trans, ref Rotation rot) =>
        {
            if (ub.Length > 0 && uc.routed)
            {
                uc.waypointDirection = math.normalize(ub[uc.currentBufferIndex].wayPoints - trans.Value);
                uc.waypointDirection = uc.waypointDirection + uc.avoidanceDirection;
                trans.Value         += uc.waypointDirection * uc.speed * deltaTime;
                rot.Value            = math.slerp(rot.Value, quaternion.LookRotation(uc.waypointDirection, math.up()), deltaTime * uc.rotationSpeed);
                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();

        //Debug - HasKey

        /*Entities
         * .ForEach((ref UnitV2_Component uc, ref Translation trans) =>
         * {
         *  uc.hashKey = GetUniqueKeyForPosition(trans.Value, 20);
         * }).ScheduleParallel();*/
    }
        public void Execute(int jobIndex)
        {
            var       stateKey = StatesToUpdate[jobIndex];
            StateInfo updatedStateInfo;

            var actionCount = ActionLookup.CountValuesForKey(stateKey);

            if (actionCount == 0)
            {
                if (UpdateStateValueNoActions(stateKey, out updatedStateInfo))
                {
                    // Queue for write job
                    StateInfoLookup[stateKey] = updatedStateInfo;

                    // If a change has occured, queue predecessors for update
                    if (PredecessorGraph.TryGetFirstValue(stateKey, out var predecessorStateKey, out var predecessorIterator))
                    {
                        do
                        {
                            PredecessorStatesToUpdate.TryAdd(predecessorStateKey, default);
                        }while (PredecessorGraph.TryGetNextValue(out predecessorStateKey, ref predecessorIterator));
                    }
                }
                return;
            }

            // Allocate local container
            if (!m_ActionInfoForState.IsCreated)
            {
                m_ActionInfoForState = new NativeList <ActionInfo>(actionCount, Allocator.Temp);
            }
            else
            {
                m_ActionInfoForState.Clear();
            }

            // Expanded state. Only update if one or more actions have updated.
            var updateState = false;

            // Update all actions
            ActionLookup.TryGetFirstValue(stateKey, out var actionKey, out var stateActionIterator);
            do
            {
                var stateActionPair = new StateActionPair <TStateKey, TActionKey>(stateKey, actionKey);
                if (UpdateCumulativeReward(stateActionPair, out var actionInfo))
                {
                    // Queue for write job
                    ActionInfoLookup[stateActionPair] = actionInfo;

                    updateState = true;
                }

                m_ActionInfoForState.Add(actionInfo);
            }while (ActionLookup.TryGetNextValue(out actionKey, ref stateActionIterator));



            // If no actions have changed info, the state info will not change, so check before updating state.
            if (updateState && UpdateStateValueFromActions(stateKey, m_ActionInfoForState, out updatedStateInfo))
            {
                // Queue for write job
                StateInfoLookup[stateKey] = updatedStateInfo;

                // If a change has occured, queue predecessors for update
                if (PredecessorGraph.TryGetFirstValue(stateKey, out var predecessorStateKey, out var predecessorIterator))
                {
                    do
                    {
                        PredecessorStatesToUpdate.TryAdd(predecessorStateKey, default);
                    }while (PredecessorGraph.TryGetNextValue(out predecessorStateKey, ref predecessorIterator));
                }
            }
        }
            // パーティクル連動頂点ごと
            public void Execute(int index)
            {
                int vindex = vertexToParticleList[index];

                if (vindex < 0)
                {
                    return;
                }

                int pindex;

                //#if !UNITY_2018_4
#if false
                // v1.5.2
                // こちらのクォータニオン補間の方が安全
                int cnt = vertexToParticleMap.CountValuesForKey(vindex);
                if (cnt > 0)
                {
                    if (vertexToParticleMap.TryGetFirstValue(vindex, out pindex, out iterator))
                    {
                        float3     pos    = particlePosList[pindex];
                        quaternion rot    = particleRotList[pindex];
                        var        flag   = particleFlagList[pindex];
                        int        fixcnt = flag.IsKinematic() ? 1 : 0;
                        float      ratio  = 1.0f / cnt;

                        while (vertexToParticleMap.TryGetNextValue(out pindex, ref iterator))
                        {
                            float3     ppos = particlePosList[pindex];
                            quaternion prot = particleRotList[pindex];
                            flag = particleFlagList[pindex];

                            pos    += ppos;
                            rot     = math.slerp(rot, prot, ratio);
                            fixcnt += flag.IsKinematic() ? 1 : 0;
                        }
                        pos = pos / cnt;

                        virtualPosList[vindex] = pos;
                        virtualRotList[vindex] = rot;

                        // 仮想メッシュの法線/接線計算フラグ
                        //virtualVertexFlagList[vindex] = 1;
                        byte vflag = (byte)(PhysicsManagerMeshData.VirtualVertexFlag_Use
                                            | (fixcnt > 0 ? PhysicsManagerMeshData.VirtualVertexFlag_Fix : 0x0));
                        //virtualVertexFlagList[vindex] = (byte)(fixcnt == cnt ? 0 : 1);
                        virtualVertexFlagList[vindex] = vflag;
                    }
                }
#else
                if (vertexToParticleMap.TryGetFirstValue(vindex, out pindex, out iterator))
                {
                    float3 pos = 0;
                    float3 nor = 0;
                    float3 tan = 0;
                    int    cnt = 0;
                    do
                    {
                        // particle
                        var flag = particleFlagList[pindex];

                        // 固定パーティクルかつ固定は回転しない設定ならば打ち切る(v1.5.2)
                        if (flag.IsKinematic())
                        {
                            var team = teamDataList[teamIdList[pindex]];
                            if (team.IsFlag(PhysicsManagerTeamData.Flag_FixedNonRotation))
                            {
                                // 1つでも当てはまれば打ち切る
                                return;
                            }
                        }

                        float3     ppos = particlePosList[pindex];
                        quaternion prot = particleRotList[pindex];

                        pos += ppos;
                        nor += math.mul(prot, new float3(0, 0, 1));
                        tan += math.mul(prot, new float3(0, 1, 0));
                        cnt++;
                    }while (vertexToParticleMap.TryGetNextValue(out pindex, ref iterator));

                    if (cnt > 0)
                    {
                        pos = pos / cnt;
                        nor = math.normalize(nor);
                        tan = math.normalize(tan);

                        virtualPosList[vindex] = pos;
                        virtualRotList[vindex] = quaternion.LookRotation(nor, tan);

                        // 仮想メッシュの法線/接線計算フラグ
                        virtualVertexFlagList[vindex] = PhysicsManagerMeshData.VirtualVertexFlag_Use;
                    }
                }
#endif
            }
Ejemplo n.º 4
0
        protected virtual int SetUpInventoryItems(InventoryGroupWrapper inventoryGroup, int itemCount, Entity owner)
        {
            var foodList        = new NativeList <ItemHashValue>(Allocator.Temp);
            var potionList      = new NativeList <ItemHashValue>(Allocator.Temp);
            var treasureList    = new NativeList <ItemHashValue>(Allocator.Temp);
            var weaponList      = new NativeList <ItemHashValue>(Allocator.Temp);
            var magicWeaponList = new NativeList <ItemHashValue>(Allocator.Temp);
            var helmetList      = new NativeList <ItemHashValue>(Allocator.Temp);
            var chestList       = new NativeList <ItemHashValue>(Allocator.Temp);
            var bootsList       = new NativeList <ItemHashValue>(Allocator.Temp);

            var itemCounter = 0;

            this.Entities.With(this._itemsGroup).ForEach((Entity itemEntity, ref ItemComponent itemComponent, ref PickedUpComponent pickedUpComponent) =>
            {
                if (pickedUpComponent.Owner != owner)
                {
                    return;
                }

                itemCounter++;
                var item = ItemsManagerComponent.Instance.ItemsStoreComponent.Items[itemComponent.StoreIndex];
                switch (item.ItemType)
                {
                case ItemType.Food:
                    foodList.Add(
                        new ItemHashValue
                    {
                        Entity        = itemEntity,
                        ItemComponent = itemComponent
                    });
                    break;

                case ItemType.Potion:
                    potionList.Add(
                        new ItemHashValue
                    {
                        Entity        = itemEntity,
                        ItemComponent = itemComponent
                    });
                    break;

                case ItemType.Treasure:
                    treasureList.Add(
                        new ItemHashValue
                    {
                        Entity        = itemEntity,
                        ItemComponent = itemComponent
                    });
                    break;

                case ItemType.Gear:
                    switch (item.GearType)
                    {
                    case GearType.Helmet:
                        helmetList.Add(
                            new ItemHashValue
                        {
                            Entity        = itemEntity,
                            ItemComponent = itemComponent
                        });
                        break;

                    case GearType.Chest:
                        chestList.Add(
                            new ItemHashValue
                        {
                            Entity        = itemEntity,
                            ItemComponent = itemComponent
                        });
                        break;

                    case GearType.Weapon:
                        weaponList.Add(
                            new ItemHashValue
                        {
                            Entity        = itemEntity,
                            ItemComponent = itemComponent
                        });
                        break;

                    case GearType.Boots:
                        bootsList.Add(
                            new ItemHashValue
                        {
                            Entity        = itemEntity,
                            ItemComponent = itemComponent
                        });
                        break;

                    case GearType.Magic:
                        magicWeaponList.Add(
                            new ItemHashValue
                        {
                            Entity        = itemEntity,
                            ItemComponent = itemComponent
                        });
                        break;
                    }
                    break;
                }
            });

            if (itemCounter != this.LastItemsCount || this.LastOwnerEntity != owner)
            {
                this.LastItemsCount  = itemCounter;
                this.LastOwnerEntity = owner;

                for (var i = inventoryGroup.Grid.transform.childCount - 1; i >= 0; i--)
                {
                    GameObject.Destroy(inventoryGroup.Grid.transform.GetChild(i).gameObject);
                }

                var itemsHashMap = new NativeMultiHashMap <int, ItemHashValue>(foodList.Length + potionList.Length + treasureList.Length, Allocator.Temp);
                for (var i = 0; i < foodList.Length; i++)
                {
                    itemsHashMap.Add(this.GetItemHash(foodList[i]), foodList[i]);
                }
                for (var i = 0; i < potionList.Length; i++)
                {
                    itemsHashMap.Add(this.GetItemHash(potionList[i]), potionList[i]);
                }
                for (var i = 0; i < treasureList.Length; i++)
                {
                    itemsHashMap.Add(this.GetItemHash(treasureList[i]), treasureList[i]);
                }

                if (itemsHashMap.Length > 0)
                {
                    var iterator = new NativeMultiHashMapIterator <int>();
                    var(keys, keysLength) = itemsHashMap.GetUniqueKeyArray(Allocator.Temp);
                    for (var keyI = 0; keyI < keysLength; keyI++)
                    {
                        if (!itemsHashMap.TryGetFirstValue(keys[keyI], out var hashValue, out iterator))
                        {
                            continue;
                        }

                        var button = this.AddInventoryButton(hashValue, inventoryGroup);

                        var itemsCount = 1;
                        while (itemsHashMap.TryGetNextValue(out hashValue, ref iterator))
                        {
                            itemsCount++;
                        }

                        if (itemsCount > 1)
                        {
                            button.Amount.text = itemsCount.ToString();
                        }
                        else
                        {
                            button.Amount.text = string.Empty;
                        }
                    }
                    keys.Dispose();
                }
                itemsHashMap.Dispose();

                for (var i = 0; i < weaponList.Length; i++)
                {
                    this.AddInventoryButton(weaponList[i], inventoryGroup);
                }
                for (var i = 0; i < magicWeaponList.Length; i++)
                {
                    this.AddInventoryButton(magicWeaponList[i], inventoryGroup);
                }
                for (var i = 0; i < helmetList.Length; i++)
                {
                    this.AddInventoryButton(helmetList[i], inventoryGroup);
                }
                for (var i = 0; i < chestList.Length; i++)
                {
                    this.AddInventoryButton(chestList[i], inventoryGroup);
                }
                for (var i = 0; i < bootsList.Length; i++)
                {
                    this.AddInventoryButton(bootsList[i], inventoryGroup);
                }
            }

            foodList.Dispose();
            potionList.Dispose();
            treasureList.Dispose();
            weaponList.Dispose();
            magicWeaponList.Dispose();
            helmetList.Dispose();
            chestList.Dispose();
            bootsList.Dispose();

            return(itemCounter);
        }
Ejemplo n.º 5
0
        public void Execute(ref Boid b)
        {
            int neighbourStartIndex = maxNeighbours * b.boidId;
            int neighbourCount      = 0;


            if (usePatritioning)
            {
                int surroundingCellCount = (int)Mathf.Ceil(neighbourDistance / cellSize);

                // Are we looking above and below?
                int sliceSurrounding = threedcells ? surroundingCellCount : 0;
                for (int slice = -sliceSurrounding; slice <= sliceSurrounding; slice++)
                {
                    for (int row = -surroundingCellCount; row <= surroundingCellCount; row++)
                    {
                        for (int col = -surroundingCellCount; col <= surroundingCellCount; col++)
                        {
                            Vector3 pos  = positions[b.boidId] + new Vector3(col * cellSize, slice * cellSize, row * cellSize);
                            int     cell = PartitionSpaceJob.PositionToCell(pos, cellSize, gridSize);

                            NativeMultiHashMapIterator <int> iterator;
                            int boidId;
                            if (cells.TryGetFirstValue(cell, out boidId, out iterator))
                            {
                                do
                                {
                                    if (boidId != b.boidId)
                                    {
                                        if (Vector3.Distance(positions[b.boidId], positions[boidId]) < neighbourDistance)
                                        {
                                            neighbours[neighbourStartIndex + neighbourCount] = boidId;
                                            neighbourCount++;
                                            if (neighbourCount == maxNeighbours)
                                            {
                                                b.taggedCount = neighbourCount;
                                                return;
                                            }
                                        }
                                    }
                                } while (cells.TryGetNextValue(out boidId, ref iterator));
                            }
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i < positions.Length; i++)
                {
                    if (i != b.boidId)
                    {
                        if (Vector3.Distance(positions[b.boidId], positions[i]) < neighbourDistance)
                        {
                            neighbours[neighbourStartIndex + neighbourCount] = i;
                            neighbourCount++;
                            if (neighbourCount == maxNeighbours)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            b.taggedCount = neighbourCount;
        }
Ejemplo n.º 6
0
        static void ApplyBlobAssetChanges(
            EntityManager entityManager,
            NativeArray <EntityGuid> packedEntityGuids,
            NativeMultiHashMap <int, Entity> packedEntities,
            NativeArray <ComponentType> packedTypes,
            NativeArray <BlobAssetChange> createdBlobAssets,
            NativeArray <byte> createdBlobAssetData,
            NativeArray <ulong> destroyedBlobAssets,
            NativeArray <BlobAssetReferenceChange> blobAssetReferenceChanges)
        {
            if (createdBlobAssets.Length == 0 && blobAssetReferenceChanges.Length == 0)
            {
                return;
            }

            var patcherBlobAssetSystem = entityManager.World.GetOrCreateSystem <EntityPatcherBlobAssetSystem>();

            var blobAssetDataPtr = (byte *)createdBlobAssetData.GetUnsafePtr();

            for (var i = 0; i < createdBlobAssets.Length; i++)
            {
                if (!patcherBlobAssetSystem.TryGetBlobAsset(createdBlobAssets[i].Hash, out _))
                {
                    patcherBlobAssetSystem.AllocateBlobAsset(blobAssetDataPtr, createdBlobAssets[i].Length, createdBlobAssets[i].Hash);
                }

                blobAssetDataPtr += createdBlobAssets[i].Length;
            }

            for (var i = 0; i < destroyedBlobAssets.Length; i++)
            {
                patcherBlobAssetSystem.ReleaseBlobAsset(destroyedBlobAssets[i]);
            }

            for (var i = 0; i < blobAssetReferenceChanges.Length; i++)
            {
                var packedComponent = blobAssetReferenceChanges[i].Component;
                var component       = packedTypes[packedComponent.PackedTypeIndex];
                var targetOffset    = blobAssetReferenceChanges[i].Offset;

                BlobAssetReferenceData targetBlobAssetReferenceData;
                if (patcherBlobAssetSystem.TryGetBlobAsset(blobAssetReferenceChanges[i].Value, out var blobAssetPtr))
                {
                    targetBlobAssetReferenceData = new BlobAssetReferenceData {
                        m_Ptr = (byte *)blobAssetPtr.Data
                    };
                }

                if (packedEntities.TryGetFirstValue(packedComponent.PackedEntityIndex, out var entity, out var iterator))
                {
                    do
                    {
                        if (!entityManager.Exists(entity))
                        {
                            Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but entity to patch does not exist.");
                        }
                        else if (!entityManager.HasComponent(entity, component))
                        {
                            Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but component in entity to patch does not exist.");
                        }
                        else
                        {
                            if (component.IsBuffer)
                            {
                                var pointer = (byte *)entityManager.GetBufferRawRW(entity, component.TypeIndex);
                                UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData));
                            }
#if !NET_DOTS
                            else if (component.IsManagedComponent)
                            {
                                var obj     = entityManager.GetManagedComponentDataAsObject(entity, component);
                                var pointer = (byte *)UnsafeUtility.PinGCObjectAndGetAddress(obj, out ulong handle);
                                pointer += TypeManager.ObjectOffset;
                                UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData));
                                UnsafeUtility.ReleaseGCObject(handle);
                            }
#endif
                            else
                            {
                                var pointer = (byte *)entityManager.GetComponentDataRawRW(entity, component.TypeIndex);
                                UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData));
                            }
                        }
                    }while (packedEntities.TryGetNextValue(out entity, ref iterator));
                }
            }

            // Workaround to catch some special cases where the memory is never released. (e.g. reloading a scene, toggling live-link on/off).
            patcherBlobAssetSystem.ReleaseUnusedBlobAssets();
        }
Ejemplo n.º 7
0
        public void Execute(int index)
        {
            var currentAsks = new NativeList <Offer>(Allocator.Temp);
            var currentBids = new NativeList <Offer>(Allocator.Temp);

            var numAsks = 0f;
            var numBids = 0f;

            if (TradeAsks.TryGetFirstValue(index, out var currentOffer, out var iterator))
            {
                do
                {
                    currentAsks.Add(currentOffer);
                    numAsks += currentOffer.Units;
                } while (TradeAsks.TryGetNextValue(out currentOffer, ref iterator));

                // Descending order (3, 2, 1).
                currentAsks.AsArray().Sort();
            }

            if (TradeBids.TryGetFirstValue(index, out currentOffer, out iterator))
            {
                do
                {
                    currentBids.Add(currentOffer);
                    numBids += currentOffer.Units;
                } while (TradeBids.TryGetNextValue(out currentOffer, ref iterator));

                // Randomizing bids
                var n = currentBids.Length;
                while (n-- > 1)
                {
                    var k           = Rng.NextInt(n + 1);
                    var placeholder = currentBids[k];
                    currentBids[k] = currentBids[n];
                    currentBids[n] = placeholder;
                }
            }

            AskHistory[index] = math.lerp(AskHistory[index], numAsks, 0.75f);
            BidHistory[index] = math.lerp(BidHistory[index], numBids, 0.75f);
            var numTraded   = 0f;
            var moneyTraded = 0f;

            while (currentBids.Length > 0 && currentAsks.Length > 0)
            {
                // Descending order
                var buyer  = currentBids[currentBids.Length - 1];
                var seller = currentAsks[currentAsks.Length - 1];

                var quantityTraded = math.min(buyer.Units, seller.Units);
                var clearingPrice  = seller.Cost;

                if (quantityTraded > 0)
                {
                    // Transferring goods
                    seller.Units -= quantityTraded;
                    buyer.Units  -= quantityTraded;

                    // Recording history
                    numTraded   += quantityTraded;
                    moneyTraded += clearingPrice * quantityTraded;

                    currentAsks[currentAsks.Length - 1] = seller;
                    currentBids[currentBids.Length - 1] = buyer;

                    var targetInv   = InventoryContents[seller.Source].AsNativeArray();
                    var placeholder = targetInv[index];
                    placeholder.Quantity -= quantityTraded;
                    // TODO: Find out why this is causing skyrocketing prices.
                    placeholder.RecordedPrice = math.lerp(placeholder.RecordedPrice, clearingPrice,
                                                          quantityTraded / (quantityTraded + placeholder.Quantity));
                    targetInv[index] = placeholder;

                    targetInv   = InventoryContents[buyer.Source].AsNativeArray();
                    placeholder = targetInv[index];
                    placeholder.RecordedPrice = clearingPrice;
                    placeholder.Quantity     += quantityTraded;
                    targetInv[index]          = placeholder;

                    DeltaMoney.Add(seller.Source, clearingPrice * quantityTraded);
                    DeltaMoney.Add(buyer.Source, -clearingPrice * quantityTraded);
                }

                if (seller.Units <= 0)
                {
                    currentAsks.RemoveAtSwapBack(currentAsks.Length - 1);
                }

                if (buyer.Units <= 0)
                {
                    currentBids.RemoveAtSwapBack(currentBids.Length - 1);
                }
            }

            for (var unsold = 0; unsold < currentAsks.Length; unsold++)
            {
                var seller      = currentAsks[unsold];
                var targetInv   = InventoryContents[seller.Source].AsNativeArray();
                var placeholder = targetInv[index];
                placeholder.RecordedPrice = math.clamp(
                    placeholder.RecordedPrice * (1 - 0.01f * math.sqrt(seller.Units)),
                    0.005f, 10f);
                targetInv[index] = placeholder;
            }

            TradeHistory[index] = numTraded;
            if (numTraded > 0)
            {
                PriceHistory[index] = moneyTraded / numTraded;
            }
        }
Ejemplo n.º 8
0
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            this.DisposeBuffers();
            var handle = inputDeps;

            // ----------------------------------------------
            // Allocate Memory
            var groupLength = this._rendererGroup.CalculateLength();

            this._localToWorlds     = new NativeArray <LocalToWorld>(groupLength, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            this._animationPlayData = new NativeArray <AnimationPlayData>(groupLength, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);


            // ----------------------------------------------
            // CopyComponentData
            handle = new CopyComponentData <LocalToWorld>
            {
                Source  = this._rendererGroup.GetComponentDataArray <LocalToWorld>(),
                Results = this._localToWorlds,
            }.Schedule(groupLength, 32, handle);
            handle = new CopyComponentData <AnimationPlayData>
            {
                Source  = this._rendererGroup.GetComponentDataArray <AnimationPlayData>(),
                Results = this._animationPlayData,
            }.Schedule(groupLength, 32, handle);


            // ----------------------------------------------
            // アニメーションタイプ毎に再生情報を振り分けていく
            // FIXME: 今回の実装でNativeMultiHashMapで確保しているメモリはサンプルのために適当。
            //        → ここらの仕様は最大描画数などを考慮した上で、どれくらい必要なのかすり合わせた方が良いかと思われる。
            var playDataMap = new NativeMultiHashMap <int, SendPlayData>(1000000, Allocator.TempJob);

            handle = new MapAnimationPlayDataJob
            {
                LocalToWorlds     = this._localToWorlds,
                AnimationPlayData = this._animationPlayData,
                SendPlayDataMap   = playDataMap.ToConcurrent(),
            }.Schedule(groupLength, 32, handle);


            // ----------------------------------------------
            // 再生情報の更新
            handle = new PlayAnimationJob
            {
                DeltaTime           = Time.deltaTime,
                AnimationLengthList = this._animationLengthList,
                MaxAnimationType    = this._maxAnimationType,
            }.Schedule(this, handle);
            handle.Complete();


            // ----------------------------------------------
            // GPU Instancing
            for (int i = 0; i < this._maxAnimationType; ++i)
            {
                // アニメーションタイプに応じた再生情報の取得
                var          buffer = new NativeArray <SendPlayData>(groupLength, Allocator.Temp);
                SendPlayData sendPlayData; NativeMultiHashMapIterator <int> it; int instanceCount = 0;
                // ※ iの値はAnimationTypeに該当
                if (!playDataMap.TryGetFirstValue(i, out sendPlayData, out it))
                {
                    continue;
                }
                do
                {
                    // 同一のアニメーションが再生されているインスタンスの再生情報をbufferに確保していく。
                    buffer[instanceCount] = sendPlayData;
                    ++instanceCount;
                } while (playDataMap.TryGetNextValue(out sendPlayData, ref it));


                // Materialに対し再生するアニメーションデータなど(ComputeBuffer)を設定していく。
                var renderer       = this._animationMeshes[i];
                var computeBuffers = this._sendBuffers[i];
                // 初回 or 同一のアニメーションが再生されているインスタンス数に変更があったらバッファを初期化
                if (computeBuffers.CurrentInstance <= 0 || computeBuffers.CurrentInstance != instanceCount)
                {
                    if (computeBuffers.SendPlayBuffer != null)
                    {
                        computeBuffers.SendPlayBuffer.Release();
                    }
                    computeBuffers.SendPlayBuffer = new ComputeBuffer(instanceCount, Marshal.SizeOf(typeof(SendPlayData)));
                    if (computeBuffers.GPUInstancingArgsBuffer != null)
                    {
                        computeBuffers.GPUInstancingArgsBuffer.Release();
                    }
                    computeBuffers.GPUInstancingArgsBuffer = new ComputeBuffer(1, this._GPUInstancingArgs.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
                    computeBuffers.CurrentInstance         = instanceCount;
                }

                // 再生情報の設定
                var bufferSlice = buffer.Slice(0, instanceCount);
                var copyArray   = new NativeArray <SendPlayData>(bufferSlice.Length, Allocator.Temp);
                bufferSlice.CopyTo(copyArray);
                // ※ComputeBufferにはNativeArrayを渡すことが可能。(内部的にもポインタ渡ししていた覚え)
                computeBuffers.SendPlayBuffer.SetData(copyArray);
                renderer.AnimationMaterial.SetBuffer(this._playDataBufferID, computeBuffers.SendPlayBuffer);

                // 「Graphics.DrawMeshInstancedIndirect -> bufferWithArgs」の設定
                this._GPUInstancingArgs[0] = (uint)renderer.Mesh.GetIndexCount(0);
                this._GPUInstancingArgs[1] = (uint)instanceCount;
                this._GPUInstancingArgs[2] = (uint)renderer.Mesh.GetIndexStart(0);
                this._GPUInstancingArgs[3] = (uint)renderer.Mesh.GetBaseVertex(0);
                computeBuffers.GPUInstancingArgsBuffer.SetData(this._GPUInstancingArgs);

                // 描画
                Graphics.DrawMeshInstancedIndirect(
                    renderer.Mesh,
                    0,
                    renderer.AnimationMaterial,
                    new Bounds(Vector3.zero, 1000000 * Vector3.one),
                    computeBuffers.GPUInstancingArgsBuffer);

                buffer.Dispose();
                copyArray.Dispose();
            }
            playDataMap.Dispose();
            return(handle);
        }
Ejemplo n.º 9
0
        public void Execute(Entity entity, int index, ref Translation translation, [ReadOnly] ref Rotation rotation, [ReadOnly] ref NonUniformScale nonUniformScale, [ReadOnly] ref MotionProperties motionProperties, ref Planetoid planetoidCrashInfo)
        {
            float3 position   = translation.Value;
            float3 scale      = nonUniformScale.Value;
            float  qRotationZ = rotation.Value.value.z;
            float  axisA      = nonUniformScale.Value.x / 2f;
            float  axisB      = nonUniformScale.Value.y / 2f;
            //TODO read the angle from quaternion
            //float angleZ = GameHandler.ToEulerAngles(q).z;
            //angleZ = angleZ % (2 * math.PI);
            // read z angle of entity rotation by multiplying right vector by quaternion:
            float3 rotationRightVectorN = math.normalize(qRotationZ * new float3(0, 0, 1));

            int hashMapKey = QuadrantSystem.GetPositionHashMapKey(position);

            if (quadrantMultiHashMap.TryGetFirstValue(hashMapKey, out EntityWithProps inspectedEntityWithProps, out NativeMultiHashMapIterator <int> it)) //TODO check the neighbouring quadrants
            {                                                                                                                                             //TODO find the closest entity and only monitor that one
                do
                {
                    float distance = math.distancesq(position, inspectedEntityWithProps.position);
                    //TODO for ellipses:
                    // calculate angle vector to the target
                    //float3 vectorToTarget = inspectedEntityWithProps.position - position;
                    //float distanceToTargetSq = vectorToTarget.x * vectorToTarget.x + vectorToTarget.y + vectorToTarget.y;
                    float3 vectorToTargetN = math.normalize(inspectedEntityWithProps.position - position);
                    // add angle to rotation angle of active ellipse collider
                    float radiaeAngle    = math.acos(math.dot(rotationRightVectorN, vectorToTargetN));
                    float sinRadiaeAngle = math.sin(radiaeAngle);
                    float cosRadiaeAngle = math.cos(radiaeAngle);
                    // calculate radius in line of target of active ellipse collider
                    float radiusToTarget = axisA * axisB / math.sqrt(axisA * axisA * sinRadiaeAngle * sinRadiaeAngle + axisB * axisB * cosRadiaeAngle * cosRadiaeAngle);
                    // do the same with passive ellipse collider
                    float qRotationZofInspectedEntity = inspectedEntityWithProps.rotation.value.z;

                    float3 rotationRightVectorNofInspectedEntity = math.normalize(qRotationZofInspectedEntity * new float3(0, 0, 1));

                    float axisAofInspectedEntity = inspectedEntityWithProps.nonUniformScale.x / 2f;

                    float axisBofInspectedEntity = inspectedEntityWithProps.nonUniformScale.y / 2f;

                    float radiaeAngleOfInspectedEntity = math.acos(math.dot(rotationRightVectorNofInspectedEntity, -vectorToTargetN));

                    float sinRadiaeAngleOfInspectedEntity = math.sin(radiaeAngleOfInspectedEntity);
                    float cosRadiaeAngleOfInspectedEntity = math.cos(radiaeAngleOfInspectedEntity);

                    float radiusFromTarget = axisAofInspectedEntity * axisBofInspectedEntity / math.sqrt(axisAofInspectedEntity * axisAofInspectedEntity * sinRadiaeAngleOfInspectedEntity * sinRadiaeAngleOfInspectedEntity
                                                                                                         + axisBofInspectedEntity * axisBofInspectedEntity * cosRadiaeAngleOfInspectedEntity * cosRadiaeAngleOfInspectedEntity);
                    // sum the radiae to get the distance
                    float radiaeSum   = radiusToTarget + radiusFromTarget;
                    float radiaeSumSq = radiaeSum * radiaeSum;
                    // set the longer axis of ellipse to be the zero degrees rotation vector
                    // or make it so that the x axis of ellipse is always longer

                    // calculate the rotation of the asteroid % 360
                    // calculate the rotation of the asteroid upon which the check is being made

                    // calculate the vector between two of the asteroids (maybe make it the normal vector)

                    // calculate the angle between asteroid rotation and the connecting vector
                    // and calculate for the radius at that point

                    // same for the other asteroid

                    // sum up the radii to obtain the collision distance

                    // check for the collision distance (below)



                    if (distance < radiaeSumSq && inspectedEntityWithProps.entity != entity && !(inspectedEntityWithProps.planetoidCrashData.crashTime > 0))// TODO and if entity that is being collided with has crashTime zero
                    {
                        planetoidCrashInfo.crashTime = realTimeSinceStartUp;
                        inspectedEntityWithProps.planetoidCrashData.crashTime = realTimeSinceStartUp;
                        destroyedPlanetoidsQueue.Enqueue(entity);
                        destroyedPlanetoidsQueue.Enqueue(inspectedEntityWithProps.entity);
                        //explosion location, TODO put exlosion locations into a persistent queue
                        float3 explosionPoint = position - (position - inspectedEntityWithProps.position) / 2;
                        explosionCoordsQueue.Enqueue(explosionPoint);
                        break;
                    }
                }while (quadrantMultiHashMap.TryGetNextValue(out inspectedEntityWithProps, ref it));
            }
        }
Ejemplo n.º 10
0
 public static bool SelectIterator <K, T>(this NativeMultiHashMap <K, T> HashMap, Predicate <T> Operate, K Key, out NativeMultiHashMapIterator <K> Iterator) where T : struct where K : struct, IEquatable <K>
 {
     for (bool Success = HashMap.TryGetFirstValue(Key, out var Value, out var It); Success;)
Ejemplo n.º 11
0
            public void Execute(int index)
            {
                BioClouds.CloudIDPosRadius CloudPos;
                if (!BioClouds2PosMap.TryGetValue(AgentCloudID[index].CloudID, out CloudPos))
                {
                    return;
                }
                float3 CloudPosition          = CloudPos.position;
                float3 BioCrowdsCloudPosition = WindowManager.Clouds2Crowds(CloudPosition);


                float3 Agent2CloudCenterVec = BioCrowdsCloudPosition - AgentPos[index].Value;

                float3 NormalizedAgent2CloudCenter = math.normalize(Agent2CloudCenterVec);


                float3 currentMarkerPosition;
                NativeMultiHashMapIterator <int> it;

                float3 moveStep  = float3.zero;
                float3 direction = float3.zero;
                float  totalW;

                AgentTotalW.TryGetValue(AgentData[index].ID, out totalW);

                bool keepgoing = AgentMarkersMap.TryGetFirstValue(AgentData[index].ID, out currentMarkerPosition, out it);

                if (!keepgoing)
                {
                    return;
                }

                float extraweight = math.dot(NormalizedAgent2CloudCenter, currentMarkerPosition - AgentPos[index].Value);

                float F = AgentCalculations.GetF(currentMarkerPosition, AgentPos[index].Value, AgentGoals[index].SubGoal - AgentPos[index].Value);

                F += extraweight * 0.1f;

                direction += AgentCalculations.PartialW(totalW, F) * AgentData[index].MaxSpeed * (currentMarkerPosition - AgentPos[index].Value);



                while (AgentMarkersMap.TryGetNextValue(out currentMarkerPosition, ref it))
                {
                    extraweight = math.dot(NormalizedAgent2CloudCenter, currentMarkerPosition - AgentPos[index].Value);

                    F = AgentCalculations.GetF(currentMarkerPosition, AgentPos[index].Value, AgentGoals[index].SubGoal - AgentPos[index].Value);

                    F += extraweight * 0.1f;

                    direction += AgentCalculations.PartialW(totalW, F) * AgentData[index].MaxSpeed * (currentMarkerPosition - AgentPos[index].Value);
                }


                float moduleM = math.length(direction);
                float s       = (float)(moduleM * math.PI);

                if (s > AgentData[index].MaxSpeed)
                {
                    s = AgentData[index].MaxSpeed;
                }

                if (moduleM > 0.00001f)
                {
                    moveStep = s * (math.normalize(direction));
                }
                else
                {
                    moveStep = float3.zero;
                }

                AgentStep[index] = new AgentStep()
                {
                    delta = moveStep
                };
            }
Ejemplo n.º 12
0
        internal void UpdateBlobAssetForUnityObject <TB>(int ownerId, NativeArray <Hash128> newBlobHashes) where TB : struct
        {
            var leftLength = newBlobHashes.Length;
            var toInc      = new NativeArray <Hash128>(leftLength, Allocator.Temp);
            var toDec      = new NativeArray <Hash128>(m_HashByOwner.CountValuesForKey(ownerId), Allocator.Temp);

            var curLeftIndex = 0;
            var curIncIndex  = 0;
            var curDecIndex  = 0;

            var leftRes  = curLeftIndex < leftLength;
            var rightRes = m_HashByOwner.TryGetFirstValue(ownerId, out var rightHash, out var it);

            var maxHash = new Hash128(UInt32.MaxValue, UInt32.MaxValue, UInt32.MaxValue, UInt32.MaxValue);

            // We will parse newBlobHashes, considered the left part and the store hashes for this ownerId, considered the right part
            //  in order to build a list of BlobAssets to increment (the ones only present in left part) and the ones to decrement
            //  (only present in the right part). If a hash is present on both side, we do not change its RefCounter
            do
            {
                var leftHash = leftRes ? newBlobHashes[curLeftIndex] : maxHash;
                rightHash = rightRes ? rightHash : maxHash;

                // Both side equal? We are synchronized, step next for both sides
                if (rightHash == leftHash)
                {
                    leftRes  = ++curLeftIndex < leftLength;
                    rightRes = m_HashByOwner.TryGetNextValue(out rightHash, ref it);
                    continue;
                }

                // More items on the left, add them to the "toAdd" list
                if (leftHash < rightHash)
                {
                    do
                    {
                        // Get left hash
                        leftHash = newBlobHashes[curLeftIndex++];

                        // Add to "toInc"
                        toInc[curIncIndex++] = leftHash;

                        // Check if there's more left item
                        leftRes = curLeftIndex < leftLength;
                    } while (leftRes && (leftHash < rightHash));
                }

                // More items on the right, add them to the "toRemove" list
                else
                {
                    do
                    {
                        // Add to "toDec"
                        toDec[curDecIndex++] = rightHash;

                        // Get next right item
                        rightRes = m_HashByOwner.TryGetNextValue(out rightHash, ref it);
                    } while (rightRes && leftHash > rightHash);
                }
            } while (leftRes || rightRes);

            // Increment each hash in "toInc" if they exist, add them to the RefCounter hash if they are new
            for (int i = 0; i < curIncIndex; i++)
            {
                var hash = toInc[i];
                if (m_RefCounterPerBlobHash.TryGetValue(hash, out var counter))
                {
                    m_RefCounterPerBlobHash[hash] = counter + 1;
                }
                else
                {
                    m_RefCounterPerBlobHash.Add(hash, 1);
                }
            }

            // Decrement each hash in "toDec", remove the BlobAsset if it reaches 0
            for (int i = 0; i < curDecIndex; i++)
            {
                // Decrement the hash of the previously assigned Blob Asset
                var hash         = toDec[i];
                var oldHashCount = --m_RefCounterPerBlobHash[hash];

                // If it reaches 0, we dispose the Blob Asset and remove the counter
                if (oldHashCount == 0)
                {
                    Remove <TB>(hash, true);
                    m_RefCounterPerBlobHash.Remove(hash);
                }
            }

            // Clear the former list of BlobAsset hashes and replace by the new one
            m_HashByOwner.Remove(ownerId);

            for (int i = 0; i < leftLength; i++)
            {
                m_HashByOwner.Add(ownerId, newBlobHashes[i]);
            }
        }
Ejemplo n.º 13
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                var localToWorlds = chunk.GetNativeArray(PickerLocalToWorld);
                var aggroRadii    = chunk.GetNativeArray(PickerAggroRadii);
                var teams         = chunk.GetNativeArray(PickerTeams);
                var pickerTargets = chunk.GetNativeArray(PickerTargets);
                var pickerTeams   = chunk.GetNativeArray(PickerTeams);

                // Targeting orders
                var hasPickerOrders     = chunk.Has(PickerOrders);
                var pickerOrders        = chunk.GetNativeArray(PickerOrders);
                var defaultPickerOrders = new TargetingOrders {
                    Discouraged = AgentCategory.eType.None, Preferred = AgentCategory.eType.None
                };

                for (int picker = 0; picker < chunk.Count; picker++)
                {
                    // Ignore entities which already have a target.
                    if (pickerTargets[picker].Value != Entity.Null)
                    {
                        continue;
                    }

                    // Initialise target loop variables.
                    float  score         = float.PositiveInfinity;
                    Entity currentTarget = Entity.Null;

                    // Search all bins that cover the given aggro radius.
                    float  radius         = aggroRadii[picker].Value;
                    var    pickerPosition = localToWorlds[picker].Position;
                    float2 vec            = new float2(pickerPosition.x, pickerPosition.z);
                    var    minBinCoords   = BinCoordinates(vec - radius, CellSize);
                    var    maxBinCoords   = BinCoordinates(vec + radius, CellSize);

                    var orders = hasPickerOrders ? pickerOrders[picker] : defaultPickerOrders;

                    for (int x = minBinCoords.x; x <= maxBinCoords.x; x++)
                    {
                        for (int y = minBinCoords.y; y <= maxBinCoords.y; y++)
                        {
                            // Identify bucket to search
                            var hash = Hash(new int2(x, y));

                            // Check targets within each bucket.
                            if (!TargetMap.TryGetFirstValue(hash, out int targetIndex, out NativeMultiHashMapIterator <int> iterator))
                            {
                                continue;
                            }
                            CheckTarget(
                                pickerTeams[picker],
                                TargetTeams[targetIndex],
                                TargetPositions[targetIndex].Position,
                                pickerPosition,
                                aggroRadii[picker].Value,
                                orders,
                                TargetTypes[targetIndex],
                                ref score,
                                ref currentTarget,
                                Targets[targetIndex]
                                );

                            while (TargetMap.TryGetNextValue(out targetIndex, ref iterator))
                            {
                                CheckTarget(
                                    pickerTeams[picker],
                                    TargetTeams[targetIndex],
                                    TargetPositions[targetIndex].Position,
                                    pickerPosition,
                                    aggroRadii[picker].Value,
                                    orders,
                                    TargetTypes[targetIndex],
                                    ref score,
                                    ref currentTarget,
                                    Targets[targetIndex]
                                    );
                            }
                        }
                    }

                    // If a target was found, write it.
                    if (currentTarget != Entity.Null)
                    {
                        pickerTargets[picker] = new Target {
                            Value = currentTarget
                        }
                    }
                    ;
                }
            }
Ejemplo n.º 14
0
    //---------------------- Collision Avoidance ---------------------------

    protected override void OnUpdate()
    {
        float innerProbabilityOfInfectionWithMaskWait = probabilityOfInfectionWithMaskWait;
        float innerProbabilityOfInfectionWait         = probabilityOfInfectionWait;
        float innerProbabilityOfInfectionWithMask     = probabilityOfInfectionWithMask;
        float innerProbabilityOfInfection             = probabilityOfInfection;
        float innerInfectionDistance     = infectionDistance;
        float innerInfectionDistanceWait = infectionDistanceWait;

        frameCounter++;

        totalCurrentNumberOfStudents      = 0;
        totalCurrentNumberOfStudentsCovid = 0;

        float deltaTime = Time.DeltaTime;

        var ecb = bi_ECB.CreateCommandBuffer();
        var ecbParallel = bi_ECB.CreateCommandBuffer().AsParallelWriter();
        var randomArray = World.GetExistingSystem <RandomSystem>().RandomArray;
        int i = 0, counter = 0;

        Entities.
        WithNone <WaitComponent>().
        WithoutBurst().
        WithStructuralChanges().
        ForEach((Entity e, ref UnitComponent uc, ref DynamicBuffer <UnitBuffer> ub, ref Translation trans, ref PersonComponent pc) =>
        {
            if (i <= UnitManager.Instance.MaxEntitiesRoutedPerFrame)
            {
                string key = uc.fromLocation.x + "_" + uc.fromLocation.z + "_" + uc.toLocation.x + "_" + uc.toLocation.z;

                //Cached path
                if (UnitManager.Instance.UseCache && allPaths.ContainsKey(key) && (!uc.routed || ub.Length == 0))
                {
                    allPaths.TryGetValue(key, out float3[] cachedPath);
                    for (int h = 0; h < cachedPath.Length; h++)
                    {
                        ub.Add(new UnitBuffer {
                            wayPoints = cachedPath[h]
                        });
                    }
                    uc.routed          = true;
                    uc.usingCachedPath = true;
                    EntityManager.AddComponent <UnitRoutedComponent>(e);
                    return;
                }
                //Job
                else if (!uc.routed || ub.Length == 0)
                {
                    keys[counter]             = key;
                    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[counter],
                        statusOutput     = statusOutputs[counter],
                        maxPathSize      = UnitManager.Instance.MaxPathSize,
                        ub = ub
                    };
                    routedEntities.Add(e);
                    queries.Add(currentQuery);
                    jobHandles.Add(spfj.Schedule());
                    counter++;
                }
                i++;
            }
            else
            {
                return;
            }
        }).Run();

        //Waiting for the completion of jobs
        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(keys[j]))
                {
                    float3[] wayPoints = new float3[statusOutputs[j][1]];
                    for (int k = 0; k < statusOutputs[j][1]; k++)
                    {
                        wayPoints[k] = results[j][k];
                    }
                    if (wayPoints.Length > 0)
                    {
                        allPaths.Add(keys[j], wayPoints);
                    }
                }

                UnitComponent uc = EntityManager.GetComponentData <UnitComponent>(routedEntities[j]);
                uc.routed = true;
                EntityManager.SetComponentData <UnitComponent>(routedEntities[j], uc);
                EntityManager.AddComponent <UnitRoutedComponent>(routedEntities[j]);
            }
            queries[j].Dispose();
            j++;
        }
        routedEntities.Clear();
        jobHandles.Clear();
        queries.Clear();

        //----------- Collision Avoidance Code -----------------

        EntityQuery eq = GetEntityQuery(typeof(UnitComponent));

        cellVsEntityPositions.Clear();
        if (eq.CalculateEntityCount() > cellVsEntityPositions.Capacity)
        {
            cellVsEntityPositions.Capacity = eq.CalculateEntityCount();
        }

        NativeMultiHashMap <int, CovidPos> .ParallelWriter cellVsEntityPositionsParallel = cellVsEntityPositions.AsParallelWriter();
        Entities
        .WithNone <WaitComponent>()
        .WithBurst(synchronousCompilation: true)
        .ForEach((ref UnitComponent uc, ref Translation trans, ref PersonComponent pc) =>
        {
            cellVsEntityPositionsParallel.Add(GetUniqueKeyForPosition(trans.Value, 5), new CovidPos {
                pos = trans.Value, hasCovid = pc.hasCovid
            });
        }).ScheduleParallel();



        NativeMultiHashMap <int, CovidPos> cellVsEntityPositionsForJob = cellVsEntityPositions;

        Entities
        .WithNone <WaitComponent>()
        .WithBurst(synchronousCompilation: true)
        .WithReadOnly(cellVsEntityPositionsForJob)
        .WithNativeDisableParallelForRestriction(randomArray)
        .ForEach((Entity e, int entityInQueryIndex, int nativeThreadIndex, ref UnitComponent uc, ref Translation trans, ref PersonComponent pc) =>
        {
            var random = randomArray[nativeThreadIndex];
            int key    = GetUniqueKeyForPosition(trans.Value, 5);
            NativeMultiHashMapIterator <int> nmhKeyIterator;
            CovidPos otherEntityData;
            float3 otherEntityPos;
            bool otherEntityHasCovid;
            float currentDistance = 0.3f;
            uc.avoidanceDirection = float3.zero;
            int total             = 0;
            int totalInCell       = 0;

            if (cellVsEntityPositionsForJob.TryGetFirstValue(key, out otherEntityData, out nmhKeyIterator))
            {
                otherEntityPos      = otherEntityData.pos;
                otherEntityHasCovid = otherEntityData.hasCovid;

                do
                {
                    if (!trans.Value.Equals(otherEntityPos))
                    {
                        totalInCell++;

                        if (currentDistance > math.sqrt(math.lengthsq(trans.Value - otherEntityPos)))
                        {
                            currentDistance       = math.sqrt(math.lengthsq(trans.Value - otherEntityPos));
                            float3 distanceFromTo = trans.Value - otherEntityPos;
                            uc.avoidanceDirection = math.normalize(distanceFromTo / currentDistance);
                            total++;
                        }
                    }
                } while (cellVsEntityPositionsForJob.TryGetNextValue(out otherEntityData, ref nmhKeyIterator) && totalInCell < 20);
                if (total > 0)
                {
                    uc.avoidanceDirection /= total;
                }
            }
            randomArray[nativeThreadIndex] = random;
        }).ScheduleParallel();

        //----------- Collision Avoidance Code -----------------

        cellVsEntityPositionsForJob = cellVsEntityPositions;

        if (frameCounter % 30 == 0)
        {
            Entities
            .WithoutBurst()
            .WithReadOnly(cellVsEntityPositionsForJob)
            .WithNativeDisableParallelForRestriction(randomArray)
            .WithNone <WaitComponent>()
            .ForEach((Entity e, int entityInQueryIndex, int nativeThreadIndex, ref UnitComponent uc, ref Translation trans, ref PersonComponent pc) =>
            {
                if (!pc.hasCovid)
                {
                    var random = randomArray[nativeThreadIndex];
                    int key    = GetUniqueKeyForPosition(trans.Value, 5);
                    NativeMultiHashMapIterator <int> nmhKeyIterator;
                    CovidPos otherEntityData;
                    float3 otherEntityPos;
                    bool otherEntityHasCovid;
                    float contagionPercentageValue = 0;
                    float covidPercentage          = 0;
                    //int totalInCell = 0;
                    if (cellVsEntityPositionsForJob.TryGetFirstValue(key, out otherEntityData, out nmhKeyIterator))
                    {
                        otherEntityPos      = otherEntityData.pos;
                        otherEntityHasCovid = otherEntityData.hasCovid;

                        do
                        {
                            if (!trans.Value.Equals(otherEntityPos))
                            {
                                if (otherEntityHasCovid && math.abs(otherEntityPos.x - trans.Value.x) < innerInfectionDistanceWait && math.abs(otherEntityPos.z - trans.Value.z) < innerInfectionDistanceWait)
                                {
                                    contagionPercentageValue = random.NextInt(0, 100);

                                    if (pc.wearMask)
                                    {
                                        covidPercentage = innerProbabilityOfInfectionWithMask;
                                    }
                                    else
                                    {
                                        covidPercentage = innerProbabilityOfInfection;
                                    }

                                    if (contagionPercentageValue <= covidPercentage)
                                    {
                                        pc.hasCovid = true;

                                        ecbParallel.SetSharedComponent(entityInQueryIndex, e, new RenderMesh
                                        {
                                            mesh     = UnitManager.Instance.unitMesh,
                                            material = UnitManager.Instance.covidMoveMaterial
                                        });

                                        break;
                                    }
                                }
                            }
                        } while (cellVsEntityPositionsForJob.TryGetNextValue(out otherEntityData, ref nmhKeyIterator));
                    }
                    randomArray[nativeThreadIndex] = random;
                }
            }).ScheduleParallel();

            Entities
            .WithoutBurst()
            .WithReadOnly(cellVsEntityPositionsForJob)
            .WithNativeDisableParallelForRestriction(randomArray)
            .WithAll <WaitComponent>().ForEach((Entity e, int entityInQueryIndex, int nativeThreadIndex, ref UnitComponent uc, ref Translation trans, ref PersonComponent pc) =>
            {
                if (!pc.hasCovid)
                {
                    var random = randomArray[nativeThreadIndex];
                    int key    = GetUniqueKeyForPosition(trans.Value, 5);
                    NativeMultiHashMapIterator <int> nmhKeyIterator;
                    CovidPos otherEntityData;
                    float3 otherEntityPos;
                    bool otherEntityHasCovid;
                    float contagionPercentageValue = 0;
                    float covidPercentage          = 0;
                    int totalInCell = 0;

                    if (cellVsEntityPositionsForJob.TryGetFirstValue(key, out otherEntityData, out nmhKeyIterator))
                    {
                        otherEntityPos      = otherEntityData.pos;
                        otherEntityHasCovid = otherEntityData.hasCovid;

                        do
                        {
                            if (!trans.Value.Equals(otherEntityPos))
                            {
                                totalInCell++;

                                if (otherEntityHasCovid && math.abs(otherEntityPos.x - trans.Value.x) < innerInfectionDistanceWait || math.abs(otherEntityPos.z - trans.Value.z) < innerInfectionDistanceWait)
                                {
                                    contagionPercentageValue = random.NextInt(0, 100);

                                    if (pc.wearMask)
                                    {
                                        covidPercentage = innerProbabilityOfInfectionWithMaskWait;
                                    }
                                    else
                                    {
                                        covidPercentage = innerProbabilityOfInfectionWait;
                                    }

                                    if (contagionPercentageValue <= covidPercentage)
                                    {
                                        pc.hasCovid = true;

                                        ecbParallel.SetSharedComponent(entityInQueryIndex, e, new RenderMesh
                                        {
                                            mesh     = UnitManager.Instance.unitMesh,
                                            material = UnitManager.Instance.covidWaitMaterial
                                        });

                                        break;
                                    }
                                }
                            }
                        } while (cellVsEntityPositionsForJob.TryGetNextValue(out otherEntityData, ref nmhKeyIterator) && totalInCell < 30);
                    }
                    randomArray[nativeThreadIndex] = random;
                }
            }).ScheduleParallel();
        }


        //Movement
        Entities
        .WithoutBurst()
        .WithNone <WaitComponent>()
        .WithAll <UnitRoutedComponent>().ForEach((Entity e, int entityInQueryIndex, ref UnitComponent uc, ref DynamicBuffer <UnitBuffer> ub, ref DynamicBuffer <ScheduleBuffer> sb, ref Translation trans, ref PersonComponent pc, in RenderMesh rm) =>
        {
            UnityEngine.AI.NavMeshHit outResult;
            Translation newTrans = trans;

            if (ub.Length > 0 && uc.routed)
            {
                uc.waypointDirection    = math.normalize(ub[uc.currentBufferIndex].wayPoints - trans.Value);
                uc.avoidanceDirection.y = 0;
                uc.waypointDirection.y  = 0;
                uc.waypointDirection    = uc.waypointDirection + uc.avoidanceDirection;

                newTrans.Value   = trans.Value + uc.waypointDirection * uc.speed * deltaTime;
                newTrans.Value.y = 1.791667f;

                if (!UnityEngine.AI.NavMesh.SamplePosition(newTrans.Value, out outResult, 0.8f, NavMesh.AllAreas))
                {
                    uc.waypointDirection -= uc.avoidanceDirection;
                }

                trans.Value         += uc.waypointDirection * uc.speed * deltaTime;
                float3 finalWayPoint = uc.toLocation;
                finalWayPoint.y      = ub[uc.currentBufferIndex].wayPoints.y;

                if (math.distance(trans.Value, ub[uc.currentBufferIndex].wayPoints) <= uc.minDistanceReached)
                {
                    if (uc.currentBufferIndex < ub.Length - 1 && !ub[uc.currentBufferIndex].wayPoints.Equals(finalWayPoint))
                    {
                        uc.currentBufferIndex = uc.currentBufferIndex + 1;
                    }

                    else if (uc.count < sb.Length - 1)
                    {
                        uc.count             += 1;
                        uc.fromLocation       = uc.toLocation;
                        uc.toLocation         = sb[uc.count].destination;
                        uc.routed             = false;
                        uc.usingCachedPath    = false;
                        uc.currentBufferIndex = 0;
                        ub.Clear();
                        ecb.RemoveComponent <UnitRoutedComponent>(e);
                        ecb.AddComponent(e, new WaitComponent
                        {
                            slotsToWait = sb[uc.count - 1].duration,
                            waitEndTime = 0
                        });

                        ecb.SetSharedComponent(e, new RenderMesh
                        {
                            mesh     = UnitManager.Instance.unitMesh,
                            material = pc.hasCovid ? UnitManager.Instance.covidWaitMaterial : UnitManager.Instance.healthyWaitMaterial
                        });
                    }
                    else if (uc.count == sb.Length - 1)
                    {
                        ecb.DestroyEntity(e);

                        totalNumberOfStudentsExit++;
                        if (pc.hasCovid)
                        {
                            totalNumberOfCovidExit++;
                        }
                    }
                }
            }
        }).Run();

        Entities.
        WithoutBurst().
        ForEach((PersonComponent pc) =>
        {
            totalCurrentNumberOfStudents++;

            if (pc.hasCovid)
            {
                totalCurrentNumberOfStudentsCovid++;
            }
        }).Run();

        UnitManager.Instance.TotNumberOfStudentsExit = totalNumberOfStudentsExit;
        UnitManager.Instance.TotNumberOfCovidExit    = totalNumberOfCovidExit;
        UnitManager.Instance.CurrentNumberOfStudents = totalCurrentNumberOfStudents;
        UnitManager.Instance.CurrentNumberOfCovid    = totalCurrentNumberOfStudentsCovid;
    }
Ejemplo n.º 15
0
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            if (AgentMarkers.Capacity < agentGroup.Agents.Length * qtdMarkers * 4)
            {
                AgentMarkers.Dispose();
                AgentMarkers = new NativeMultiHashMap <int, float3>(agentGroup.Agents.Length * qtdMarkers * 4, Allocator.Persistent);
            }
            else
            {
                AgentMarkers.Clear();
            }


            if (!CellTagSystem.AgentIDToPos.IsCreated)
            {
                return(inputDeps);
            }


            TakeMarkers takeMarkersJob = new TakeMarkers
            {
                AgentIDToPos = CellTagSystem.AgentIDToPos,
                AgentMarkers = AgentMarkers.ToConcurrent(),
                cellToAgent  = CellTagSystem.CellToMarkedAgents,
                MarkerCell   = markerGroup.MarkerCell,
                MarkerPos    = markerGroup.Position,
                Densities    = LocalDensities.ToConcurrent()
                               //Entities = markerGroup.Entities,
                               //CommandBuffer = m_SpawnerBarrier.CreateCommandBuffer().ToConcurrent()
            };

            //if (CellTagSystem.AgentIDToPos.IsCreated)
            // {
            JobHandle takeMakersHandle = takeMarkersJob.Schedule(markerGroup.Length, 64, inputDeps);

            takeMakersHandle.Complete();


            NativeMultiHashMap <int, float3> agtM = AgentMarkers;

            NativeMultiHashMapIterator <int> iter;
            float3 marker;

            for (int i = 0; i < agentGroup.Length; i++)
            {
                bool keepGoing = agtM.TryGetFirstValue(agentGroup.Agents[i].ID, out marker, out iter);
                if (keepGoing)
                {
                    //Debug.Log(i);

                    Debug.DrawLine(agentGroup.Positions[i].Value, marker);
                    while (agtM.TryGetNextValue(out marker, ref iter))
                    {
                        Debug.DrawLine(agentGroup.Positions[i].Value, marker);
                    }
                }
            }


            return(takeMakersHandle);
            // }

            // return inputDeps;
        }
Ejemplo n.º 16
0
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            NativeArray <Translation> translations = chunk.GetNativeArray(translationType);
            NativeArray <Velocity>    velocities   = chunk.GetNativeArray(velocityType);

            NativeArray <Line> orcaLines = new NativeArray <Line>(maxNeighbors, Allocator.Temp);
            NativeArray <KeyValuePair <float, AgentNeighbor> > agentNeighbors =
                new NativeArray <KeyValuePair <float, AgentNeighbor> >(maxNeighbors, Allocator.Temp);
            NativeArray <int> quadrantKeys = new NativeArray <int>(MAX_QUADRANT_NEIGHBORS, Allocator.Temp);

            float invTimeStep       = 1.0f / dt;
            float combinedRadius    = radius * 2.0f;
            float combinedRadiusSqr = math.pow(combinedRadius, 2);
            float rangeSqr          = neighborsDist * neighborsDist;

            for (int entityIdx = 0; entityIdx < chunk.ChunkEntityCount; entityIdx++)
            {
                float2 velocity = velocities[entityIdx].Value;

                //Early exit if the agent is not moving
                if (math.lengthsq(velocity) < 0.001f)
                {
                    continue;
                }

                float2 position = translations[entityIdx].Value.xz;

                int countNeighborQuadrant = 0;
                QuadrantSystem.GetCurrentCellAndNeighborsKeys(position, ref quadrantKeys, ref countNeighborQuadrant);

                //ORCA setup
                int neighborsCount = 0;

                int nbObstacleLine = 0;

                //Get nearest neighbors
                for (int i = 0; i < countNeighborQuadrant; i++)
                {
                    if (!quadrantMap.TryGetFirstValue(quadrantKeys[i], out var neighbor,
                                                      out var nativeMultiHashMapIterator))
                    {
                        continue;
                    }
                    do
                    {
                        float2 dir     = position - neighbor.position;
                        float  distSqr = math.dot(dir, dir);

                        //Condition to avoid self
                        if (distSqr > 0.001f)
                        {
                            //If the other agent is under the minimum range => add it
                            if (!(distSqr < rangeSqr))
                            {
                                continue;
                            }

                            //If there is a free space, add it immediately
                            if (neighborsCount < maxNeighbors)
                            {
                                agentNeighbors[neighborsCount] = new KeyValuePair <float, AgentNeighbor>(distSqr,
                                                                                                         new AgentNeighbor()
                                {
                                    position = neighbor.position,
                                    velocity = neighbor.velocity
                                });

                                neighborsCount++;
                            }

                            //Make sure the list is sorted
                            int j = neighborsCount - 1;
                            while (j != 0 && distSqr < agentNeighbors[j - 1].Key)
                            {
                                agentNeighbors[j] = agentNeighbors[j - 1];
                                j--;
                            }

                            //Once a spot with a further agent is found, place if
                            agentNeighbors[j] = new KeyValuePair <float, AgentNeighbor>(distSqr, new AgentNeighbor()
                            {
                                position = neighbor.position,
                                velocity = neighbor.velocity
                            });

                            //If the list is full, only check agent nearer than the farrest neighbor.
                            if (neighborsCount == maxNeighbors)
                            {
                                rangeSqr = agentNeighbors[maxNeighbors - 1].Key;
                            }
                        }
                    } while (quadrantMap.TryGetNextValue(out neighbor, ref nativeMultiHashMapIterator));
                }

                //Evaluate each neighbors
                for (int neighborIdx = 0; neighborIdx < neighborsCount; neighborIdx++)
                {
                    AgentNeighbor otherAgent = agentNeighbors[neighborIdx].Value;

                    float2 relativePosition = otherAgent.position - position;
                    float2 relativeVelocity = velocity - otherAgent.velocity;
                    float  distSqr          = math.lengthsq(relativePosition);

                    Line   line;
                    float2 u;

                    if (distSqr > combinedRadiusSqr)
                    {
                        // No Collision
                        float2 w = relativeVelocity - invTimeHorizon * relativePosition;

                        // Vector from center to relative velocity
                        float wLengthSqr  = math.lengthsq(w);
                        float dotProduct1 = math.dot(w, relativePosition);

                        if (dotProduct1 < 0.0f && math.pow(dotProduct1, 2) > combinedRadiusSqr * wLengthSqr)
                        {
                            // Project on circle
                            float  wLength = math.sqrt(wLengthSqr);
                            float2 unitW   = w / wLength;

                            line.direction = new float2(unitW.y, -unitW.x);
                            u = (combinedRadius * invTimeHorizon - wLength) * unitW;
                        }
                        else
                        {
                            // Projection on legs
                            float leg = math.sqrt(distSqr - combinedRadiusSqr);

                            if (Det(relativePosition, w) > 0.0f)
                            {
                                line.direction = new float2(
                                    relativePosition.x * leg - relativePosition.y * combinedRadius,
                                    relativePosition.x * combinedRadius + relativePosition.y * leg) /
                                                 distSqr;
                            }
                            else
                            {
                                line.direction = -new float2(
                                    relativePosition.x * leg - relativePosition.y * combinedRadius,
                                    -relativePosition.x * combinedRadius + relativePosition.y * leg) /
                                                 distSqr;
                            }

                            float dotProduct2 = math.dot(relativeVelocity, line.direction);
                            u = dotProduct2 * line.direction - relativeVelocity;
                        }
                    }
                    else
                    {
                        //Collision
                        float2 w = relativeVelocity - invTimeStep * relativePosition;

                        float  wLength = math.length(w);
                        float2 wUnit   = w / wLength;

                        line.direction = new float2(wUnit.y, -wUnit.x);
                        u = (combinedRadius * invTimeStep - wLength) * wUnit;
                    }

                    line.point = velocity + 0.5f * u;

                    orcaLines[neighborIdx] = line;
                }

                float2 optimalVel = velocity;
                float2 vel        = float2.zero;
                float  maxSpeed   = velocities[entityIdx].maxSpeed;
                int    lineFail   = LinearProgram2(orcaLines, neighborsCount, maxSpeed, optimalVel, false, ref vel);

                if (lineFail < neighborsCount)
                {
                    LinearProgram3(orcaLines, neighborsCount, nbObstacleLine, lineFail, maxSpeed, ref vel);
                }

                velocities[entityIdx] = new Velocity()
                {
                    Value    = vel,
                    maxSpeed = maxSpeed
                };
            }

            quadrantKeys.Dispose();
            orcaLines.Dispose();
            agentNeighbors.Dispose();
        }
Ejemplo n.º 17
0
            public void Execute(int index)
            {
                NativeMultiHashMapIterator <int3> iter;
                int agents = 0;
                //int3 currentCell;
                int   currentAgent    = -1;
                int   bestAgent       = -1;
                float agentRadius     = 1f;
                float closestDistance = agentRadius + 1;

                bool keepgoing = cellToAgent.TryGetFirstValue(MarkerCell[index].Value, out currentAgent, out iter);


                if (!keepgoing)
                {
                    return;
                }


                float3 agentPos;

                AgentIDToPos.TryGetValue(currentAgent, out agentPos);

                agents++;

                float dist = math.distance(MarkerPos[index].Value, agentPos);

                if (dist < agentRadius)
                {
                    closestDistance = dist;
                    bestAgent       = currentAgent;
                }

                while (cellToAgent.TryGetNextValue(out currentAgent, ref iter))
                {
                    agents++;
                    AgentIDToPos.TryGetValue(currentAgent, out agentPos);
                    dist = math.distance(MarkerPos[index].Value, agentPos);
                    if (dist < agentRadius && dist <= closestDistance)
                    {
                        if (dist != closestDistance)
                        {
                            closestDistance = dist;
                            bestAgent       = currentAgent;
                            //Debug.Log(MarkerCell[index].Value + " " + bestAgent);
                        }
                        else
                        {
                            if (bestAgent > currentAgent)
                            {
                                bestAgent = currentAgent;
                                //Debug.Log(MarkerCell[index].Value + " " + bestAgent);

                                closestDistance = dist;
                            }
                        }
                    }
                }

                if (bestAgent == -1)
                {
                    return;
                }
                //Debug.Log(bestAgent);
                AgentMarkers.Add(bestAgent, MarkerPos[index].Value);

                Densities.TryAdd(MarkerCell[index].Value, (float)agents / 36f);
            }
Ejemplo n.º 18
0
            // エッジデータごと
            public void Execute(int index)
            {
                var data = dataList[index];

                if (data.IsValid() == false)
                {
                    return;
                }

                int gindex = groupIndexList[index];
                var gdata  = groupDataList[gindex];

                if (gdata.teamId == 0 || gdata.active == 0)
                {
                    return;
                }

                var tdata = teamDataList[gdata.teamId];

                if (tdata.IsActive() == false)
                {
                    return;
                }
                // 更新確認
                if (tdata.IsUpdate() == false)
                {
                    return;
                }

                int pstart = tdata.particleChunk.startIndex;

                float3 corr0 = 0;
                float3 corr1 = 0;

                int pindex0 = data.vindex0 + pstart;
                int pindex1 = data.vindex1 + pstart;

                float3 nextpos0 = nextPosList[pindex0];
                float3 nextpos1 = nextPosList[pindex1];

                //float3 oldpos0 = oldPosList[pindex0];
                //float3 oldpos1 = oldPosList[pindex1];

                float radius = 0.01f;

                // 計算結果の移動値をcorrに格納
                // チームごとに判定[グローバル(0)]->[自身のチーム(team)]
                int colliderTeam = 0;

                for (int i = 0; i < 2; i++)
                {
                    // チーム内のコライダーをループ
                    int cindex;
                    NativeMultiHashMapIterator <int> iterator;
                    if (colliderMap.TryGetFirstValue(colliderTeam, out cindex, out iterator))
                    {
                        do
                        {
                            var cflag = flagList[cindex];
                            if (cflag.IsValid() == false)
                            {
                                continue;
                            }

                            bool hit = false;

                            if (cflag.IsFlag(PhysicsManagerParticleData.Flag_Plane))
                            {
                                // 平面コライダー判定
                                //hit = PlaneColliderDetection(ref nextpos, radius, cindex);
                            }
                            else if (cflag.IsFlag(PhysicsManagerParticleData.Flag_CapsuleX))
                            {
                                // カプセルコライダー判定
                                hit = CapsuleColliderDetection(nextpos0, nextpos1, ref corr0, ref corr1, radius, cindex, new float3(1, 0, 0));
                                //hit = CapsuleColliderDetection(nextpos0, nextpos1, oldpos0, oldpos1, ref corr0, ref corr1, radius, cindex, new float3(1, 0, 0));
                            }
                            else if (cflag.IsFlag(PhysicsManagerParticleData.Flag_CapsuleY))
                            {
                                // カプセルコライダー判定
                                hit = CapsuleColliderDetection(nextpos0, nextpos1, ref corr0, ref corr1, radius, cindex, new float3(0, 1, 0));
                                //hit = CapsuleColliderDetection(nextpos0, nextpos1, oldpos0, oldpos1, ref corr0, ref corr1, radius, cindex, new float3(0, 1, 0));
                            }
                            else if (cflag.IsFlag(PhysicsManagerParticleData.Flag_CapsuleZ))
                            {
                                // カプセルコライダー判定
                                hit = CapsuleColliderDetection(nextpos0, nextpos1, ref corr0, ref corr1, radius, cindex, new float3(0, 0, 1));
                                //hit = CapsuleColliderDetection(nextpos0, nextpos1, oldpos0, oldpos1, ref corr0, ref corr1, radius, cindex, new float3(0, 0, 1));
                            }
                            else if (cflag.IsFlag(PhysicsManagerParticleData.Flag_Box))
                            {
                                // ボックスコライダー判定
                                // ★まだ未実装
                            }
                            else
                            {
                                // 球コライダー判定
                                hit = SphereColliderDetection(nextpos0, nextpos1, ref corr0, ref corr1, radius, cindex);
                                //hit = SphereColliderDetection(nextpos0, nextpos1, oldpos0, oldpos1, ref corr0, ref corr1, radius, cindex);
                            }

                            if (hit)
                            {
                                // 衝突あり!
                                // 摩擦設定
                                //frictionList[index] = math.max(frictionList[index], teamData.friction);
                            }
                        }while (colliderMap.TryGetNextValue(out cindex, ref iterator));
                    }

                    // 自身のチームに切り替え
                    colliderTeam = gdata.teamId;
                }


                // 作業バッファへ格納
                int wstart  = gdata.writeDataChunk.startIndex;
                int windex0 = data.writeIndex0 + wstart;
                int windex1 = data.writeIndex1 + wstart;

                writeBuffer[windex0] = corr0;
                writeBuffer[windex1] = corr1;
            }
Ejemplo n.º 19
0
        // todo: maybe intelligent ones should avoid not only the blockers but also each other?
        public void Execute([ReadOnly] ref Translation translation, [ReadOnly] ref TargetComponent target, ref MovementComponent movement)
        {
            int    hashKey               = QuadrantSystem.GetPositionHashMapKey(translation.Value);
            float3 dir                   = new float3(0, 0, -1);
            float  closestDis            = 1000f;
            float3 closestPos            = float3(10000f, 1000f, 1000f);
            bool   bFoundPotentialThreat = false;

            if (BlockerMap.TryGetFirstValue(hashKey, out var data, out var it))
            {
                float zombieX = translation.Value.x;
                do
                {
                    // todo: maybe you should first find the closest target first and then determine if it's worth avoiding
                    // are you close enough to care?
                    float furthestRight = data.position.x + data.width / 2 + 2f;
                    float furthestLeft  = data.position.x - data.width / 2 - 2f;

                    if (zombieX < furthestLeft || zombieX > furthestRight)
                    {
                        continue;
                    }

                    float disSq = distancesq(translation.Value, data.position);
                    if (disSq > closestDis)
                    {
                        continue;
                    }

                    closestDis            = disSq;
                    closestPos            = data.position;
                    bFoundPotentialThreat = true;
                } while (BlockerMap.TryGetNextValue(out data, ref it));
            }
            if (!bFoundPotentialThreat)
            {
                movement.defaultDirection = dir;
                // todo: cause an irrational movement
                return;
            }
            if (closestDis > 150f)
            {
                movement.defaultDirection = dir;
                return;
            }

            // yes avoid
            float3 vFromAiToBlocker = normalize(closestPos - translation.Value);
            float  dotProd          = dot(dir, vFromAiToBlocker);

            // is it behind?
            if (dotProd < 0f)
            {
                movement.defaultDirection = dir;
                return;
            }

            // detect if to the left or to the right
            float3 right = new float3(1, 0, 0);
            float  side  = dot(right, vFromAiToBlocker);

            if (side > 0f)
            {
                // to the right, go left
                movement.defaultDirection.x -= ((movement.direction.x - 0.1) < -1) ? 0 : 0.1f;
                movement.defaultDirection.z += ((movement.direction.z + 0.1) > 0) ? 0 : 0.1f;
                return;
            }
            // to the left, go right
            movement.defaultDirection.x += ((movement.direction.x + 0.1) > 1) ? 0 : 0.1f;
            movement.defaultDirection.z += ((movement.direction.z + 0.1) > 0) ? 0 : 0.1f;
        }
Ejemplo n.º 20
0
            // スプリング対象頂点ごと
            public void Execute(int index)
            {
                int vindex = springVertexList[index];

                if (vindex < 0)
                {
                    return;
                }

                SpringData data;

                // 頂点のトータルウエイトを求める
                float totalWeight = 0;

                if (springMap.TryGetFirstValue(vindex, out data, out iterator))
                {
                    do
                    {
                        var flag = flagList[data.particleIndex];
                        if (flag.IsValid())
                        {
                            totalWeight += data.weight;
                        }
                    }while (springMap.TryGetNextValue(out data, ref iterator));
                }

                if (totalWeight > 0 && springMap.TryGetFirstValue(vindex, out data, out iterator))
                {
                    var    vpos = virtualPosList[vindex];
                    float3 pos  = 0;

                    do
                    {
                        int pindex = data.particleIndex;
                        var flag   = flagList[data.particleIndex];
                        if (flag.IsValid() == false)
                        {
                            continue;
                        }

                        // パーティクル現在姿勢
                        var ppos = particlePosList[pindex];
                        var prot = particleRotList[pindex];

                        // パーティクル原点姿勢
                        var pbpos   = particleBasePosList[pindex];
                        var pbrot   = particleBaseRotList[pindex];
                        var ivpbrot = math.inverse(pbrot);

                        // (1)パーティクルBaseからの相対位置
                        var lpos = math.mul(ivpbrot, (vpos - pbpos));

                        // (2)パーティクル現在地からの頂点位置
                        var npos = math.mul(prot, lpos) + ppos;

                        // (3)ウエイト
                        npos = math.lerp(vpos, npos, data.weight);

                        // (4)ウエイト乗算
                        pos += npos * (data.weight / totalWeight);
                    }while (springMap.TryGetNextValue(out data, ref iterator));

                    // 結果格納
                    virtualPosList[vindex] = pos;
                }
            }
        Velocity Calculate(int i)
        {
            float3 currentPosition = positions[i];
            float3 currentVelocity = velocities[i];

            float2 velocity = currentVelocity.xz;

            int j    = 0;
            int hash = Hash(currentPosition);
            NativeMultiHashMapIterator <int> iterator;
            bool found = buckets.TryGetFirstValue(hash, out j, out iterator);

            int iterations  = 0;
            int closestDone = 0;

            while (found)
            {
                if (j == i)
                {
                    // Exclude self
                    found = buckets.TryGetNextValue(out j, ref iterator);
                    continue;
                }

                float epsilon = 0.00001f;

                // Construct the force direction
                float2 relative = currentPosition.xz - positions[j].xz;

                if (math.dot(relative, relative) < epsilon || !math.any(relative))
                {
                    relative = new float2(1, 0);
                }

                float distanceSqr = math.dot(relative, relative);

                // Update velocity data
                float str = math.max(0, radiusSqr - distanceSqr) / radiusSqr;
                velocity += math.normalize(relative) * str * maxForce * dt;

                // Next iteration
                found = buckets.TryGetNextValue(out j, ref iterator);

                // We will check 3 cells in the corner
                if (!found && closestDone < maxClosestDone)
                {
                    float2 position        = currentPosition.xz / step;
                    int2   flooredPosition = new int2(math.floor(position));

                    int2 nextQuantizedPosition = new int2(math.round(2f * position - (flooredPosition + new float2(0.5f))));
                    if (nextQuantizedPosition.x == flooredPosition.x)
                    {
                        nextQuantizedPosition.x -= 1;
                    }
                    if (nextQuantizedPosition.y == flooredPosition.y)
                    {
                        nextQuantizedPosition.y -= 1;
                    }

                    if (closestDone == 1)
                    {
                        nextQuantizedPosition.x = flooredPosition.x;
                    }
                    else if (closestDone == 2)
                    {
                        nextQuantizedPosition.y = flooredPosition.y;
                    }

                    int nextHash = nextQuantizedPosition.x + fieldWidthHalf + (nextQuantizedPosition.y + fieldHeightHalf) * fieldWidth;

                    found = buckets.TryGetFirstValue(nextHash, out j, out iterator);

                    closestDone++;
                }

                if (++iterations > maxIterations)
                {
                    break;
                }
            }

            float2 dampingStr = velocity * damping * dt;

            velocity -= dampingStr;

            float3 collisionVelocity = new float3(velocity.x, 0, velocity.y) - currentVelocity;

            currentVelocity += collisionVelocity;

            if (math.dot(currentVelocity, currentVelocity) > maxVelocitySqr)
            {
                currentVelocity = math.normalize(currentVelocity) * maxVelocity;
            }

            Velocity velocityComponent = new Velocity
            {
                Value             = currentVelocity,
                CollisionVelocity = collisionVelocity
            };

            return(velocityComponent);
        }
        static void ApplyBlobAssetChanges(
            EntityManager entityManager,
            NativeArray <EntityGuid> packedEntityGuids,
            NativeMultiHashMap <int, Entity> packedEntities,
            NativeArray <ComponentType> packedTypes,
            NativeArray <BlobAssetChange> createdBlobAssets,
            NativeArray <byte> createdBlobAssetData,
            NativeArray <ulong> destroyedBlobAssets,
            NativeArray <BlobAssetReferenceChange> blobAssetReferenceChanges)
        {
            if (createdBlobAssets.Length == 0 && blobAssetReferenceChanges.Length == 0)
            {
                return;
            }

            s_ApplyBlobAssetChangesProfilerMarker.Begin();

            var managedObjectBlobAssetReferencePatches = new NativeMultiHashMap <EntityComponentPair, ManagedObjectBlobAssetReferencePatch>(blobAssetReferenceChanges.Length, Allocator.Temp);

            var patcherBlobAssetSystem = entityManager.World.GetOrCreateSystem <EntityPatcherBlobAssetSystem>();

            var blobAssetDataPtr = (byte *)createdBlobAssetData.GetUnsafePtr();

            for (var i = 0; i < createdBlobAssets.Length; i++)
            {
                if (!patcherBlobAssetSystem.TryGetBlobAsset(createdBlobAssets[i].Hash, out _))
                {
                    patcherBlobAssetSystem.AllocateBlobAsset(blobAssetDataPtr, createdBlobAssets[i].Length, createdBlobAssets[i].Hash);
                }

                blobAssetDataPtr += createdBlobAssets[i].Length;
            }

            for (var i = 0; i < destroyedBlobAssets.Length; i++)
            {
                patcherBlobAssetSystem.ReleaseBlobAsset(entityManager, destroyedBlobAssets[i]);
            }

            for (var i = 0; i < blobAssetReferenceChanges.Length; i++)
            {
                var packedComponent = blobAssetReferenceChanges[i].Component;
                var component       = packedTypes[packedComponent.PackedTypeIndex];
                var targetOffset    = blobAssetReferenceChanges[i].Offset;

                BlobAssetReferenceData targetBlobAssetReferenceData;
                if (patcherBlobAssetSystem.TryGetBlobAsset(blobAssetReferenceChanges[i].Value, out var blobAssetPtr))
                {
                    targetBlobAssetReferenceData = new BlobAssetReferenceData {
                        m_Ptr = (byte *)blobAssetPtr.Data
                    };
                }

                if (packedEntities.TryGetFirstValue(packedComponent.PackedEntityIndex, out var entity, out var iterator))
                {
                    do
                    {
                        if (!entityManager.Exists(entity))
                        {
                            Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but entity to patch does not exist.");
                        }
                        else if (!entityManager.HasComponent(entity, component))
                        {
                            Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but component in entity to patch does not exist.");
                        }
                        else
                        {
                            if (component.IsBuffer)
                            {
                                var pointer = (byte *)entityManager.GetBufferRawRW(entity, component.TypeIndex);
                                UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData));
                            }
                            else if (component.IsManagedComponent || component.IsSharedComponent)
                            {
                                managedObjectBlobAssetReferencePatches.Add(
                                    new EntityComponentPair {
                                    Entity = entity, Component = component
                                },
                                    new ManagedObjectBlobAssetReferencePatch {
                                    Id = targetOffset, Target = blobAssetReferenceChanges[i].Value
                                });
                            }
                            else
                            {
                                var pointer = (byte *)entityManager.GetComponentDataRawRW(entity, component.TypeIndex);
                                UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData));
                            }
                        }
                    }while (packedEntities.TryGetNextValue(out entity, ref iterator));
                }
            }
            s_ApplyBlobAssetChangesProfilerMarker.End();

#if !UNITY_DOTSRUNTIME
            var managedObjectPatcher = new ManagedObjectBlobAssetReferencePatcher(patcherBlobAssetSystem);

            // Apply all managed entity patches
            using (var keys = managedObjectBlobAssetReferencePatches.GetKeyArray(Allocator.Temp))
            {
                keys.Sort();
                var uniqueCount = keys.Unique();

                for (var i = 0; i < uniqueCount; i++)
                {
                    var pair    = keys[i];
                    var patches = managedObjectBlobAssetReferencePatches.GetValuesForKey(pair);

                    if (pair.Component.IsManagedComponent)
                    {
                        var obj = entityManager.GetComponentObject <object>(pair.Entity, pair.Component);
                        managedObjectPatcher.ApplyPatches(ref obj, patches);
                    }
                    else if (pair.Component.IsSharedComponent)
                    {
                        var obj = entityManager.GetSharedComponentData(pair.Entity, pair.Component.TypeIndex);
                        managedObjectPatcher.ApplyPatches(ref obj, patches);
                        entityManager.SetSharedComponentDataBoxedDefaultMustBeNull(pair.Entity, pair.Component.TypeIndex, obj);
                    }

                    patches.Dispose();
                }
            }
#endif

            managedObjectBlobAssetReferencePatches.Dispose();

            // Workaround to catch some special cases where the memory is never released. (e.g. reloading a scene, toggling live-link on/off).
            patcherBlobAssetSystem.ReleaseUnusedBlobAssets();
        }
Ejemplo n.º 23
0
            public void Execute(int index)
            {
                Entity currentEntity = entityArray[index];
                EntityBoundMinMaxData boundMinMaxData = entityBoundMinMaxData[index];
                int3 minQuanta   = Quantize(boundMinMaxData.min, cellSizes);
                int3 maxQuanta   = Quantize(boundMinMaxData.max, cellSizes);
                int3 deltaQuanta = maxQuanta - minQuanta;

                bool   collided            = false;
                Entity collidedEntityFound = new Entity();
                int    hash;

                for (int i = 0; i <= deltaQuanta.x && !collided; i++)
                {
                    for (int j = 0; j <= deltaQuanta.y && !collided; j++)
                    {
                        for (int k = 0; k <= deltaQuanta.z && !collided; k++)
                        {
                            hash = Hash(minQuanta + new int3(i, j, k));

                            HashMapData hashMapDataFound;
                            NativeMultiHashMapIterator <int> iterator;

                            bool found = boundCells.TryGetFirstValue(hash, out hashMapDataFound, out iterator);
                            while (found && !collided)
                            {
                                //This test is not needed given that we have separate hash map for each entity type

                                /* if(currentEntity == collidedEntity)
                                 * {
                                 *   found = boundCells.TryGetNextValue(out collidedEntity, ref iterator);
                                 *   continue;
                                 * }*/

                                EntityBoundMinMaxData boundMinMaxDataOther = hashMapDataFound.minMaxData;

                                //axis aligned test

                                float3 minSelf  = boundMinMaxData.min;
                                float3 minOther = boundMinMaxDataOther.min;
                                float3 maxSelf  = boundMinMaxData.max;
                                float3 maxOther = boundMinMaxDataOther.max;

                                if (math.all(maxSelf > minOther) &&
                                    math.all(maxOther > minSelf))
                                {
                                    collided            = true;
                                    collidedEntityFound = hashMapDataFound.entityStored;
                                }
                                else
                                {
                                    found = boundCells.TryGetNextValue(out hashMapDataFound, ref iterator);
                                }
                            }
                        }
                    }
                }

                if (collided)
                {
                    collidedEntityQueue.Enqueue(currentEntity);
                    collidedEntityQueue.Enqueue(collidedEntityFound);
                }
            }
Ejemplo n.º 24
0
            public void Execute(int index)
            {
                float3 currentCellPosition;
                NativeMultiHashMapIterator <int> it;

                float3 moveStep  = float3.zero;
                float3 direction = float3.zero;

                CloudTotalW.TryGetValue(CloudData[index].ID, out float totalW);

                bool keepgoing = CloudMarkersMap.TryGetFirstValue(CloudData[index].ID, out currentCellPosition, out it);

                if (!keepgoing)
                {
                    return;
                }

                float F           = CloudCalculations.GetF(currentCellPosition, CloudPositions[index].Value, CloudGoals[index].SubGoal - CloudPositions[index].Value);
                var   auxinWeight = CloudCalculations.PartialW(totalW, F) * CloudData[index].MaxSpeed * (currentCellPosition - CloudPositions[index].Value);

                direction += auxinWeight;

                if (useSplit)
                {
                    if (ExtraWeightCell.TryGetValue(CloudData[index].ID, out int extraweightcell))
                    {
                        if (GridConverter.Position2CellID(currentCellPosition) == extraweightcell)
                        {
                            //TODO dynamic extra weight
                            direction += 5 * auxinWeight;
                        }
                    }
                }



                while (CloudMarkersMap.TryGetNextValue(out currentCellPosition, ref it))
                {
                    F          = CloudCalculations.GetF(currentCellPosition, CloudPositions[index].Value, CloudGoals[index].SubGoal - CloudPositions[index].Value);
                    direction += CloudCalculations.PartialW(totalW, F) * CloudData[index].MaxSpeed * (currentCellPosition - CloudPositions[index].Value);


                    if (useSplit)
                    {
                        if (ExtraWeightCell.TryGetValue(CloudData[index].ID, out int extraweightcell))
                        {
                            if (GridConverter.Position2CellID(currentCellPosition) == extraweightcell)
                            {
                                direction += auxinWeight;
                            }
                        }
                    }
                }


                float moduleM = math.length(direction);
                float s       = (float)(moduleM * math.PI);

                float3 normalized_direction  = math.normalize(direction);
                float3 normalized_goalvector = math.normalize(CloudGoals[index].SubGoal - CloudPositions[index].Value);

                if (s > CloudData[index].MaxSpeed)
                {
                    s = CloudData[index].MaxSpeed;
                }

                if (moduleM > 0.00001f)
                {
                    moveStep = s * (normalized_direction);
                }
                else
                {
                    moveStep = float3.zero;
                }

                CloudStep[index] = new CloudMoveStep()
                {
                    Delta = moveStep
                };
            }
    protected override void OnUpdate()
    {
        processing.records.Clear();
        processing.frame = frames++;

        for (int i = 0; i < agentGroup.Length; i++)
        {
            processing.records.Add(new AgentRecord
            {
                AgentID  = agentGroup.Data[i].ID,
                Position = WindowManager.Crowds2Clouds(agentGroup.Position[i].Value),
                CloudID  = agentGroup.OwnerCloud[i].CloudID
            });
        }

        FrameRecord aux = complete;

        complete   = processing;
        processing = aux;


        var inst = BioClouds.Parameters.Instance;

        if (!inst.SaveSimulationData)
        {
            return;
        }

        //Data recording
        #region BioClouds Datarecording
        NativeMultiHashMap <int, float3> cellmap = m_CellMarkSystem.cloudID2MarkedCellsMap;
        float3 currentCellPosition;
        NativeMultiHashMapIterator <int> it;

        //if ((inst.SaveDenstiies || inst.SavePositions))
        //{
        if (inst.MaxSimulationFrames > CurrentFrame && CurrentFrame % inst.FramesForDataSave == 0)
        {
            for (int i = 0; i < m_CloudDataGroup.Length; i++)
            {
                List <int> cellIDs = new List <int>();

                if (!cellmap.TryGetFirstValue(m_CloudDataGroup.CloudData[i].ID, out currentCellPosition, out it))
                {
                    continue;
                }
                int2 grid_cell = GridConverter.PositionToGridCell(new float3(currentCellPosition.x, currentCellPosition.y, currentCellPosition.z));
                cellIDs.Add(GridConverter.GridCell2CellID(grid_cell));

                while (cellmap.TryGetNextValue(out currentCellPosition, ref it))
                {
                    grid_cell = GridConverter.PositionToGridCell(new float3(currentCellPosition.x, currentCellPosition.y, currentCellPosition.z));
                    cellIDs.Add(GridConverter.GridCell2CellID(grid_cell));
                }

                if (inst.IDToRecord == -1 || m_CloudDataGroup.CloudData[i].ID == inst.IDToRecord)
                {
                    BioClouds.Record record = new BioClouds.Record(frames,
                                                                   m_CloudDataGroup.CloudData[i].ID,
                                                                   m_CloudDataGroup.CloudData[i].AgentQuantity,
                                                                   cellIDs.Count,
                                                                   cellIDs,
                                                                   m_CloudDataGroup.Position[i].Value,
                                                                   m_CloudDataGroup.CloudData[i].Radius
                                                                   );

                    bioCloudsRecords.Add(record);
                }
            }
        }

        //if (inst.MaxSimulationFrames == CurrentFrame - 1)
        //{
        using (System.IO.StreamWriter file =
                   new System.IO.StreamWriter(inst.LogFilePath + "Clouds.txt", true))
        {
            foreach (BioClouds.Record record in bioCloudsRecords)
            {
                file.Write(record.ToString() + '\n');
            }
        }
        bioCloudsRecords.Clear();
        //}
        //}
        #endregion


        #region BioCrowds DataRecording

        //if (inst.MaxSimulationFrames == CurrentFrame - 1)
        //{
        using (System.IO.StreamWriter file =
                   new System.IO.StreamWriter(inst.LogFilePath + "Agents.txt", true))
        {
            file.Write(complete.ToString() + '\n');
        }
        //}

        #endregion
    }
        public void Execute()
        {
            var statesToUpdateLength = SelectedStates.Count();
            var statesToUpdate       = new NativeMultiHashMap <int, TStateKey>(statesToUpdateLength, Allocator.Temp);
            var currentHorizon       = new NativeList <TStateKey>(statesToUpdateLength, Allocator.Temp);
            var nextHorizon          = new NativeList <TStateKey>(statesToUpdateLength, Allocator.Temp);

            var maxDepth          = int.MinValue;
            var selectedStateKeys = SelectedStates.GetKeyArray(Allocator.Temp);

            for (int i = 0; i < selectedStateKeys.Length; i++)
            {
                var stateKey   = selectedStateKeys[i];
                int stateDepth = int.MinValue;
                SelectedStates.TryGetFirstValue(stateKey, out var selectedDepth, out var iterator);
                do
                {
                    stateDepth = math.max(stateDepth, selectedDepth);
                }while (SelectedStates.TryGetNextValue(out selectedDepth, ref iterator));

                // Update depth map
                DepthMap[stateKey] = stateDepth;

                // Queue state and track max depth of backpropagation
                statesToUpdate.AddValueIfUnique(stateDepth, stateKey);
                maxDepth = math.max(maxDepth, stateDepth);
            }
            selectedStateKeys.Dispose();

            var actionLookup              = planGraph.ActionLookup;
            var resultingStateLookup      = planGraph.ResultingStateLookup;
            var actionInfoLookup          = planGraph.ActionInfoLookup;
            var stateInfoLookup           = planGraph.StateInfoLookup;
            var stateTransitionInfoLookup = planGraph.StateTransitionInfoLookup;
            var predecessorLookup         = planGraph.PredecessorGraph;
            var depth = maxDepth;

            // Pull states from statesToUpdate
            if (statesToUpdate.TryGetFirstValue(depth, out var stateToAdd, out var stateIterator))
            {
                do
                {
                    currentHorizon.AddIfUnique(stateToAdd);
                }while (statesToUpdate.TryGetNextValue(out stateToAdd, ref stateIterator));
            }

            // Update values from leaf state(s) to root
            while (depth >= 0)
            {
                for (int i = 0; i < currentHorizon.Length; i++)
                {
                    var stateKey    = currentHorizon[i];
                    var updateState = true;
                    if (actionLookup.TryGetFirstValue(stateKey, out var actionKey, out var stateActionIterator))
                    {
                        // Expanded state. Only update if one or more actions have updated.
                        updateState = false;

                        // Update all actions
                        do
                        {
                            updateState |= UpdateCumulativeReward(new StateActionPair <TStateKey, TActionKey>(stateKey, actionKey), resultingStateLookup, stateInfoLookup, actionInfoLookup, stateTransitionInfoLookup);
                        }while (actionLookup.TryGetNextValue(out actionKey, ref stateActionIterator));
                    }

                    if (!updateState)
                    {
                        continue;
                    }

                    // Update state
                    if (UpdateStateValue(stateKey, actionLookup, stateInfoLookup, actionInfoLookup))
                    {
                        // If a change has occured, update predecessors
                        if (predecessorLookup.TryGetFirstValue(stateKey, out var predecessorStateKey, out var predecessorIterator))
                        {
                            do
                            {
                                nextHorizon.AddIfUnique(predecessorStateKey);
                            }while (predecessorLookup.TryGetNextValue(out predecessorStateKey, ref predecessorIterator));
                        }
                    }
                }

                var temp = currentHorizon;
                currentHorizon = nextHorizon;
                nextHorizon    = temp;
                nextHorizon.Clear();

                depth--;

                // pull out states from statesToUpdate
                if (statesToUpdate.TryGetFirstValue(depth, out stateToAdd, out stateIterator))
                {
                    do
                    {
                        currentHorizon.AddIfUnique(stateToAdd);
                    }while (statesToUpdate.TryGetNextValue(out stateToAdd, ref stateIterator));
                }
            }

            // new: continue propagating complete flag changes
            while (currentHorizon.Length > 0)
            {
                for (int i = 0; i < currentHorizon.Length; i++)
                {
                    var stateKey    = currentHorizon[i];
                    var updateState = false;

                    // Update all actions
                    actionLookup.TryGetFirstValue(stateKey, out var actionKey, out var stateActionIterator);
                    do
                    {
                        var stateActionPair = new StateActionPair <TStateKey, TActionKey>(stateKey, actionKey);
                        if (UpdateSubplanCompleteStatus(stateActionPair, out var updatedActionInfo))
                        {
                            updateState = true;

                            // Write back updated info
                            actionInfoLookup[stateActionPair] = updatedActionInfo;
                        }
                    }while (actionLookup.TryGetNextValue(out actionKey, ref stateActionIterator));

                    // Update state
                    if (updateState && UpdateSubplanCompleteStatus(stateKey, out var updatedStateInfo))
                    {
                        // Write back updated info
                        stateInfoLookup[stateKey] = updatedStateInfo;

                        // If a change has occured, update predecessors
                        if (predecessorLookup.TryGetFirstValue(stateKey, out var predecessorStateKey, out var predecessorIterator))
                        {
                            do
                            {
                                nextHorizon.AddIfUnique(predecessorStateKey);
                            }while (predecessorLookup.TryGetNextValue(out predecessorStateKey, ref predecessorIterator));
                        }
                    }
                }

                var temp = currentHorizon;
                currentHorizon = nextHorizon;
                nextHorizon    = temp;
                nextHorizon.Clear();
            }

            currentHorizon.Dispose();
            nextHorizon.Dispose();
            statesToUpdate.Dispose();
        }