public void UpdateData(string action, string key, string psr) { bool isItemInDictionary = itemDictionary.ContainsKey(key); if (action == "child_added" || action == "child_changed") { if (isItemInDictionary) { // Set existing data entry ItemData existingItem; bool exists = itemDictionary.TryGetValue(key, out existingItem); // re-add the item again into the tree, as it is not possible to move it directly to another position itemTree.Remove(existingItem); existingItem.CalculatePSR(psr); itemTree.Add(existingItem, existingItem.Position); // set existing item game object, because we want nearby data update to be immediate if (existingItem.DistanceTo(Camera.main.transform) <= visibleDistance) { SetChild(existingItem); } } else { // Add data entry var item = new ItemData(key, psr); itemTree.Add(item, item.Position); itemDictionary.Add(item.Key, item); // create object if it is nearby if (item.DistanceTo(Camera.main.transform) <= visibleDistance) { CreateChild(item); } } } else if (action == "child_removed") { if (isItemInDictionary) { var existingItem = itemDictionary[key]; itemTree.Remove(existingItem); itemDictionary.Remove(key); RemoveChild(existingItem); } } // Start Proximity Check If not yet if (coroutine == null) { coroutine = CoroutineSpawnDespawnChildren(manageGameObjectInterval); StartCoroutine(coroutine); } }
public static void Update(ServerWorldEntity entity) { lock (octree) { octree.Remove(entity); Register(entity); } }
// Use this for initialization IEnumerator Start() { { for (int x = -99; x <= 99; x += 6) { for (int y = -99; y <= 99; y += 6) { for (int z = -99; z <= 99; z += 6) { positions.Add(new Vector3(x, y, z)); } } } } tree = new LooseOctree <GameObject>(200F, Vector3.zero, 1.25F, positions.Count); numObjectsDisplay.text = "Objects per iteration: " + positions.Count; float[] buildResults = new float[20]; float buildTotal = 0; float[] destroyResults = new float[20]; float destroyTotal = 0; Stopwatch timer = new Stopwatch(); for (int i = 0; i < buildResults.Length; i++) { iterationsDisplay.text = "Iterations: " + (i + 1); buildResults[i] = PopulateTree(timer); timer.Stop(); buildTotal += buildResults[i]; numNodesDisplay.text = "Nodes per iteration: " + tree.nodeCount; destroyResults[i] = DestroyTree(timer); destroyTotal += destroyResults[i]; averageTimeDisplay.text = "Average time: Build(" + Mathf.Round(buildTotal / (i + 1)) + "ms) - Destroy(" + Mathf.Round(destroyTotal / (i + 1)) + "ms)"; totalTimeDisplay.text = "Total time: Build(" + buildTotal + "ms) - Destroy(" + destroyTotal + "ms)"; yield return(new WaitForSeconds(0.1F)); } PopulateTree(timer); pointTree = new PointOctree <OctreeObject <GameObject> >(200F, Vector3.zero, 1.25F); OctreeObject <GameObject> obj; Queue <OctreeObject <GameObject> > remObj = new Queue <OctreeObject <GameObject> >(); timer.Reset(); while (treeObj.Count > 0) { obj = treeObj.Dequeue(); timer.Start(); pointTree.Add(obj, obj.boundsCenter); timer.Stop(); remObj.Enqueue(obj); } pointTreeAddTimeDisplay.text = timer.ElapsedMilliseconds + "ms"; timer.Reset(); while (remObj.Count > 0) { obj = remObj.Dequeue(); timer.Start(); pointTree.Remove(obj); timer.Stop(); } pointTreeRemoveTimeDisplay.text = timer.ElapsedMilliseconds + "ms"; averageTimeDisplay.text = "Average time: Build(" + buildTotal / buildResults.Length + "ms) - Destroy(" + destroyTotal / destroyResults.Length + "ms)"; StartCoroutine(PopulateTreeSlow()); }
/// <summary> /// Runs current tracked object data through Octree. /// </summary> private TrackedObjectStates evaluateOctree(OctreeThreadParameters otp) { int alloc = WorldMonitor.Instance.AllocationSpace; updatePositions = new Vector3[alloc]; // otp.ObjectIDs.Count float[] thresholds = new float[alloc]; // otp.ObjectIDs.Count //for (int i = 0; i < otp.ObjectIDs.Count; i++) foreach (int id in otp.ObjectIDs) { KeyValuePair <float, Vector3> pos; if (!otp.Coordinates.TryGetValue(id, out pos)) { Debug.LogError("unknown object position request in octree eval"); } thresholds[id] = pos.Key; updatePositions[id] = pos.Value; PointOctree.Remove(id); PointOctree.Add(id, pos.Value); } List <int[]> enteringIDs = new List <int[]>(); List <int[]> leavingIDs = new List <int[]>(); List <int> parentIDLeavers = new List <int>(); List <int> parentIDEnterers = new List <int>(); int ind = 0; foreach (int id in otp.ObjectIDs) { List <int> validConflicts = new List <int>(); List <int> stayers = new List <int>(); int[] areaObjects = PointOctree.GetNearby(updatePositions[id], thresholds[id]); for (int j = 0; j < areaObjects.Length; j++) { string affiliateObj = WorldMonitor.Instance.TrackedObjectAffiliations[id]; string affiliateCompare = WorldMonitor.Instance.TrackedObjectAffiliations[areaObjects[j]]; /* * run conflict validity checks: if not the same object && not an object of the same class type && is a new conflict */ if (areaObjects[j] != id && !MasterList[id].Contains(areaObjects[j]) && string.Compare(affiliateObj, affiliateCompare) != 0) { if (!parentIDEnterers.Contains(id)) { parentIDEnterers.Add(id); } MasterList[id].Add(areaObjects[j]); // add conflicting object to master list of current conflicts validConflicts.Add(areaObjects[j]); // *new* conflicts stayers.Add(areaObjects[j]); // use to look for conflicts that have ended } else if (MasterList[id].Contains(areaObjects[j])) { stayers.Add(areaObjects[j]); // this is an object staying in conflict } } bool leaverDetected = false; List <int> leavers = new List <int>(); foreach (int _id in MasterList[id]) // look at master list's record of conflicts for this parent ID - if it isn't in stayers, it has left the conflict area or been destroyed { if (!stayers.Contains(_id)) { leaverDetected = true; leavers.Add(_id); } switch (WorldMonitor.Instance.ConflictEndMode) { case ConflictEndMode.OnAllConflictsEnded: if (leavers.Count == MasterList[id].Count) { parentIDLeavers.Add(id); } break; case ConflictEndMode.OnIndividualConflictEnded: if (leaverDetected && !parentIDEnterers.Contains(id) && !parentIDLeavers.Contains(id)) { parentIDLeavers.Add(id); } break; } } foreach (int leaver in leavers) { MasterList[id].Remove(leaver); } int numValid = leavers.ToArray().Length; if (numValid > 0) { leavingIDs.Add(leavers.ToArray()); } numValid = validConflicts.ToArray().Length; if (numValid > 0) { enteringIDs.Add(validConflicts.ToArray()); } ind++; } return(new TrackedObjectStates { ParentIDEnterers = parentIDEnterers.ToArray(), // parent IDs of new or increased conflict states ParentIDLeavers = parentIDLeavers.ToArray(), // parent IDs of expired or reduced conflict states LeavingIDs = leavingIDs, // child IDs - ended conflict(s) EnteringIDs = enteringIDs, // child IDs - the conflict(s) PriorConflictingIDs = parentIDLeavers // parent IDs that need informed all conflicts have ceased }); }