summaryrefslogtreecommitdiff
path: root/marching/Assets/Scripts/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'marching/Assets/Scripts/Physics')
-rw-r--r--marching/Assets/Scripts/Physics/FastBoxCollider.cs8
-rw-r--r--marching/Assets/Scripts/Physics/PhysicsManager.cs154
-rw-r--r--marching/Assets/Scripts/Physics/PhysicsManager_Collide.cs58
-rw-r--r--marching/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs6
-rw-r--r--marching/Assets/Scripts/Physics/Quadtree.cs5
-rw-r--r--marching/Assets/Scripts/Physics/TestQuadtree.cs4
-rw-r--r--marching/Assets/Scripts/Physics/TestSpirits.cs24
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()