// 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); }
/// <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); }
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)); }
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); } } }