Esempio n. 1
0
        /// <summary>
        /// Check if the specified bounds intersect with anything in the tree. See also: GetColliding.
        /// </summary>
        /// <param name="checkBounds">Bounds to check.</param>
        /// <returns>True if there was a collision.</returns>
        public bool IsColliding(ColliderProxy obj, ref LRect checkBounds)
        {
            // Are the input bounds at least partially in this node?
            if (!bounds.Overlaps(checkBounds))
            {
                return(false);
            }

            // Check against any objects in this node
            for (int i = 0; i < objects.Count; i++)
            {
                var o = objects[i];
                if (!ReferenceEquals(o.Obj, obj) && o.Bounds.Overlaps(checkBounds))
                {
                    return(true);
                }
            }

            // Check children
            if (children != null)
            {
                for (int i = 0; i < NUM_CHILDREN; i++)
                {
                    if (children[i].IsColliding(obj, ref checkBounds))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Esempio n. 2
0
        public void CheckCollision(ColliderProxy obj, ref LRect checkBounds)
        {
            // Are the input bounds at least partially in this node?
            if (!bounds.Overlaps(checkBounds))
            {
                return;
            }

            // Check against any objects in this node
            for (int i = 0; i < objects.Count; i++)
            {
                var o = objects[i];
                if (!ReferenceEquals(o.Obj, obj) &&
                    BoundsQuadTree.FuncCanCollide(o.Obj, obj) &&
                    o.Bounds.Overlaps(checkBounds)
                    )
                {
                    BoundsQuadTree.funcOnCollide(obj, o.Obj);
                }
            }

            // Check children
            if (children != null)
            {
                for (int i = 0; i < NUM_CHILDREN; i++)
                {
                    children[i].CheckCollision(obj, ref checkBounds);
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Private counterpart to the public <see cref="Remove(ColliderProxy, LRect)"/> method.
        /// </summary>
        /// <param name="obj">Object to remove.</param>
        /// <param name="objBounds">3D bounding box around the object.</param>
        /// <returns>True if the object was removed successfully.</returns>
        bool SubRemove(ColliderProxy obj, LRect objBounds)
        {
            bool removed = false;

            for (int i = 0; i < objects.Count; i++)
            {
                if (ReferenceEquals(objects[i].Obj, obj))
                {
                    removed = objects.Remove(objects[i]);
                    break;
                }
            }

            if (!removed && children != null)
            {
                int bestFitChild = BestFitChild(objBounds.center);
                removed = children[bestFitChild].SubRemove(obj, objBounds);
            }

            if (removed && children != null)
            {
                // Check if we should merge nodes now that we've removed an item
                if (ShouldMerge())
                {
                    Merge();
                }
            }

            return(removed);
        }
Esempio n. 4
0
        /// <summary>
        /// Remove an object. Makes the assumption that the object only exists once in the tree.
        /// </summary>
        /// <param name="obj">Object to remove.</param>
        /// <returns>True if the object was removed successfully.</returns>
        public bool Remove(ColliderProxy obj)
        {
            if (obj2Node.TryGetValue(obj, out var val))
            {
                obj2Node.Remove(obj);
                bool removed = false;
                for (int i = 0; i < val.objects.Count; i++)
                {
                    if (ReferenceEquals(val.objects[i].Obj, obj))
                    {
                        val.objects.RemoveAt(i);
                        removed = true;
                        break;
                    }
                }

                if (removed)
                {
                    val.OnRemoved();
                }

                return(removed);
            }

            return(false);
        }
        bool NeedCheck(ColliderProxy a, ColliderProxy b)
        {
            var val       = _collisionMask[a.LayerType];
            var val2      = 1 << b.LayerType;
            var needCheck = (val & val2) != 0;

            return(needCheck);
        }
 private void _CheckRegionCircle(ColliderProxy obj)
 {
     Debug.Trace($"ColliderProxy _CheckRegionCircle {obj.Id} trans{obj.Transform2D} col{obj.Prefab}");
     if (CollisionHelper.CheckCollision(obj.Prefab, obj.Transform2D, _tempPos, _tempRadius))
     {
         tempCallback(obj);
     }
 }
 private void _CheckRegionOBB(ColliderProxy obj)
 {
     Debug.Trace($"ColliderProxy _CheckRegionOBB {obj.Id} trans{obj.Transform2D} col{obj.Prefab}");
     if (CollisionHelper.CheckCollision(obj.Prefab, obj.Transform2D, _tempPos, _tempSize, _tempForward))
     {
         tempCallback(obj);
     }
 }
Esempio n. 8
0
 /// <summary>
 /// Check if the specified bounds intersect with anything in the tree. See also: GetColliding.
 /// </summary>
 /// <param name="checkBounds">bounds to check.</param>
 /// <returns>True if there was a collision.</returns>
 public bool IsColliding(ColliderProxy obj, LRect checkBounds)
 {
     //#if UNITY_EDITOR
     // For debugging
     //AddCollisionCheck(checkBounds);
     //#endif
     return(rootNode.IsColliding(obj, ref checkBounds));
 }
Esempio n. 9
0
        /// <summary>
        /// Removes the specified object at the given position. Makes the assumption that the object only exists once in the tree.
        /// </summary>
        /// <param name="obj">Object to remove.</param>
        /// <param name="objBounds">3D bounding box around the object.</param>
        /// <returns>True if the object was removed successfully.</returns>
        public bool Remove(ColliderProxy obj, LRect objBounds)
        {
            if (!Encapsulates(bounds, objBounds))
            {
                return(false);
            }

            return(false);
        }
Esempio n. 10
0
        // #### PUBLIC METHODS ####


        // #### PUBLIC METHODS ####
        public BoundsQuadTreeNode GetNode(ColliderProxy obj)
        {
            if (BoundsQuadTreeNode.obj2Node.TryGetValue(obj, out var val))
            {
                return(val);
            }

            return(null);
        }
Esempio n. 11
0
        /// <summary>
        /// Add an object.
        /// </summary>
        /// <param name="obj">Object to add.</param>
        /// <param name="objBounds">3D bounding box around the object.</param>
        /// <returns>True if the object fits entirely within this node.</returns>
        public bool Add(ColliderProxy obj, LRect objBounds)
        {
            if (!Encapsulates(bounds, objBounds))
            {
                return(false);
            }

            SubAdd(obj, objBounds);
            return(true);
        }
Esempio n. 12
0
        private ColliderProxy CreateType(int layerType, bool isStatic, Color rawColor)
        {
            var prefab = prefabs[Random.Range(0, prefabs.Count)];
            var type   = (EShape2D)prefab.collider.TypeId;
            var obj    = GameObject.CreatePrimitive(type2PType[type]).GetComponent <Collider>();

            obj.transform.SetParent(transform, false);
            obj.transform.position = new Vector3(Random.Range(-halfworldSize, halfworldSize), 0,
                                                 Random.Range(-halfworldSize, halfworldSize));
            switch (type)
            {
            case EShape2D.Circle: {
                var colInfo = (CCircle)prefab.collider;
                obj.transform.localScale =
                    new Vector3(colInfo.radius.ToFloat() * 2, 1, colInfo.radius.ToFloat() * 2);
                break;
            }

            case EShape2D.AABB: {
                var colInfo = (CAABB)prefab.collider;
                obj.transform.localScale =
                    new Vector3(colInfo.size.x.ToFloat() * 2, 1, colInfo.size.y.ToFloat() * 2);
                break;
            }

            case EShape2D.OBB: {
                var colInfo = (COBB)prefab.collider;
                obj.transform.localScale =
                    new Vector3(colInfo.size.x.ToFloat() * 2, 1, colInfo.size.y.ToFloat() * 2);
                break;
            }
            }

            var proxy = new ColliderProxy();

            proxy.Init(prefab, obj.transform.position.ToLVector2XZ());
            proxy.UnityTransform = obj.transform;
            var mono = obj.gameObject.AddComponent <ColliderProxyMono>();

            mono.proxy = proxy;
            if (!isStatic)
            {
                var mover = obj.gameObject.AddComponent <RandomMove>();
                mover.halfworldSize = halfworldSize;
                mover.isNeedRotate  = type == EShape2D.OBB;
            }

            proxy.IsStatic  = isStatic;
            proxy.LayerType = layerType;
            mono.rawColor   = rawColor;
            return(proxy);
        }
Esempio n. 13
0
 public void UpdateObj(ColliderProxy obj, LRect bound)
 {
     for (int i = 0; i < objects.Count; i++)
     {
         if (ReferenceEquals(objects[i].Obj, obj))
         {
             objects[i] = new OctreeObject()
             {
                 Obj = obj, Bounds = bound
             };
         }
     }
 }
Esempio n. 14
0
        /// <summary>
        /// Removes the specified object at the given position. Makes the assumption that the object only exists once in the tree.
        /// </summary>
        /// <param name="obj">Object to remove.</param>
        /// <param name="objBounds">3D bounding box around the object.</param>
        /// <returns>True if the object was removed successfully.</returns>
        public bool Remove(ColliderProxy obj, LRect objBounds)
        {
            bool removed = rootNode.Remove(obj, objBounds);

            // See if we can shrink the octree down now that we've removed the item
            if (removed)
            {
                Count--;
                Shrink();
            }

            return(removed);
        }
Esempio n. 15
0
        /// <summary>
        /// Removes the specified object at the given position. Makes the assumption that the object only exists once in the tree.
        /// </summary>
        /// <param name="obj">Object to remove.</param>
        /// <param name="objBounds">3D bounding box around the object.</param>
        /// <returns>True if the object was removed successfully.</returns>
        public bool Remove(ColliderProxy obj, LRect objBounds)
        {
            Debug.Trace($"ColliderProxy Add { obj.Id} objBounds  {objBounds}");
            bool removed = rootNode.Remove(obj, objBounds);

            // See if we can shrink the octree down now that we've removed the item
            if (removed)
            {
                Count--;
                Shrink();
            }

            return(removed);
        }
Esempio n. 16
0
 void OnTriggerEvent(ColliderProxy other, ECollisionEvent type)
 {
     hasCollided = true;
     if (IsDebug)
     {
         if (type != ECollisionEvent.Stay)
         {
             Debug.Log(type);
         }
     }
     if (proxy.IsStatic)
     {
         int i = 0;
     }
 }
Esempio n. 17
0
        public void NotifyCollisionEvent(ColliderProxy a, ColliderProxy b, ECollisionEvent type)
        {
            funcGlobalOnTriggerEvent?.Invoke(a, b, type);

            if (!a.IsStatic)
            {
                a.OnTriggerEvent?.Invoke(b, type);
                //TriggerEvent(a, b, type);
            }

            if (!b.IsStatic)
            {
                b.OnTriggerEvent?.Invoke(a, type);
                //TriggerEvent(b, a, type);
            }
        }
Esempio n. 18
0
        public void OnQuadTreeCollision(ColliderProxy a, ColliderProxy b)
        {
            var pairId = (((long)a.Id) << 32) + b.Id;

            if (_curPairs.Contains(pairId))
            {
                return;
            }
            bool isCollided = CollisionHelper.CheckCollision
                                  (a.Prefab, a.Transform2D, b.Prefab, b.Transform2D);

            if (isCollided)
            {
                _curPairs.Add(pairId);
                var type = _prePairs.Contains(pairId) ? ECollisionEvent.Stay : ECollisionEvent.Enter;
                NotifyCollisionEvent(a, b, type);
            }
        }
Esempio n. 19
0
        /// <summary>
        /// Add an object.
        /// </summary>
        /// <param name="obj">Object to add.</param>
        /// <param name="objBounds">3D bounding box around the object.</param>
        public void Add(ColliderProxy obj, LRect objBounds)
        {
            // Add object or expand the octree until it can be added
            int count = 0; // Safety check against infinite/excessive growth

            while (!rootNode.Add(obj, objBounds))
            {
                Debug.LogError("Grow");
                Grow(objBounds.center - rootNode.Center);
                if (++count > 20)
                {
                    Debug.LogError("Aborted Add operation as it seemed to be going on forever (" + (count - 1) +
                                   ") attempts at growing the octree.");
                    return;
                }
            }

            Count++;
        }
Esempio n. 20
0
        public static void TriggerEvent(ILPTriggerEventHandler a, ColliderProxy other, ECollisionEvent type)
        {
            switch (type)
            {
            case ECollisionEvent.Enter: {
                a.OnLPTriggerEnter(other);
                break;
            }

            case ECollisionEvent.Stay: {
                a.OnLPTriggerStay(other);
                break;
            }

            case ECollisionEvent.Exit: {
                a.OnLPTriggerExit(other);
                break;
            }
            }
        }
Esempio n. 21
0
        void TriggerEvent(ColliderProxy a, ColliderProxy other, ECollisionEvent type)
        {
            switch (type)
            {
            case ECollisionEvent.Enter: {
                a.OnTriggerEnter(other);
                break;
            }

            case ECollisionEvent.Stay: {
                a.OnTriggerStay(other);
                break;
            }

            case ECollisionEvent.Exit: {
                a.OnTriggerExit(other);
                break;
            }
            }
        }
Esempio n. 22
0
        public void UpdateObj(ColliderProxy obj, LRect bound)
        {
            var node = GetNode(obj);

            if (node == null)
            {
                Add(obj, bound);
            }
            else
            {
                if (!node.ContainBound(bound))
                {
                    Remove(obj);
                    Add(obj, bound);
                }
                else
                {
                    node.UpdateObj(obj, bound);
                }
            }
        }
Esempio n. 23
0
        public void UpdateObj(ColliderProxy obj, LRect bound)
        {
            Debug.Trace($"ColliderProxy UpdateObj { obj.Id} objBounds  {bound}");
            var node = GetNode(obj);

            if (node == null)
            {
                Add(obj, bound);
            }
            else
            {
                if (!node.ContainBound(bound))
                {
                    Remove(obj);
                    Add(obj, bound);
                }
                else
                {
                    node.UpdateObj(obj, bound);
                }
            }
        }
Esempio n. 24
0
 public void CheckCollision(ColliderProxy obj, LRect checkBounds)
 {
     rootNode.CheckCollision(obj, ref checkBounds);
 }
Esempio n. 25
0
        public void CheckCollision(ColliderProxy obj, FuncCollision callback)
        {
            var checkBounds = LRect.CreateRect(obj.pos, new LVector2(obj.MaxSideSize, obj.MaxSideSize));

            rootNode.CheckCollision(ref checkBounds, callback);
        }
Esempio n. 26
0
 public void RemoveCollider(ColliderProxy collider)
 {
     GetBoundTree(collider.LayerType).Remove(collider);
     id2Proxy.Remove(collider.Id);
     _id2LastMovePos.Remove(collider.Id);
 }
Esempio n. 27
0
        //public List<>
        public void DoUpdate(LFloat deltaTime)
        {
            tempLst.Clear();
            //deal layer
            foreach (var pair in BoundsQuadTreeNode.obj2Node)
            {
                var val = pair.Key;
                if (!val.IsStatic)
                {
                    val.DoUpdate(deltaTime);
                    if (val.IsMoved)
                    {
                        val.IsMoved = false;
                        tempLst.Add(val);
                    }
                }
            }

            //Check Collision with static colliders
            var staticTree = GetStaticBoundTree();

            __DebugColProxy1 = null;
            __DebugColProxy2 = null;
            foreach (var proxy in tempLst)
            {
                var lastPos = _id2LastMovePos[proxy.Id];
                var curPos  = proxy.Pos3;
                if (lastPos == curPos)
                {
                    continue;
                }
                staticTree.CheckCollision(proxy, (ColliderProxy obj) => {
                    if (__DebugColProxy1 != null)
                    {
                        return;
                    }
                    if (obj.Id == __DegbuLastCollisionId)
                    {
                    }

                    bool isCollided = CollisionHelper.CheckCollision
                                          (proxy.Prefab, proxy.Transform2D, obj.Prefab, obj.Transform2D);
                    if (isCollided)
                    {
                        __DebugColProxy1       = proxy;
                        __DebugColProxy2       = obj;
                        __DegbuLastCollisionId = obj.Id;
                        //Debug.LogError("碰撞到了静态物体 不让其移动");
                        proxy.Transform2D.Pos3 = lastPos;
                    }
                });
                if (proxy.Transform2D.Pos3 != lastPos)
                {
                    _id2LastMovePos[proxy.Id] = curPos;
                }
            }

            //swap
            var temp = _prePairs;

            _prePairs = _curPairs;
            _curPairs = temp;
            _curPairs.Clear();
            ////class version 1.41ms
            Profiler.BeginSample("UpdateObj");
            foreach (var val in tempLst)
            {
                val.IsMoved = false;
                var bound      = val.GetBounds();
                var boundsTree = GetBoundTree(val.LayerType);
                boundsTree.UpdateObj(val, bound);
            }

            Profiler.EndSample();
            ////0.32~0.42ms
            Profiler.BeginSample("CheckCollision");
            foreach (var val in tempLst)
            {
                val.IsMoved = false;
                var bound = val.GetBounds();
                for (int i = 0; i < LayerCount; i++)
                {
                    if (InterestingMasks[val.LayerType * LayerCount + i])
                    {
                        var boundsTree = GetBoundTree(i);
                        boundsTree.CheckCollision(val, bound);
                    }
                }
            }

            Profiler.EndSample();
            Profiler.BeginSample("CheckLastFrameCollison");
            foreach (var pairId in _curPairs)
            {
                _prePairs.Remove(pairId);
            }

            //check stay leave event
            foreach (var idPair in _prePairs)
            {
                var a = GetCollider((int)(idPair >> 32));
                var b = GetCollider((int)(idPair & 0xffffffff));
                if (a == null || b == null)
                {
                    continue;
                }

                bool isCollided = CollisionHelper.CheckCollision
                                      (a.Prefab, a.Transform2D, b.Prefab, b.Transform2D);
                if (isCollided)
                {
                    _curPairs.Add(idPair);
                    NotifyCollisionEvent(a, b, ECollisionEvent.Stay);
                }
                else
                {
                    NotifyCollisionEvent(a, b, ECollisionEvent.Exit);
                }
            }

            Profiler.EndSample();
        }
Esempio n. 28
0
        /// <summary>
        /// Private counterpart to the public Add method.
        /// </summary>
        /// <param name="obj">Object to add.</param>
        /// <param name="objBounds">3D bounding box around the object.</param>
        void SubAdd(ColliderProxy obj, LRect objBounds)
        {
            // We know it fits at this level if we've got this far

            // We always put things in the deepest possible child
            // So we can skip some checks if there are children aleady
            if (!HasChildren)
            {
                // Just add if few objects are here, or children would be below min size
                if (objects.Count < NUM_OBJECTS_ALLOWED || (BaseLength / 2) < minSize)
                {
                    OctreeObject newObj = new OctreeObject {
                        Obj = obj, Bounds = objBounds
                    };
                    objects.Add(newObj);
#if SHOW_NODES
                    obj.UnityTransform?.SetParent(monoTrans, true);
#endif

                    obj2Node[obj] = this;
                    return; // We're done. No children yet
                }

                // Fits at this level, but we can go deeper. Would it fit there?
                // Create the 8 children
                int bestFitChild;
                if (children == null)
                {
                    Split();
                    if (children == null)
                    {
                        Debug.LogError("Child creation failed for an unknown reason. Early exit.");
                        return;
                    }

                    // Now that we have the new children, see if this node's existing objects would fit there
                    for (int i = objects.Count - 1; i >= 0; i--)
                    {
                        OctreeObject existingObj = objects[i];
                        // Find which child the object is closest to based on where the
                        // object's center is located in relation to the octree's center
                        bestFitChild = BestFitChild(existingObj.Bounds.center);
                        // Does it fit?
                        if (Encapsulates(children[bestFitChild].bounds, existingObj.Bounds))
                        {
                            children[bestFitChild]
                            .SubAdd(existingObj.Obj, existingObj.Bounds); // Go a level deeper
                            objects.Remove(existingObj);                  // Remove from here
                        }
                    }
                }
            }

            // Handle the new object we're adding now
            int bestFit = BestFitChild(objBounds.center);
            if (Encapsulates(children[bestFit].bounds, objBounds))
            {
                children[bestFit].SubAdd(obj, objBounds);
            }
            else
            {
                // Didn't fit in a child. We'll have to it to this node instead
                OctreeObject newObj = new OctreeObject {
                    Obj = obj, Bounds = objBounds
                };
                objects.Add(newObj);
                obj2Node[obj] = this;
            }
        }
Esempio n. 29
0
 public void AddCollider(ColliderProxy collider)
 {
     GetBoundTree(collider.LayerType).Add(collider, collider.GetBounds());
     id2Proxy[collider.Id]        = collider;
     _id2LastMovePos[collider.Id] = collider.Pos3;
 }