public static bool CheckCollision(Collider aa, Collider bb)
 {
     return Collision.CheckDispatch[(int)aa.shape.GetShapeType(), (int)bb.shape.GetShapeType()](aa, bb);
 }
        public List<Collider> retrieve(Collider collider, int reach = -1)
        {
            //CountArray<Node>[,] nodes;

            //if (reach == -1) reach = cellReach;
            if (reach == -1) reach = 5;
            List<Collider> returnList = new List<Collider>();
            Tuple<int, int> indexs = getIndexs(collider);
            int x = indexs.Item1;
            int y = indexs.Item2;
            //grid[indexs.Item1, indexs.Item2].Add(node);
            int xbegin, xend, ybegin, yend;
            xbegin = x - reach;
            xend = x + reach + 1;
            if (xbegin < 0) xbegin = 0;
            if (xend > cellsX) xend = cellsX;

            ybegin = y - reach;
            yend = y + reach + 1;
            if (ybegin < 0) ybegin = 0;
            if (yend > cellsY) yend = cellsY;
            //return box of slots
            /*
            for (int i = xbegin; i < xend; i++)
            {
                for (int j = ybegin; j < yend; j++)
                {
                    //grid[i, j] = new List<Node>();
                    //returnList.AddRange(grid[i, j]);
                    foreach (Node n in grid[i, j])
                    {
                        returnList.Add(n);
                    }
                }
            }
            */
            //return circle of slots
            ///*
            //int cellsHit = 0;
            for (int i = xbegin; i < xend; i++)
            {
                for (int j = ybegin; j < yend; j++)
                {
                    // Wow. Never use Math class >.<
                    //double dist = Math.Pow(Math.Abs(x - i), 2) + Math.Pow(Math.Abs(y - j), 2);
                    int xd = (x - i) * (x - i);
                    if (xd < 0) xd *= -1;
                    int yd = (y - j) * (y - j);
                    if (yd < 0) yd *= -1;
                    int dist = xd + yd;

                    if (dist <= reach * reach)
                    {
                        returnList.AddRange(grid[i, j]);
                        //foreach (Node n in grid[i, j])
                        //{
                        //    returnList.Add(n);
                        //}
                        //cellsHit++;
                    }

                }

            }
            //Console.WriteLine("Cells hit: {0}", cellsHit);
            ///*
            //Console.WriteLine("xbegin:{0} + xend:{1} + ybegin:{2} + yend:{3}", xbegin, xend, ybegin, yend);
            return returnList;
        }
Пример #3
0
        public override void CheckCollisionCollider(Collider other)
        {
            //if (!active || !other.active) { return; }
            //if (exclusions.Contains(other)) return;

            //Manifold m = new Manifold(this, other);
            //m.Solve();
            bool iscolliding = Collision.CheckCollision(this, other);

            if (iscolliding)
            {
                if (DoExclusionCheck(other)) return;
                if (other.HandlersEnabled)
                {
                    //todo:add to handler list
                    //if (OnCollisionStay != null)
                    //{
                    //    OnCollisionStay(parent, other.parent);
                    //}
                    //bool parentEnter = OnCollisionEnter != null;
                    //if (parentEnter || OnCollisionExit != null || OnCollisionFirstEnter != null || OnCollisionAllExit != null)
                    //{
                    //    HashSet<Collider> lastframe = previousCollision;
                    //    HashSet<Collider> thisframe = currentCollision;
                    //    thisframe.Add(other);
                    //    if (!lastframe.Contains(other) && parentEnter)
                    //    {
                    //        OnCollisionEnter(parent, other.parent);
                    //    }
                    //}

                    if (other.OnCollisionStay != null)
                    {
                        other.OnCollisionStay(other.parent, parent);
                    }
                    bool otherEnter = other.OnCollisionEnter != null;
                    if (otherEnter || other.OnCollisionExit != null || other.OnCollisionFirstEnter != null || other.OnCollisionAllExit != null)
                    {
                        //HashSet<Node> lastframe = other.collision.currentIsCol1 ? other.collision.collisions1 : other.collision.collisions2;
                        //HashSet<Node> thisframe = !other.collision.currentIsCol1 ? other.collision.collisions1 : other.collision.collisions2;
                        HashSet<Collider> lastframe = other.previousCollision;
                        HashSet<Collider> thisframe = other.currentCollision;
                        thisframe.Add(this);
                        if (!lastframe.Contains(this) && otherEnter)
                        {
                            other.OnCollisionEnter(other.parent, parent);
                        }
                    }
                }
            }
        }
Пример #4
0
 public virtual void CheckCollisionCollider(Collider other)
 {
     //bool iscolliding = Collision.CheckCollision(this, other);
     //
     //if (iscolliding)
     //{
     //    //todo:add to handler list
     //    InvokeOnCollisionStay(other.parent);
     //
     //    bool parentEnter = OnCollisionEnter != null;
     //    if (parentEnter || OnCollisionExit != null || OnCollisionFirstEnter != null || OnCollisionAllExit != null)
     //    {
     //        HashSet<Collider> lastframe = previousCollision;
     //        HashSet<Collider> thisframe = currentCollision;
     //        thisframe.Add(other);
     //        if (!lastframe.Contains(other) && parentEnter)
     //        {
     //            OnCollisionEnter(parent, other.parent);
     //        }
     //    }
     //
     //    other.InvokeOnCollisionStay(parent);
     //
     //    bool otherEnter = other.OnCollisionEnter != null;
     //    if (otherEnter || other.OnCollisionExit != null || other.OnCollisionFirstEnter != null || other.OnCollisionAllExit != null)
     //    {
     //        //HashSet<Node> lastframe = other.collision.currentIsCol1 ? other.collision.collisions1 : other.collision.collisions2;
     //        //HashSet<Node> thisframe = !other.collision.currentIsCol1 ? other.collision.collisions1 : other.collision.collisions2;
     //        HashSet<Collider> lastframe = other.previousCollision;
     //        HashSet<Collider> thisframe = other.currentCollision;
     //        thisframe.Add(this);
     //        if (!lastframe.Contains(this) && otherEnter)
     //        {
     //            other.OnCollisionEnter(other.parent, parent);
     //        }
     //    }
     //
     //}
 }
        public void retrieveNew(Collider collider, float reachDistance, Action<Node> action)
        {
            int x = (int)collider.pos.X / cellWidth;
            int y = (int)collider.pos.Y / cellHeight;
            if (x < 0 || x >= cellsX || y < 0 || y >= cellsY) return;

            foreach(float dist in distToOffsets.Keys)
            {
                if (dist > reachDistance) break;
                foreach(var tuple in distToOffsets[dist])
                {
                    foreach (Collider c in grid[x + tuple.Item1, y + tuple.Item2])
                    {
                        action(c.parent);

                    }
                }
            }
        }
 public void RemoveCollider(Collider collider)
 {
     if (CollisionSetCircle.Contains(collider))
         CollisionSetCircle.Remove(collider);
     if (CollisionSetPolygon.Contains(collider))
         CollisionSetPolygon.Remove(collider);
 }
        public static bool PolygontoPolygonCheck(Collider a, Collider b)
        {
            Polygon A = (Polygon)a.shape;
            Polygon B = (Polygon)b.shape;
            //m.contact_count = 0;

            // Check for a separating axis with A's face planes
            int faceA = 0;
            double penetrationA = FindAxisLeastPenetration(ref faceA, A, B);
            if (penetrationA >= 0.0f)
                return false;

            // Check for a separating axis with B's face planes
            int faceB = 0;
            double penetrationB = FindAxisLeastPenetration(ref faceB, B, A);
            if (penetrationB >= 0.0f)
                return false;

            int referenceIndex;
            //bool flip; // Always point from a to b

            Polygon RefPoly; // Reference
            Polygon IncPoly; // Incident

            // Determine which shape contains reference face
            if (GMath.BiasGreaterThan(penetrationA, penetrationB))
            {
                RefPoly = A;
                IncPoly = B;
                referenceIndex = faceA;
                //flip = false;
            }
            else
            {
                RefPoly = B;
                IncPoly = A;
                referenceIndex = faceB;
                //flip = true;
            }
            // World space incident face
            Vector2[] incidentFace = new Vector2[2];
            FindIncidentFace(ref incidentFace, RefPoly, IncPoly, referenceIndex);
            // Setup reference face vertices
            Vector2 v1 = RefPoly.vertices[referenceIndex];
            referenceIndex = referenceIndex + 1 == RefPoly.vertexCount ? 0 : referenceIndex + 1;
            Vector2 v2 = RefPoly.vertices[referenceIndex];

            // Transform vertices to world space
            v1 = RefPoly.u * v1 + RefPoly.body.pos;
            v2 = RefPoly.u * v2 + RefPoly.body.pos;

            // Calculate reference face side normal in world space
            Vector2 sidePlaneNormal = (v2 - v1);
            VMath.NormalizeSafe(ref sidePlaneNormal);

            // Orthogonalize
            Vector2 refFaceNormal = new Vector2(sidePlaneNormal.Y, -sidePlaneNormal.X);

            // ax + by = c
            // c is distance from origin
            double refC = Vector2.Dot(refFaceNormal, v1);
            double negSide = -Vector2.Dot(sidePlaneNormal, v1);
            double posSide = Vector2.Dot(sidePlaneNormal, v2);

            // Clip incident face to reference face side planes
            if (Clip(-sidePlaneNormal, negSide, ref incidentFace) < 2)
                return false; // Due to floating point error, possible to not have required points

            if (Clip(sidePlaneNormal, posSide, ref incidentFace) < 2)
                return false; // Due to floating point error, possible to not have required points

            // Flip
            //m.normal = flip ? -refFaceNormal : refFaceNormal;

            // Keep points behind reference face
            int cp = 0; // clipped points behind reference face
            double separation = Vector2.Dot(refFaceNormal, incidentFace[0]) - refC;
            if (separation <= 0.0f)
            {
                //m.contacts[cp] = incidentFace[0];
                //m.penetration = -separation;
                ++cp;
            }
            //else
            //    m.penetration = 0;

            separation = Vector2.Dot(refFaceNormal, incidentFace[1]) - refC;
            if (separation <= 0.0f)
            {
                //m.contacts[cp] = incidentFace[1];
                //
                //m.penetration += -separation;
                ++cp;

                // Average penetration
                //m.penetration /= (double)cp;
            }

            //m.contact_count = cp;
            return cp > 0;
        }
 public void retrieveFromAllOffsets(Collider collider, float reachDistance, Action<Collider, Collider> action)
 {
     int x = (int)collider.pos.X / cellWidth;
     int y = (int)collider.pos.Y / cellHeight;
     if (x < 0 || x >= cellsX || y < 0 || y >= cellsY) return;
     int findcount = FindCount(reachDistance);
     for (int i = 0; i < findcount; i++)
     {
         foreach (var tuple in distToOffsets.ElementAt(i).Value)
         {
             int xx = tuple.Item1 + x; int yy = tuple.Item2 + y;
             if (xx < 0 || xx >= cellsX || yy < 0 || yy >= cellsY) continue;
             //foreach (Collider c in grid[tuple.Item1, tuple.Item2])
             //{
             //    action(collider, c);
             //}
             IndexArray<Collider> buck = arrayGrid[xx][yy];
             int count = buck.index;
             //if (count > 0) Console.WriteLine(count);
             for (int j = 0; j < count; j++)
             {
                 Collider c = arrayGrid[xx][yy].array[j];
                 if (alreadyVisited.Contains(c) || collider == c) continue;
                 action(collider, c);
             }
         }
     }
 }
 public static bool PolygontoCircle(Manifold m, Collider a, Collider b)
 {
     bool ret = CircletoPolygon(m, b, a);
     m.normal = -m.normal;
     return ret;
 }
Пример #10
0
 public static bool PolygontoCircleCheck(Collider a, Collider b)
 {
     return CircletoPolygonCheck(b, a);
     //m.normal = -m.normal;
     //return ret;
 }
Пример #11
0
        public static bool CircletoPolygonCheck(Collider a, Collider b)
        {
            Circle A = (Circle)a.shape;
            Polygon B = (Polygon)b.shape;

            //m.contact_count = 0;

            // Transform circle center to Polygon model space
            Vector2 center = a.pos;
            center = B.u.Transpose() * (center - b.pos);

            // Find edge with minimum penetration
            // Exact concept as using support points in Polygon vs Polygon
            double separation = -float.MaxValue;
            int faceNormal = 0;
            for (int i = 0; i < B.vertexCount; ++i)
            {
                double s = Vector2.Dot(B.normals[i], center - B.vertices[i]);

                if (s > A.radius)
                {
                    return false;
                }

                if (s > separation)
                {
                    separation = s;
                    faceNormal = i;
                }
            }

            // Grab face's vertices
            Vector2 v1 = B.vertices[faceNormal];
            int i2 = faceNormal + 1 < B.vertexCount ? faceNormal + 1 : 0;
            Vector2 v2 = B.vertices[i2];

            // Check to see if center is within polygon
            if (separation < GMath.EPSILON)
            {
                //m.contact_count = 1;
                //m.normal = -(B.u * B.normals[faceNormal]);
                //m.contacts[0] = VMath.MultVectDouble(m.normal, A.radius) + a.pos;
                //m.penetration = A.radius;
                return true;
            }

            // Determine which voronoi region of the edge center of circle lies within
            double dot1 = Vector2.Dot(center - v1, v2 - v1);
            double dot2 = Vector2.Dot(center - v2, v1 - v2);
            //m.penetration = A.radius - separation;

            // Closest to v1
            if (dot1 <= 0.0f)
            {
                if (Vector2.DistanceSquared(center, v1) > A.radius * A.radius)
                {
                    return false;
                }
                //m.contact_count = 1;
                //Vector2 n = v1 - center;
                //n = B.u * n;
                //n.Normalize();
                //m.normal = n;
                //v1 = B.u * v1 + b.pos;
                //m.contacts[0] = v1;
            }
            // Closest to v2
            else if (dot2 <= 0.0f)
            {
                if (Vector2.DistanceSquared(center, v2) > A.radius * A.radius)
                {
                    return false;
                }

                //m.contact_count = 1;
                //Vector2 n = v2 - center;
                //v2 = B.u * v2 + b.pos;
                //m.contacts[0] = v2;
                //n = B.u * n;
                //n.Normalize();
                //m.normal = n;
            }
            // Closest to face
            else
            {
                Vector2 n = B.normals[faceNormal];
                if (Vector2.Dot(center - v1, n) > A.radius)
                {
                    return false;
                }

                //n = B.u * n;
                //m.normal = -n;
                //m.contacts[0] = VMath.MultVectDouble(m.normal, A.radius) + a.pos;
                //m.contact_count = 1;
            }
            return true;
        }
Пример #12
0
 ////////FUCKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
 public static bool CircletoCircleCheck(Collider a, Collider b)
 {
     Vector2 normal = b.pos - a.pos;
     float distSquared = normal.LengthSquared();
     double radius = a.radius + b.radius;
     return distSquared < radius * radius;
 }
Пример #13
0
        public static bool CircletoCircle(Manifold m, Collider a, Collider b)
        {
            Circle ca = (Circle)a.shape;
            Circle cb = (Circle)b.shape;
            Vector2 normal = b.pos - a.pos;
            float distSquared = normal.LengthSquared();
            double radius = a.radius + b.radius;

            if (distSquared >= (float)(radius * radius))
            {
                m.contact_count = 0;
                return false;
            }

            double distance = Math.Sqrt(distSquared);
            m.contact_count = 1;

            if (distance == 0)
            {
                m.penetration = ca.radius;
                m.normal = new Vector2(1, 0);
                m.contacts[0] = a.pos;
            }
            else
            {
                m.penetration = radius - distance;
                m.normal = VMath.MultVectDouble(normal, 1.0 / distance); //normal / distance;
                m.contacts[0] = VMath.MultVectDouble(m.normal, ca.radius) + a.pos; //m.normal * ca.radius + a.body.position;
            }
            return true;
        }
        public IndexArray<IndexArray<Collider>> retrieveBucketBags(Collider collider)
        {
            int effectiveX = (int)(collider.pos.X - position.X);
            int effectiveY = (int)(collider.pos.Y - position.Y);

            if (effectiveX < 0 || effectiveY < 0) return null;
            int x = effectiveX / cellWidth;
            int y = effectiveY / cellHeight;

            if (x < 0 || x >= cellsX || y < 0 || y >= cellsY) return null;
            return bucketBags[x][y];
        }
Пример #15
0
 public void AddCollider(string key, Collider col)
 {
     int i = 0;
     while(colliders.ContainsKey(key))
     {
         key = key + i++;
     }
     colliders.Add(key, col);
     col.parent = parent;
     if (active && parent != null && parent.group != null)
     {
         UpdateCollisionSet();
     }
 }
        public List<List<Collider>> retrieveBuckets(Collider collider, float reachDistance)
        {
            int x = (int)collider.pos.X / cellWidth;
            int y = (int)collider.pos.Y / cellHeight;

            if (x < 0 || x >= cellsX || y < 0 || y >= cellsY)
            {
                return null;
            }
            else
            {
                if (bucketLists[x, y] != null)
                {
                    preexistingCounter++;
                    return bucketLists[x, y];
                }
                bucketLists[x, y] = new List<List<Collider>>();

                int count = FindCount(reachDistance);
                var dict = offsetsArrayCollection[x, y];
                if (dict.Count <= count)
                {
                    throw new SystemException("Count too big exception");
                }
                //int cellsHit = 0;
                for (int i = 0; i < count; i++)
                {
                    List<Tuple<int, int>> tuples = dict.ElementAt(i).Value;
                    foreach (var tuple in tuples)
                    {
                        bucketLists[x, y].Add(grid[tuple.Item1 + x, tuple.Item2 + y]);
                    }
                }
                //Console.WriteLine(cellsHit);
                return bucketLists[x, y];
            }
        }
 public bool ContainsCollider(Collider collider)
 {
     for (int i = 0; i < cellsX; i++)
     {
         for (int j = 0; j < cellsY; j++)
         {
             if (grid[i, j].Contains(collider)) return true;
         }
     }
     return false;
 }
 public void retrieveFromOptimizedOffsets(Collider collider, float reachDistance, Action<Node> action)
 {
     int x = (int)collider.pos.X / cellWidth;
     int y = (int)collider.pos.Y / cellHeight;
     if (x < 0 || x >= cellsX || y < 0 || y >= cellsY) return;
     int count = FindCount(reachDistance);
     var dict = offsetsArrayCollection[x, y];
     if (dict.Count <= count)
     {
         throw new SystemException("Count too big exception");
     }
     //int cellsHit = 0;
     for (int i = 0; i < count; i++)
     {
         foreach (var tuple in dict.ElementAt(i).Value)
         {
             foreach (Collider c in grid[tuple.Item1 + x, tuple.Item2 + y])
             {
                 action(c.parent);
             }
             //cellsHit++;
         }
     }
     //Console.WriteLine(cellsHit);
 }
        public Tuple<int, int> getIndexs(Collider collider)
        {
            Vector2 pos = new Vector2(collider.pos.X, collider.pos.Y);
            int x = (int)collider.pos.X;
            int y = (int)collider.pos.Y;
            int gridx = (int)pos.X - ((int)pos.X % cellWidth);
            x = gridx / cellWidth;
            //if ((int)pos.X - gridx > gridx + cellwidth - (int)node.transform.radius) x++;
            int gridy = (int)pos.Y - ((int)pos.Y % cellHeight);
            y = gridy / cellHeight;
            //if ((int)pos.Y - gridy > gridy + cellheight - (int)node.transform.radius) y++;

            if (x > cellsX - 1) x = cellsX - 1;
            if (y > cellsY - 1) y = cellsY - 1;
            if (x < 0) x = 0;
            if (y < 0) y = 0;
            //Console.WriteLine("{0} + {1}", x, y);
            return new Tuple<int, int>(x, y);
        }
        public void retrieveOffsetArraysCollision(Collider collider, Action<Collider, Collider> action, float distance)
        {
            int effectiveX = (int)(collider.pos.X - position.X);
            int effectiveY = (int)(collider.pos.Y - position.Y);

            int x = effectiveX / cellWidth;
            int y = effectiveY / cellHeight;
            if (x < 0 || x > cellsX || y < 0 || y > cellsY) return;
            int findcount = FindCount(distance);
            int lastIndex;
            //lastIndex = reachIndexs[reachCount];
            lastIndex = reachIndexs[findcount];
            for (int coordPointer = 0; coordPointer <= lastIndex; coordPointer += 2)
            {
                int xx = offsetArray[coordPointer] + x;
                int yy = offsetArray[coordPointer + 1] + y;
                if (xx < 0 || xx >= cellsX || yy < 0 || yy >= cellsY) continue;
                IndexArray<Collider> buck = arrayGrid[xx][yy];
                int count = buck.index;
                for (int j = 0; j < count; j++)
                {
                    Collider c = arrayGrid[xx][yy].array[j];
                    //if (room.ColorNodesInReach && collider.parent == room.targetNode) c.parent.body.color = Color.Purple;
                    if (alreadyVisited.Contains(c) || collider == c) continue;
                    action(collider, c);
                }
            }
        }
 // gets the index of the node in the gridsystem, without correcting out of bounds nodes.
 public Tuple<int, int> getIndexsNew(Collider collider)
 {
     //int a = (int)node.body.pos.X / cellWidth;
     return new Tuple<int, int>((int)collider.pos.X / cellWidth, (int)collider.pos.Y / cellHeight);
 }
 public void AddCollider(Collider collider)
 {
     if (collider.shape is Circle)
         CollisionSetCircle.Add(collider);
     else if (collider.shape is Polygon)
         CollisionSetPolygon.Add(collider);
 }
 //static int largest = 0;
 public void insert(Collider collider)
 {
     Tuple<int, int> indexs = getIndexs(collider);
     //if (node == room.game.targetNode) Console.WriteLine("target indexs: {0} {1}",indexs.Item1,indexs.Item2);
     grid[indexs.Item1, indexs.Item2].Add(collider);
     //if (grid[indexs.Item1, indexs.Item2].Count > largest)
     //{
     //    largest = grid[indexs.Item1, indexs.Item2].Count;
     //    //Console.WriteLine(largest);
     //}
     //grid[indexs.Item1, indexs.Item2].ToArray();
 }
Пример #24
0
 public void AddExclusionCheck(Collider other)
 {
     ExclusionCheck += (s, o) =>
     {
         return o == other;
     };
     other.ExclusionCheck += (s, o) =>
     {
         return o == this;
     };
 }
        public void insertToBuckets(Collider collider, bool forceIntoGrid = true)
        {
            int effectiveX = (int)(collider.pos.X - position.X);
            int effectiveY = (int)(collider.pos.Y - position.Y);

            int x = effectiveX / cellWidth;
            int y = effectiveY / cellHeight;
            //if (x < 0 || x >= cellsX || y < 0 || y >= cellsY) return;
            if (x < 0)
            {
                if (forceIntoGrid) x = 0;
                else
                    return;
            }
            else if (x >= cellsX)
            {
                if (forceIntoGrid) x = cellsX - 1;
                else
                    return;
            }
            if (y < 0)
            {
                if (forceIntoGrid) y = 0;
                else
                    return;
            }
            else if (y >= cellsY)
            {
                if (forceIntoGrid) y = cellsY - 1;
                else
                    return;
            }
            arrayGrid[x][y].AddItem(collider);
        }
Пример #26
0
 public bool DoExclusionCheckResolution(Collider other)
 {
     if (ExclusionCheckResolution != null)
     {
         foreach (Func<Collider, Collider, bool> del in ExclusionCheckResolution.GetInvocationList())
         {
             if (del(this, other)) return true;
         }
     }
     return false;
 }
Пример #27
0
        public void InitializePlayers()
        {
            for (int i = 0; i < 8; i++)
            {
                //Player p = Player.GetNew(i);
                Player p = new Player(i);
                if (p == null) break;
                Vector2 spawnPos = Vector2.Zero;
                double angle = Utils.random.NextDouble() * Math.PI * 2;
                angle -= Math.PI;
                float dist = 200;
                float x = dist * (float)Math.Cos(angle);
                float y = dist * (float)Math.Sin(angle);
                spawnPos = new Vector2(room.worldWidth / 2, room.worldHeight / 2) - new Vector2(x, y);

                //add //{ nodeE.position, spawnPos },
                p.node = room.spawnNode(playerProps);
                p.node.name = "player" + p.playerIndex;

                p.node.Comp<Queuer>().queuecount = 100;

                Collider collider = new Collider(new Circle(25));
                p.node.collision.AddCollider("trigger", collider);
                collider.OnCollisionEnter += onCollisionEnter;
                collider.OnCollisionExit += onCollisionExit;

                p.node.addComponent<Swap>(true);
                p.node.Comp<Swap>().OnSwapBefore += before;
                p.node.Comp<Swap>().OnSwapAfter += after;

            }
        }