diff options
author | chai <215380520@qq.com> | 2023-05-09 18:52:28 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2023-05-09 18:52:28 +0800 |
commit | 4afa7c36ba9ec33ed113dcfb7cd33bd630d444f2 (patch) | |
tree | ad7260d6a1e84cd1ab56493294301df34d6bb5a6 /marching/Assets/Scripts/Physics | |
parent | f986dc197b5e093575bc0b56ee0ded991c228639 (diff) |
*misc
Diffstat (limited to 'marching/Assets/Scripts/Physics')
7 files changed, 195 insertions, 64 deletions
diff --git a/marching/Assets/Scripts/Physics/FastBoxCollider.cs b/marching/Assets/Scripts/Physics/FastBoxCollider.cs index 03fbb24..df84e0d 100644 --- a/marching/Assets/Scripts/Physics/FastBoxCollider.cs +++ b/marching/Assets/Scripts/Physics/FastBoxCollider.cs @@ -76,7 +76,15 @@ public class FastBoxCollider : MonoBehaviour, IQuadTreeObject private void OnDrawGizmos() { + Color c = Gizmos.color; + + if(m_Type == ColliderType.Hurtbox) + { + Gizmos.color = Color.red; + } Gizmos.DrawWireCube(transform.position + m_Offset.ToVector3(), m_Size.ToVector3()); + + Gizmos.color = c; } }
\ No newline at end of file diff --git a/marching/Assets/Scripts/Physics/PhysicsManager.cs b/marching/Assets/Scripts/Physics/PhysicsManager.cs index c4e6017..bfb1dfe 100644 --- a/marching/Assets/Scripts/Physics/PhysicsManager.cs +++ b/marching/Assets/Scripts/Physics/PhysicsManager.cs @@ -11,116 +11,151 @@ public enum ColliderType Hitbox, } +class PhysicsQuadtree +{ + public Vector4 quadtreeRange { set { m_QuadtreeRange = value; } } + private Vector4 m_QuadtreeRange; + private Quadtree m_Quadtree; + private List<IQuadTreeObject> m_Objects = new List<IQuadTreeObject>(); + + public PhysicsQuadtree(Vector4 range) + { + m_QuadtreeRange = range; + m_Quadtree = new Quadtree(0, range); + } + + public void AddObject(IQuadTreeObject obj) + { + m_Objects.Add(obj); + } + + public void RemoveObject(IQuadTreeObject obj) + { + m_Objects.Remove(obj); + } + + public void UpdateQuadtree() + { + m_Quadtree.Clear(false); + m_Quadtree.Rebound(m_QuadtreeRange); + for (int i = 0; i < m_Objects.Count; i++) + { + IQuadTreeObject obj = m_Objects[i]; + m_Quadtree.Insert(obj); + } + } + + public void Debug() + { + Color c = Gizmos.color; + Gizmos.color = Color.red; + m_Quadtree?.Iterate((t) => + { + Vector3 pos = new Vector3(t.x, t.y, 0); + Vector3 size = new Vector3(t.w, t.h, 1); + Gizmos.DrawWireCube(pos, size); + }); + Gizmos.color = c; + } + + public bool Retrive(ref List<IQuadTreeObject> returnObjs, IQuadTreeObject obj) + { + return m_Quadtree.Retrieve(ref returnObjs, obj); + } + + public bool Retrive(ref List<IQuadTreeObject> returnObjs, Vector4 bound) + { + return m_Quadtree.Retrieve(ref returnObjs, bound); + } + +} + /// <summary> /// 四叉树空间划分,优化碰撞检测 /// </summary> public partial class PhysicsManager : Singleton<PhysicsManager> { #region Quadtrees - public Vector4 quadtreeCollisionRange { set { m_QuadtreeCollisionRange = value; } } - private Vector4 m_QuadtreeCollisionRange; - private Quadtree m_QuadtreeCollision; - private List<IQuadTreeObject> m_QuadtreeObjColliders = new List<IQuadTreeObject>(); - - public Vector4 quadtreeHurtboxRange { set { m_QuadtreeHurtboxRange = value; } } - private Vector4 m_QuadtreeHurtboxRange; - private Quadtree m_QuadtreeHurtboxes; - private List<IQuadTreeObject> m_QuadtreeObjHurtboxes = new List<IQuadTreeObject>(); - #endregion + private PhysicsQuadtree m_CollisionQuadtree; + private PhysicsQuadtree m_HurtboxQuadtree; + #endregion + + public Vector4 collisionQuadtreeRange + { + set + { + m_CollisionQuadtree.quadtreeRange = value; + } + } + + public Vector4 hurtboxQuadtreeRange + { + set + { + m_HurtboxQuadtree.quadtreeRange = value; + } + } + public List<IQuadTreeObject> sharedRetriveResults => m_SharedRetriveResults; private List<IQuadTreeObject> m_SharedRetriveResults = new List<IQuadTreeObject>(); public PhysicsManager() { - m_QuadtreeCollision = new Quadtree(0, new Vector4(0, 0, 30, 30)); - m_QuadtreeHurtboxes= new Quadtree(0, new Vector4(0,0, 30, 30)); + m_CollisionQuadtree = new PhysicsQuadtree(new Vector4(0, 0, 30, 30)); + m_HurtboxQuadtree = new PhysicsQuadtree(new Vector4(0, 0, 30, 30)); } public void AddCollider(IQuadTreeObject collider) { - m_QuadtreeObjColliders.Add(collider); + m_CollisionQuadtree.AddObject(collider); } public void RemoveCollider(IQuadTreeObject collider) { - m_QuadtreeObjColliders.Remove(collider); + m_CollisionQuadtree.RemoveObject(collider); } public void AddHurtboxes(IQuadTreeObject hurtbox) { - m_QuadtreeObjHurtboxes.Add(hurtbox); + m_HurtboxQuadtree.AddObject(hurtbox); } public void RemoveHurtbox(IQuadTreeObject hurtbox) { - m_QuadtreeObjHurtboxes.Remove(hurtbox); - } - - public void UpdateQuadtreeCollision() - { - m_QuadtreeCollision.Clear(false); - m_QuadtreeCollision.Rebound(m_QuadtreeCollisionRange); - for (int i = 0; i < m_QuadtreeObjColliders.Count; i++) - { - IQuadTreeObject obj = m_QuadtreeObjColliders[i]; - m_QuadtreeCollision.Insert(obj); - } - } - - public void UpdateQuadtreeHurtbox() - { - m_QuadtreeHurtboxes.Clear(false); - m_QuadtreeHurtboxes.Rebound(m_QuadtreeHurtboxRange); - for (int i = 0; i < m_QuadtreeObjHurtboxes.Count; i++) - { - IQuadTreeObject obj = m_QuadtreeObjHurtboxes[i]; - m_QuadtreeHurtboxes.Insert(obj); - } + m_HurtboxQuadtree.RemoveObject(hurtbox); } public void Update() { - UpdateQuadtreeCollision(); - UpdateQuadtreeHurtbox(); - } - - public void Debug() - { - Color c = Gizmos.color; - Gizmos.color = Color.red; - m_QuadtreeCollision?.Iterate((t) => { - Vector3 pos = new Vector3(t.x, t.y, 0); - Vector3 size = new Vector3(t.w, t.h, 1); - Gizmos.DrawWireCube(pos, size); - }); - Gizmos.color = c; + m_CollisionQuadtree.UpdateQuadtree(); + m_HurtboxQuadtree.UpdateQuadtree(); } public bool RetriveColliders(ref List<IQuadTreeObject> returnObjs, IQuadTreeObject obj) { - return m_QuadtreeCollision.Retrieve(ref returnObjs, obj); + return m_CollisionQuadtree.Retrive(ref returnObjs, obj); } public bool RetriveColliders(ref List<IQuadTreeObject> returnObjs, Vector4 bound) { - return m_QuadtreeCollision.Retrieve(ref returnObjs, bound); + return m_CollisionQuadtree.Retrive(ref returnObjs, bound); } public bool RetriveHurtboxes(ref List<IQuadTreeObject> returnObjs, Vector4 bound) { - return m_QuadtreeHurtboxes.Retrieve(ref returnObjs, bound); + return m_HurtboxQuadtree.Retrive(ref returnObjs, bound); } public bool RetriveColliders(Vector4 bound) { m_SharedRetriveResults.Clear(); - return m_QuadtreeCollision.Retrieve(ref m_SharedRetriveResults, bound); + return m_CollisionQuadtree.Retrive(ref m_SharedRetriveResults, bound); } public bool RetriveHurtboxes(Vector4 bound) { m_SharedRetriveResults.Clear(); - return m_QuadtreeHurtboxes.Retrieve(ref m_SharedRetriveResults, bound); + return m_HurtboxQuadtree.Retrive(ref m_SharedRetriveResults, bound); } public System.Func<Vector4, bool> GetRetriverByType(ColliderType type) @@ -133,4 +168,9 @@ public partial class PhysicsManager : Singleton<PhysicsManager> return null; } + public void Debug() + { + m_CollisionQuadtree.Debug(); + } + }
\ No newline at end of file diff --git a/marching/Assets/Scripts/Physics/PhysicsManager_Collide.cs b/marching/Assets/Scripts/Physics/PhysicsManager_Collide.cs index 48af516..7b4aa1c 100644 --- a/marching/Assets/Scripts/Physics/PhysicsManager_Collide.cs +++ b/marching/Assets/Scripts/Physics/PhysicsManager_Collide.cs @@ -19,6 +19,27 @@ public partial class PhysicsManager : Singleton<PhysicsManager> return box; } + public Vector4 GetRayBound(Vector4 line, float maxLen=20f) + { + Vector2 tr = line.xy() + maxLen * line.zw().normalized; + Vector4 bound = new Vector4(); + bound.x = (tr.x + line.x) / 2; + bound.y = (tr.y + line.y) / 2; + bound.z = Mathf.Abs(tr.x - line.x); + bound.w = Mathf.Abs(tr.y - line.y); + return bound; + } + + public Vector4 GetPointBound(Vector2 point) + { + Vector4 bound = new Vector4(); + bound.x = point.x; + bound.y = point.y; + bound.z = 1; + bound.w = 1; + return bound; + } + public ref readonly List<IQuadTreeObject> CircleCast(ColliderType target, Vector3 circle) { m_SharedCollideResults.Clear(); @@ -55,10 +76,45 @@ public partial class PhysicsManager : Singleton<PhysicsManager> public ref readonly List<IQuadTreeObject> BoxCast(ColliderType target, Vector4 box) { + m_SharedCollideResults.Clear(); + var retriver = GetRetriverByType(target); + if (retriver != null) + { + if (retriver(GetBoxBound(box))) + { + for (int i = 0; i < m_SharedRetriveResults.Count; ++i) + { + var collider = m_SharedRetriveResults[i]; + if (collider != null) + { + if (collider is FastCircleCollider) + { + if (BoxVsCircle(box, (collider as FastCircleCollider).circle)) + { + m_SharedCollideResults.Add(collider); + } + } + else if (collider is FastBoxCollider) + { + if (BoxVsBox(box, (collider as FastBoxCollider).box)) + { + m_SharedCollideResults.Add(collider); + } + } + } + } + } + } return ref m_SharedCollideResults; } - public ref readonly List<IQuadTreeObject> LineCast(ColliderType target, Vector4 line) + /// <summary> + /// x,y dir.x dir.y + /// </summary> + /// <param name="target"></param> + /// <param name="line"></param> + /// <returns></returns> + public ref readonly List<IQuadTreeObject> RayCast(ColliderType target, Vector4 ray, float maxLength = 20f) { return ref m_SharedCollideResults; } diff --git a/marching/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs b/marching/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs index 81625ac..3436a34 100644 --- a/marching/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs +++ b/marching/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs @@ -46,6 +46,12 @@ public partial class PhysicsManager : Singleton<PhysicsManager> return false; } + public static bool BoxVsBox(Vector4 b1, Vector4 b2) + { + Vector2 intersection = new Vector2(); + return BoxVsBox(b1, b2, out intersection); + } + public static bool BoxVsCircle(Vector4 box, Vector2 pos, float radius) { Vector4 boxScaled = box; diff --git a/marching/Assets/Scripts/Physics/Quadtree.cs b/marching/Assets/Scripts/Physics/Quadtree.cs index 4185f1f..f1237ab 100644 --- a/marching/Assets/Scripts/Physics/Quadtree.cs +++ b/marching/Assets/Scripts/Physics/Quadtree.cs @@ -8,6 +8,8 @@ using System.Runtime.InteropServices.WindowsRuntime; using Unity.VisualScripting; using UnityEngine; +// https://gamedev.stackexchange.com/questions/6345/quad-tree-vs-grid-based-collision-detection + namespace mh { @@ -16,6 +18,9 @@ namespace mh public Vector4 bound { get; } } + /// <summary> + /// 四叉树空间分割 + /// </summary> public class Quadtree { public const int kMaxObjectsPerBlock = 5; diff --git a/marching/Assets/Scripts/Physics/TestQuadtree.cs b/marching/Assets/Scripts/Physics/TestQuadtree.cs index 1cbb64d..54ff5f6 100644 --- a/marching/Assets/Scripts/Physics/TestQuadtree.cs +++ b/marching/Assets/Scripts/Physics/TestQuadtree.cs @@ -18,8 +18,8 @@ namespace mh private void FixedUpdate() { var pos = UnitManager.hero.transform.position; - PhysicsManager.Instance.quadtreeCollisionRange = new Vector4(pos.x, pos.y, 50, 50); - PhysicsManager.Instance.quadtreeHurtboxRange = new Vector4(pos.x, pos.y, 50, 50); + PhysicsManager.Instance.collisionQuadtreeRange = new Vector4(pos.x, pos.y, 50, 50); + PhysicsManager.Instance.hurtboxQuadtreeRange = new Vector4(pos.x, pos.y, 50, 50); PhysicsManager.Instance.Update(); } diff --git a/marching/Assets/Scripts/Physics/TestSpirits.cs b/marching/Assets/Scripts/Physics/TestSpirits.cs index 347fc42..058f166 100644 --- a/marching/Assets/Scripts/Physics/TestSpirits.cs +++ b/marching/Assets/Scripts/Physics/TestSpirits.cs @@ -13,20 +13,36 @@ public class TestSpirits : MonoBehaviour // Start is called before the first frame update void Start() { - - for (int i = 0; i < 300; ++i) + int count = 300 - spirits.Count; + for (int i = 0; i < count; ++i) { float x = UnityEngine.Random.Range(-20, 10); float y = UnityEngine.Random.Range(-20, 10); SpiritScript go = Instantiate(prefab) as SpiritScript; go.transform.position = new Vector3(x, y, 0); go.transform.parent = this.transform; + go.gameObject.SetActive(true); } + StartCoroutine(CoSpawn(5)); } - // Update is called once per frame - void Update() + IEnumerator CoSpawn(float interval) { + while (true) + { + int count = 300 - spirits.Count; + for (int i = 0; i < count; ++i) + { + float x = UnityEngine.Random.Range(-20, 10); + float y = UnityEngine.Random.Range(-20, 10); + SpiritScript go = Instantiate(prefab) as SpiritScript; + go.transform.position = new Vector3(x, y, 0); + go.transform.parent = this.transform; + go.gameObject.SetActive(true); + } + + yield return new WaitForSeconds(interval); + } } private void FixedUpdate() |