示例#1
0
 // Convex.
 private static bool IsInsideCollider(
     PhysicsScene scene,
     int mask,
     Vector3 point,
     IList <Collider> colliders)
 {
     // NOTE PhysicsScene doesn't support OverlapSphereNonAlloc.
     if (scene.OverlapSphere(
             point,
             0,
             s_PhysicsBuffer,
             mask,
             QueryTriggerInteraction.UseGlobal) > 0)
     {
         foreach (var collider in colliders)
         {
             // Check buffer against colliders, so we don't
             // include points inside overlapping colliders
             // of neighbouring objects.
             if (Array.IndexOf(s_PhysicsBuffer, collider) != -1)
             {
                 return(true);
             }
         }
     }
     return(false);
 }
示例#2
0
        /// <summary>
        /// Scan considering actual collision chekcs,
        /// remove the need to have a convexed collider as forces in boundary method
        /// </summary>
        /// <returns></returns>
        public static List <Vector3>[] Scan(
            PhysicsScene physicsScene, Transform transform,
            IList <Collider> colliders, float resolution, float scanRadius, bool is2D, bool forceConvex)
        {
            List <Vector3>[] result;

            int mask   = 1 << transform.gameObject.layer;
            var matrix = transform.worldToLocalMatrix;

            int nColliders = colliders.Count;

            if (nColliders > s_Buffer.Length)
            {
                s_Buffer = new Collider[nColliders];
            }

            for (int i = 0; i < nColliders; i++)
            {
                if (colliders[i] is MeshCollider && !((MeshCollider)colliders[i]).convex && forceConvex)
                {
                    Debug.LogWarning($"Setting mesh collider '{transform.name}' to convex.");
                    ((MeshCollider)colliders[i]).convex = true;
                }
            }

            Bounds bounds = colliders[0].bounds;

            for (int i = 1; i < nColliders; i++)
            {
                bounds.Encapsulate(colliders[i].bounds);
            }

            // Round bounds to resolution.
            Vector3Int units = new Vector3Int(
                Mathf.RoundToInt(bounds.size.x / resolution),
                Mathf.RoundToInt(bounds.size.y / resolution),
                Mathf.RoundToInt(bounds.size.z / resolution));

            units       = Vector3Int.Max(units, Vector3Int.one);
            bounds.size = (Vector3)units * resolution;
            // Offset for centering points in grid cells.
            Vector3 offset = bounds.min + Vector3.one * resolution * 0.5f;


            // Early return for single point.

            if (units == Vector3Int.one)
            {
                result = new List <Vector3>[] { new List <Vector3>(1) };
                result[0].Add(matrix.MultiplyPoint3x4(bounds.center));

                return(result);
            }


            // Early return for 2D.

            if (is2D)
            {
                var flat = new Dictionary <Vector2Int, Vector3>(units.x * units.z);

                for (int x = 0; x < units.x; x++)
                {
                    for (int y = 0; y < units.y; y++)
                    {
                        for (int z = 0; z < units.z; z++)
                        {
                            Vector3 p = offset + new Vector3(x, y, z) * resolution;
                            int     n = physicsScene.OverlapSphere(p, scanRadius * resolution / 2f, s_Buffer, mask,
                                                                   QueryTriggerInteraction.UseGlobal);
                            if (n > 0)
                            {
                                for (int i = 0; i < nColliders; i++)
                                {
                                    // Check buffer against colliders, so we don't
                                    // include points inside overlapping colliders
                                    // of neighbouring objects.
                                    if (Array.IndexOf(s_Buffer, colliders[i]) != -1)
                                    {
                                        p.y = bounds.center.y;
                                        flat[new Vector2Int(x, z)] = p;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                result = new List <Vector3>[] { new List <Vector3>(flat.Values) };
                for (int i = 0, n = result[0].Count; i < n; i++)
                {
                    result[0][i] = matrix.MultiplyPoint3x4(result[0][i]);
                }

                return(result);
            }


            // 3D

            int unitMax = Mathf.Max(units.x, units.y, units.z);

            Clear(unitMax);

            // Analyze collider bounds.
            for (int x = 0; x < units.x; x++)
            {
                for (int y = 0; y < units.y; y++)
                {
                    for (int z = 0; z < units.z; z++)
                    {
                        Vector3 p = offset + new Vector3(x, y, z) * resolution;
                        int     n = physicsScene.OverlapSphere(p, scanRadius * resolution / 2f, s_Buffer, mask,
                                                               QueryTriggerInteraction.UseGlobal);
                        if (n > 0)
                        {
                            for (int i = 0; i < nColliders; i++)
                            {
                                // Check buffer against colliders, so we don't
                                // include points inside overlapping colliders
                                // of neighbouring objects.
                                if (Array.IndexOf(s_Buffer, colliders[i]) != -1)
                                {
                                    s_Filled[x, y, z] = true;
                                    s_Sparse[x, y, z] = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            // Reduce point count, hollow out.
            units -= Vector3Int.one;
            for (int x = 1; x < units.x; x++)
            {
                for (int y = 1; y < units.y; y++)
                {
                    for (int z = 1; z < units.z; z++)
                    {
                        s_Sparse[x, y, z] &=
                            !(s_Filled[x - 1, y, z]
                              & s_Filled[x + 1, y, z]
                              & s_Filled[x, y - 1, z]
                              & s_Filled[x, y + 1, z]
                              & s_Filled[x, y, z - 1]
                              & s_Filled[x, y, z + 1]
                              );
                    }
                }
            }

            Vector3 unitCenter = new Vector3(units.x * 0.5f, units.y * 0.5f, units.z * 0.5f);

            units += Vector3Int.one;

            // Detail levels for result.
            int nLevel = Mathf.CeilToInt(Mathf.Log(unitMax, 2)) + 1;
            // Merge points of higher detail levels, see keys below.
            int nMerge = nLevel - 2;

            result = new List <Vector3> [nLevel];
            for (int i = 0; i < nLevel; i++)
            {
                result[i] = new List <Vector3>(); // capacity?
            }

            for (int x = 0; x < units.x; x++)
            {
                for (int y = 0; y < units.y; y++)
                {
                    for (int z = 0; z < units.z; z++)
                    {
                        if (s_Sparse[x, y, z])
                        {
                            Vector3 u = new Vector3(x, y, z);
                            Vector3 p = matrix.MultiplyPoint3x4(offset + u * resolution);
                            result[0].Add(p); // all points, highest detail.

                            u -= unitCenter;  // shift units, e.g. 0 to +8 -> -4 to +4

                            for (int i = 0; i < nMerge; i++)
                            {
                                u *= 0.5f; // half detail.

                                // Keys are tree-like, e.g.
                                // merged[0] 8/6/6 -> centroid -> result[1]
                                // merged[1] 4/3/3 -> centroid -> result[2]
                                // merged[2] 2/1/1 -> centroid -> result[3]
                                // ...
                                // List for each key contains points of prior
                                // level keys/lists, to be averaged for less detail.
                                Vector3Int k = new Vector3Int(
                                    Mathf.FloorToInt(u.x),
                                    Mathf.FloorToInt(u.y),
                                    Mathf.FloorToInt(u.z));

                                if (!s_Merged[i].TryGetValue(k, out IList <Vector3> list))
                                {
                                    list = new List <Vector3>(); // capacity?
                                    s_Merged[i].Add(k, list);
                                }

                                list.Add(p);
                            }
                        }
                    }
                }
            }

            // Calculate centroids.
            for (int i = 0; i < nMerge; i++)
            {
                int j = i + 1;
                foreach (var list in s_Merged[i].Values)
                {
                    Vector3 sum = Vector3.zero;
                    int     n   = list.Count;
                    for (int k = 0; k < n; k++)
                    {
                        sum += list[k];
                    }
                    result[j].Add(sum / n);
                }
            }

            // Single center point for last level.
            result[nLevel - 1].Add(matrix.MultiplyPoint3x4(bounds.center));

            return(result);
        }
示例#3
0
 public int OverlapSphere(Vector3 position, float radius, Collider[] results, int layerMask = Physics3D.AllLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal)
 {
     return(_world.OverlapSphere(position, radius, results, layerMask, queryTriggerInteraction));
 }
示例#4
0
    private IEnumerator ExplosionTimer()
    {
        //Wait set amount of time
        yield return(new WaitForSeconds(grenadeTimer));

        //Raycast downwards to check ground
        // RaycastHit checkGround;
        // if (physicsScene.Raycast(transform.position, Vector3.down, out checkGround, 50))
        // {
        //     //Instantiate metal explosion prefab on ground
        //     Instantiate(explosionPrefab, checkGround.point,
        //         Quaternion.FromToRotation(Vector3.forward, checkGround.normal));
        // }

        //Explosion force
        Vector3 explosionPos = transform.position;

        //Use overlapshere to check for nearby colliders
        Collider[] colliders = new Collider[10];
        int        len       = physicsScene.OverlapSphere(explosionPos, radius, colliders, Physics.AllLayers,
                                                          QueryTriggerInteraction.UseGlobal);

        for (int i = 0; i < len; i++)
        {
            Collider hit = colliders[i];

            Rigidbody rb = hit.GetComponent <Rigidbody>();

            //Add force to nearby rigidbodies
            if (rb != null)
            {
                rb.AddExplosionForce(power * 5, explosionPos, radius, 3.0F);
            }

            //If the explosion hits "Target" tag and isHit is false
            if (hit.GetComponent <Collider>().tag == "Target" &&
                hit.gameObject.GetComponent <TargetScript>().isHit == false)
            {
                //Animate the target
                hit.gameObject.GetComponent <Animation>().Play("target_down");
                //Toggle "isHit" on target object
                hit.gameObject.GetComponent <TargetScript>().isHit = true;
            }

            //If the explosion hits "ExplosiveBarrel" tag
            if (hit.GetComponent <Collider>().tag == "ExplosiveBarrel")
            {
                //Toggle "explode" on explosive barrel object
                hit.gameObject.GetComponent <ExplosiveBarrelScript>().explode = true;
            }

            //If the explosion hits "GasTank" tag
            if (hit.GetComponent <Collider>().tag == "GasTank")
            {
                //Toggle "isHit" on gas tank object
                hit.gameObject.GetComponent <GasTankScript>().isHit = true;
                //Reduce explosion timer on gas tank object to make it explode faster
                hit.gameObject.GetComponent <GasTankScript>().explosionTimer = 0.05f;
            }
        }
        //Destroy the grenade object on explosion
        // Destroy(gameObject);

        // 由服务端来进行手雷的销毁(爆炸)
        if (GetComponent <EntityHold>())
        {
            var entityFlag = GetComponent <EntityHold>();
            if (entityFlag.World.IsServer())
            {
                entityFlag.World.EntityManager.DestroyEntity(entityFlag.Ent);
            }
        }
    }