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 }
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); }
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; }
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(); }
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; } }
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); }
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)); } }
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;)
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 }; }
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]); } }
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 } } ; } }
//---------------------- 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; }
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; }
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(); }
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); }
// エッジデータごと 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; }
// 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; }
// スプリング対象頂点ごと 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(); }
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); } }
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(); }