From 7aa8798b8400dd111730cf0d4415f1d02160ca4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B3=A0=E6=BC=AA?= <32807696+AngelShadow2017@users.noreply.github.com> Date: Wed, 9 Apr 2025 05:47:46 +0800 Subject: [PATCH 1/9] collidermodifications --- .../.idea/.gitignore | 13 + .../.idea/encodings.xml | 4 + .../.idea/indexLayout.xml | 8 + .../.idea.something_jobLearning/.idea/vcs.xml | 6 + Assets/ColliderObj.cs | 1620 +++++++++++++++++ Assets/ColliderObj.cs.meta | 2 + Assets/ColliderStructure.cs | 378 ++++ Assets/ColliderStructure.cs.meta | 3 + Assets/HashTypeHelpers.cs | 458 +++++ Assets/HashTypeHelpers.cs.meta | 2 + Assets/JobsTesting.cs | 80 +- Assets/PoolingManager.cs | 47 + Assets/PoolingManager.cs.meta | 2 + Assets/Scenes/SampleScene.unity | 32 +- Assets/TrueSync/Fix64.cs | 2 + Assets/TrueSync/Fuck.cs | 8 + Assets/TrueSync/Fuck.cs.meta | 3 + Assets/TrueSync/TSVector2.cs | 34 +- Assets/math.cs | 511 ++++++ Assets/math.cs.meta | 2 + Assets/tmpExtensions.cs | 45 + Assets/tmpExtensions.cs.meta | 3 + .../BurstAotSettings_StandaloneWindows.json | 18 + ProjectSettings/CommonBurstAotSettings.json | 6 + ProjectSettings/SceneTemplateSettings.json | 121 ++ 25 files changed, 3378 insertions(+), 30 deletions(-) create mode 100644 .idea/.idea.something_jobLearning/.idea/.gitignore create mode 100644 .idea/.idea.something_jobLearning/.idea/encodings.xml create mode 100644 .idea/.idea.something_jobLearning/.idea/indexLayout.xml create mode 100644 .idea/.idea.something_jobLearning/.idea/vcs.xml create mode 100644 Assets/ColliderObj.cs create mode 100644 Assets/ColliderObj.cs.meta create mode 100644 Assets/ColliderStructure.cs create mode 100644 Assets/ColliderStructure.cs.meta create mode 100644 Assets/HashTypeHelpers.cs create mode 100644 Assets/HashTypeHelpers.cs.meta create mode 100644 Assets/PoolingManager.cs create mode 100644 Assets/PoolingManager.cs.meta create mode 100644 Assets/TrueSync/Fuck.cs create mode 100644 Assets/TrueSync/Fuck.cs.meta create mode 100644 Assets/math.cs create mode 100644 Assets/math.cs.meta create mode 100644 Assets/tmpExtensions.cs create mode 100644 Assets/tmpExtensions.cs.meta create mode 100644 ProjectSettings/BurstAotSettings_StandaloneWindows.json create mode 100644 ProjectSettings/CommonBurstAotSettings.json create mode 100644 ProjectSettings/SceneTemplateSettings.json diff --git a/.idea/.idea.something_jobLearning/.idea/.gitignore b/.idea/.idea.something_jobLearning/.idea/.gitignore new file mode 100644 index 0000000..728bffe --- /dev/null +++ b/.idea/.idea.something_jobLearning/.idea/.gitignore @@ -0,0 +1,13 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# Rider 忽略的文件 +/modules.xml +/contentModel.xml +/projectSettingsUpdater.xml +/.idea.something_jobLearning.iml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.something_jobLearning/.idea/encodings.xml b/.idea/.idea.something_jobLearning/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.something_jobLearning/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.something_jobLearning/.idea/indexLayout.xml b/.idea/.idea.something_jobLearning/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.something_jobLearning/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.something_jobLearning/.idea/vcs.xml b/.idea/.idea.something_jobLearning/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/.idea.something_jobLearning/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Assets/ColliderObj.cs b/Assets/ColliderObj.cs new file mode 100644 index 0000000..5dc5eb8 --- /dev/null +++ b/Assets/ColliderObj.cs @@ -0,0 +1,1620 @@ +using System; +using System.Collections.Generic; +using TrueSync; +using UnityEngine; +using UnityEngine.Pool; +using ZeroAs.DOTS.Colliders; + +namespace Core.Algorithm +{ + public interface ICollideShape { + public ref ColliderStructure Collider { get; } + //获取在某个方向上的最远点 + public TSVector2 GetFurthestPoint(in TSVector2 direction); + //设置该形状的旋转角 + public void SetRotation(FP rotRad); + public void SetCenter(in TSVector2 center); + public TSVector2 GetCenter(); + //左上点和右下点!!! + public TSVector4 GetBoundingBox(); + public CollisionManager.CollisionGroup colliGroup { get; set; } + public bool enabled { get; set; } + public void DebugDisplayColliderShape(Color color); + } + public interface IMasteredCollider + { + public T Master { get; set; } + } + [Serializable] + public abstract class ColliderBase : ICollideShape + { + public ColliderStructure collider; + + public ref ColliderStructure Collider => ref collider; + protected CollisionManager.CollisionGroup __colli__ = CollisionManager.CollisionGroup.Default; + protected bool __enabled__ = true; + public int tag = -1;//用来识别特定的tag + public CollisionManager.CollisionGroup colliGroup { + get + { + return __colli__; + } + set + { + __colli__ = value; + } + } + public bool enabled + { + get + { + return __enabled__; + } + set + { + __enabled__ = value; + } + } + + static TSVector2 SupportFunc(ColliderBase shape1,ColliderBase shape2,TSVector2 direciton) { + //Debug.Log("direction: "+direciton+" "+ shape1.GetFurthestPoint(direciton)+" "+shape2.GetFurthestPoint(-direciton)); + return shape1.GetFurthestPoint(direciton) - shape2.GetFurthestPoint(-direciton); + } + static TSVector2 TripleProduct2d(TSVector2 a,TSVector2 b,TSVector2 c) { + FP sign = (a.x * b.y - a.y * b.x); + return new TSVector2(-c.y, c.x) * sign; + } + public abstract TSVector4 GetBoundingBox(); + public TSVector2 GetFurthestPoint(in TSVector2 direction) + { + GetFurthestPointExtensions.GetFurthestPoint(out var result, collider, direction); + return result; + } + public abstract void SetRotation(FP rotRad); + public abstract void SetCenter(in TSVector2 center); + public abstract TSVector2 GetCenter(); + public static bool CheckCollide(ColliderBase shape1, ColliderBase shape2) { + /* + #两个形状s1,s2相交则返回True。所有的向量/点都是二维的,例如([x,y]) + #第一步:选择一个初始方向,这个初始方向可以是随机选择的,但通常来说是两个形状中心之间的向量,即: + + */ + TSVector2 direction = (shape2.GetCenter() - shape1.GetCenter()).normalized; + //#第二步:找到支撑点,即第一个支撑点(即闵可夫斯基差的边上的点之一……) + TSVector2[] Simplex = new TSVector2[3];//单纯形数组,最多只能是3个 + Simplex[0] = SupportFunc(shape1, shape2, direction); + int simplexLastInd = 1; + int interateTimeMax = 100;//最大迭代次数 + //#第三步:找到第一个支撑点后,以第一个支撑点为起点指向原点O的方向为新方向d + direction = -Simplex[0].normalized; + //#第四步:开始循环,找下一个支撑点 + while (interateTimeMax-- > 0) + { + TSVector2 A = SupportFunc(shape1,shape2,direction); + //因为A点是闵可夫斯基差形状在给定方向的最远点,如果那个点没有超过原点,就不想交 + //#当新的支撑点A没有包含原点,那我们就返回False,即两个形状没有相交 + if (TSVector2.Dot(A,direction)<0) { + return false; + } + Simplex[simplexLastInd++] = A; + //Debug.Log("input: "+A+shape1.GetType()+" "+shape2.GetType()); + //处理为线段的情况 + if (simplexLastInd == 2) + { + //三维的处理方式 + /* + TSVector AB = Simplex[simplexLastInd-2] - Simplex[simplexLastInd - 1]; + TSVector AO = -Simplex[simplexLastInd-1]; + TSVector ABPrep = TSVector.Cross(TSVector.Cross(AB, AO),AB);//垂直于AB的那个点! + */ + //在2d里面可以这么简化 + TSVector2 AB = Simplex[simplexLastInd - 2] - Simplex[simplexLastInd - 1]; + TSVector2 AO = -Simplex[simplexLastInd - 1]; + TSVector2 ABPrep = TripleProduct2d(AB,AO,AB); + direction = ABPrep.normalized; + /* + * A是最新插入的点,B是第一次插入的点 + 当我们拥有两个点时,我们怎么选择新的方向? + 1. 构建向量: + o 构建向量 𝐴𝑂(从点A到原点O),即 𝐴𝑂=𝑂−𝐴 + o 构建向量 𝐴𝐵(从点A到点B),即 𝐴𝐵=𝐵−𝐴 + 2. 求解垂直向量: + o 通过叉积 𝐴𝐵×𝐴𝑂,我们可以得到一个垂直于这两个向量的向量。这个向量垂直于 𝐴𝐵 和 𝐴𝑂 所在的平面,并且指向由右手定则决定的方向。 + 3. 求解新的方向: + o 为了得到新的方向 𝑑,我们需要一个向量,这个向量既垂直于 𝐴𝐵×𝐴𝑂,又垂直于 𝐴𝐵。这可以通过三重积来实现,即: + 𝑑=(𝐴𝐵×𝐴𝑂)×𝐴𝐵 + 这个三重积的结果是一个向量,它垂直于 𝐴𝐵 和 𝐴𝐵×𝐴𝑂 所在的平面。换句话说,它是垂直于 𝐴𝐵 的并且指向原点的可能性最大。 + + 简单来说:通过选择垂直于 𝐴𝐵 的方向,我们可以在最有可能包含原点的方向上进行搜索,从而提高搜索效率。 + */ + } + else//处理为三角形的情况 + { + //C是单纯形第一次插入的元素,B是第二次插入的,A是最后插入的 + //构建向量AB,AC与AO,并来检测原点在空间的哪个沃罗诺伊区域(通过排除法可以知道肯定在AB或AC或ABC三角形内部区域) + TSVector2 AC = Simplex[simplexLastInd - 3] - Simplex[simplexLastInd - 1]; + TSVector2 AB = Simplex[simplexLastInd - 2] - Simplex[simplexLastInd - 1]; + TSVector2 AO = -Simplex[simplexLastInd - 1]; + //#通过三重积 分别得到垂直于AB、AC转向特定方向的的向量,检测区域Rab、Rac中是否包含原点。 + TSVector2 ABPrep = TripleProduct2d(AC, AB, AB).normalized; + TSVector2 ACPrep = TripleProduct2d(AB, AC, AC).normalized; + //Debug.Log(ABPrep+" "+ACPrep+" "+AC+" "+AB+" "+AO); + //#如果原点在AB区域中,我们移除点C以寻找更加完美的simplex(C离原点最远),新的方向就是垂直于AB的向量 + if (TSVector2.Dot(ABPrep, AO) > 0) + { + for (int i = 1; i < 3; i++) + { + Simplex[i - 1] = Simplex[i]; + }//删除数组首个元素(C点),当前的单纯形并不包含原点, + simplexLastInd--; + direction = ABPrep; + } else if (TSVector2.Dot(ACPrep, AO) > 0) { + //#如果原点在AC区域中,我们移除点B以寻找更加完美的simplex,新的方向就是垂直于AC的向量 + Simplex[simplexLastInd - 2] = Simplex[simplexLastInd-1]; + simplexLastInd--; + direction = ACPrep; + } + else + { + //否则单纯形包含原点,碰到了 + return true; + } + } + } + //如果超过迭代次数都没有找到点,则判定为没有碰到。 + return false; + } + public virtual bool CheckCollide(ColliderBase shape2) { + return CheckCollide(this, shape2); + } + public virtual void DebugDisplayColliderShape(Color color) { } + } + [Serializable] + public abstract class ColliderBase : ColliderBase + { + public T Master; + } + [Serializable] + public class CircleCollider : ColliderBase + { + public CircleCollider(FP R,TSVector2 center,CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) + { + Collider = new ColliderStructure() + { + colliderType = ColliderType.Circle, + radius = R, + center = center + }; + + colliGroup = group; + } + public override void SetRotation(FP rotRad) { }//没错,圆形没有旋转 + public override void SetCenter(in TSVector2 center) + { + Collider.center = center; + } + public override TSVector2 GetCenter() + { + return Collider.center; + } + /*public override TSVector2 GetFurthestPoint(in TSVector2 direction) + { + GetFurthestPointExtensions.GetFurthestPoint(out var result, this.Collider, direction); + return result; + }*/ + public override TSVector4 GetBoundingBox() + { + TSVector2 centerPos = GetCenter(); + FP r = this.Collider.radius; + return new TSVector4(centerPos.x-r,centerPos.y+r,centerPos.x+r,centerPos.y-r); + } + bool CircleCollideWithCircle(CircleCollider shape2) + { + return CollideExtensions.CircleCollideWithCircle(this.Collider,shape2.Collider); + } + public override bool CheckCollide(ColliderBase shape2) + { + if(shape2 is CircleCollider sh) + { + return CircleCollideWithCircle(sh); + }else if(shape2 is DoubleCircleCollider d) + { + + //Debug.Log(d.CircleCollideWithCircle(this)); + return d.CircleCollideWithCircle(this); + } + return CheckCollide(this, shape2); + } + public override void DebugDisplayColliderShape(Color color) + { + float r = (float)collider.radius; + int circleCount = Mathf.FloorToInt(Mathf.Lerp(5,8,((float)r)/72f)); + float angleDelta = 2 * Mathf.PI / circleCount; + + GL.Begin(GL.TRIANGLE_STRIP); + GL.Color(color); + + for (int i = 0; i < circleCount + 1; i++) + { + float angle = angleDelta * i; + float angleNext = angle + angleDelta; + Vector3 cent = GetCenter().ToVector(); + Vector3 cent2 = new Vector3(Mathf.Cos(angle) * (float)r, Mathf.Sin(angle) * (float)r, 0) + cent; + GL.Vertex3(cent2.x,cent2.y,cent2.z); + GL.Vertex3(cent.x,cent.y,cent.z); + } + + GL.End(); + } + } + [Serializable] + public class CircleCollider : CircleCollider,IMasteredCollider + { + T _master_; + public T Master { + get => _master_; + set => _master_ = value; + } + + public CircleCollider(T master,FP R, TSVector2 center, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) : base(R, center, group) + { + this._master_ = master; + } + + } + [Serializable] + public class OvalCollider : ColliderBase + { + //public FP rot, b2Dividea2;//旋转,长轴方除以短轴方,因为定点数除法……真的太慢了。。。 + //public TSVector2 Axis,SqrAxis;//半长轴和半短轴?其实应该叫水平轴和竖直轴 + //TSVector2 centerPos; + public OvalCollider(TSVector2 axis, TSVector2 center,in FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) + { + collider = new ColliderStructure() + { + colliderType = ColliderType.Oval, + rot = rotation, + center = center + }; + SetAxis(axis); + colliGroup = group; + } + public void SetAxis(TSVector2 axis) { + collider.Axis = axis; + collider.SqrAxis = new TSVector2(TSMath.FastQuadratic(axis.x), TSMath.FastQuadratic(axis.y)); + if (collider.SqrAxis.x == 0) + { + collider.b2Dividea2 = FP.MaxValue; + } + else + { + collider.b2Dividea2 = collider.SqrAxis.y / collider.SqrAxis.x; + } + } + public override void SetRotation(FP rotRad) { + collider.rot = rotRad; + }//没错,圆形没有旋转 + public override void SetCenter(in TSVector2 center) + { + collider.center = center; + } + public override TSVector2 GetCenter() + { + return collider.center; + } + /*public override TSVector2 GetFurthestPoint(in TSVector2 direction) + { + + //sin和cos还是很快的,因为是线性插值……有Lut + direction = direction.RotateRad(-rot); + if (direction.x == 0) + { + return (TSMath.Sign(direction.y)*Axis.y * TSVector2.up).RotateRad(rot) + centerPos; + }else if (direction.y == 0) + { + return (TSMath.Sign(direction.x) * Axis.x * TSVector2.right).RotateRad(rot) + centerPos; + } + FP signX = TSMath.Sign(direction.x); + FP k = direction.y / direction.x;//目标斜率 + FP a2 = SqrAxis.x; + FP b2 = SqrAxis.y; + FP ratio = FP.OverflowMul(k, b2Dividea2); + FP denominator = FP.OverflowAdd(1, FP.OverflowMul(k, ratio)); + if (denominator >= FP.MaxValue || denominator <= FP.MinValue) + { + //Debug.Log("denominatorOverflow "+ direction + " "+ new TSVector2(0, TSMath.Sign(direction.y) * Axis.y).RotateRad(rot)); + return new TSVector2(0, TSMath.Sign(direction.y) * Axis.y).RotateRad(rot) + centerPos; + } + FP value = 1.0/denominator; + + FP tarX = signX * (Axis.x*TSMath.Sqrt(value)); + FP tarY = FP.OverflowMul(tarX,ratio); + //Debug.Log("ovalthings: "+tarX+" "+tarY+" "+k+" "+ratio); + if (tarY >= FP.MaxValue||tarY<=FP.MinValue) + { + return new TSVector2(0, TSMath.Sign(direction.y)*Axis.y).RotateRad(rot) + centerPos; + } + return new TSVector2(tarX,tarY).RotateRad(rot)+centerPos; + }*/ + //椭圆的包围盒超级难算,懒了,就这样吧。 + public override TSVector4 GetBoundingBox() + { + FP maxBorder = TSMath.Max(collider.Axis.x, collider.Axis.y); + return new TSVector4(collider.center.x - collider.Axis.x, collider.center.y + collider.Axis.x, collider.center.x + collider.Axis.x, collider.center.y - collider.Axis.x); + } + public override void DebugDisplayColliderShape(Color color) + { + int circleCount = Mathf.FloorToInt(Mathf.Lerp(16, 32, ((float)collider.Axis.x) / 72f)); + Vector2 size = collider.Axis.ToVector(); + Vector3 cent = collider.center.ToVector(); + float rotRad = ((float)collider.rot); + GL.Begin(GL.TRIANGLE_STRIP); + GL.Color(color); + float angleDelta = 2 * Mathf.PI / circleCount; + for (int i = 0; i < circleCount + 1; i++) + { + float angle = angleDelta * i; + float angleNext = angle + angleDelta; + Vector2 cent2 = new Vector2(Mathf.Cos(angle) * size.x, Mathf.Sin(angle) * size.y); + cent2 = cent2.RotateRad(rotRad); + GL.Vertex3(cent2.x+cent.x, cent2.y + cent.y, cent.z); + GL.Vertex3(cent.x, cent.y, cent.z); + } + GL.End(); + } + } + [Serializable] + public class OvalCollider : OvalCollider, IMasteredCollider + { + T _master_; + public T Master + { + get => _master_; + set => _master_ = value; + } + + public OvalCollider(T master, TSVector2 axis, TSVector2 center, FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) : base(axis, center,rotation, group) + { + this._master_ = master; + } + + } + [Serializable] + public class PolygonCollider : ColliderBase + { + public FP rot; + public TSVector2[] vertexs,movedVertexs; + public TSVector2 centerPos; + TSVector4 _boundingBox_=TSVector4.zero; + public PolygonCollider() { + + //throw new System.NotImplementedException("必须为顶点赋值"); + } + public PolygonCollider(TSVector2[] vertex, TSVector2 center, FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) + { + movedVertexs = new TSVector2[vertex.Length]; //边数是不能变的 + centerPos = center; + SetRotation(rotation); + colliGroup = group; + } + public override void SetRotation(FP rotRad) + { + rot = rotRad; + RotateVertexs(); + }//没错,圆形没有旋转 + public override void SetCenter(in TSVector2 center) + { + MoveDeltaPos(center-centerPos); + centerPos = center; + } + public override TSVector2 GetCenter() + { + return centerPos; + } + void RotateVertexs() + { + TSVector4 tSVector4 = new TSVector4(FP.MaxValue, FP.MinValue, FP.MinValue, FP.MaxValue); + for (int i = movedVertexs.Length - 1; i >= 0; --i) + { + movedVertexs[i] = vertexs[i].RotateRad(rot) + centerPos; + if (movedVertexs[i].x > tSVector4.z) + { + tSVector4.z= movedVertexs[i].x; + } + if (movedVertexs[i].x < tSVector4.x) + { + tSVector4.x = movedVertexs[i].x; + } + if (movedVertexs[i].y > tSVector4.y) + { + tSVector4.y = movedVertexs[i].y;//最大值,代表上方点 + } + if (movedVertexs[i].y < tSVector4.w) + { + tSVector4.w = movedVertexs[i].y;//最小值,代表下方点 + } + } + _boundingBox_ = tSVector4; + } + void MoveDeltaPos(TSVector2 pos) + { + for (int i = movedVertexs.Length - 1; i >= 0; --i) + { + movedVertexs[i] += pos; + } + _boundingBox_.x += pos.x; + _boundingBox_.y += pos.y; + _boundingBox_.z += pos.x; + _boundingBox_.w += pos.y; + } + public override TSVector2 GetFurthestPoint(TSVector2 direction) + { + direction = direction.normalized; + FP maxLen = FP.MinValue,len; + TSVector2 pos = movedVertexs[0]; + for(int i = movedVertexs.Length-1; i >= 0; --i) + { + if((len= TSVector2.Dot(direction, movedVertexs[i])) > maxLen) + { + maxLen = len; + pos = movedVertexs[i]; + } + } + return pos; + } + + public override TSVector4 GetBoundingBox() + { + return _boundingBox_; + } + } + [Serializable] + public class BoxCollider : PolygonCollider + { + public BoxCollider(TSVector2 widthHeight,TSVector2 center,FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) + { + TSVector2 a = widthHeight * 0.5;//左下,左上,右上,右下 + TSVector2 b = new TSVector2(a.x,-a.y); + vertexs = new TSVector2[4] {-a,-b, a, b}; //边数是不能变的 + movedVertexs = new TSVector2[4]; //边数是不能变的 + centerPos = center; + SetRotation(rotation); + colliGroup = group; + + } + public override void DebugDisplayColliderShape(Color color) + { + + GL.Begin(GL.TRIANGLE_STRIP); + GL.Color(color); + //因为原来是顺时针的,现在反过来,变成逆时针画图 + for (int i = movedVertexs.Length-1; i >= 0; i--) + { + GL.Vertex(movedVertexs[i].ToVector()); + } + + GL.End(); + } + } + [Serializable] + public class BoxCollider : BoxCollider, IMasteredCollider + { + T _master_; + public T Master + { + get => _master_; + set => _master_ = value; + } + + public BoxCollider(T master, TSVector2 widthHeight, TSVector2 center, FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) : base(widthHeight, center, rotation, group) + { + this._master_ = master; + } + + } + [Serializable] + public class DiamondCollider : PolygonCollider + { + public DiamondCollider(TSVector2 widthHeight, TSVector2 center, FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) + { + TSVector2 b = new TSVector2(widthHeight.x * 0.5, 0); + TSVector2 c = new TSVector2(0, widthHeight.y * 0.5); + vertexs = new TSVector2[4] { -b, c, b, -c }; //边数是不能变的 + movedVertexs = new TSVector2[4]; //边数是不能变的 + centerPos = center; + SetRotation(rotation); + colliGroup = group; + } + + } + [Serializable] +//两个相同的圆中间连线 + public class DoubleCircleCollider : ColliderBase + { + public FP r; + protected TSVector2 centerPos; + public TSVector2 centerCircle1; + public TSVector2 centerCircle2; + public DoubleCircleCollider(FP R, TSVector2 center1,TSVector2 center2, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) + { + SetCircleCenters(center1,center2); + r = R; + colliGroup = group; + } + public override void SetRotation(FP rotRad) { }//没错,圆形没有旋转 + public override void SetCenter(in TSVector2 center) + { + TSVector2 delta = center - centerPos; + centerCircle1 += delta; + centerCircle2 += delta; + centerPos = center; + } + public void SetCircleCenters(TSVector2 center1,TSVector2 center2) { + + centerCircle1 = center1; + centerCircle2 = center2; + centerPos = (center1 + center2) * 0.5; + } + public void SetCircleCenter2(TSVector2 center2) + { + centerCircle2 = center2; + centerPos = (centerCircle1 + center2) * 0.5; + } + public void SetCircleCenter1(TSVector2 center1) + { + centerCircle1 = center1; + centerPos = (centerCircle2 + center1) * 0.5; + } + public override TSVector2 GetCenter() + { + return centerPos; + } + public override TSVector2 GetFurthestPoint(TSVector2 direction) + { + //d.normal* + if (TSVector2.Dot(direction, centerCircle1-centerPos) > 0) + { + return direction.normalized * r + centerCircle1; + } + else + { + return direction.normalized * r + centerCircle2; + } + } + public override TSVector4 GetBoundingBox() + { + FP minX; + FP minY; + FP maxX; + FP maxY; + if (centerCircle1.x halfLen+r+shape2.r) { + //Debug.Log("Type1: "+distance + " " + (this.r + shape2.r) + " " + halfLen); + return false; + } + if (absDis >= halfLen) + { + //Debug.Log("Type2: " + distance + " "+ centerShape + " " + this.centerCircle2+ " " + this.centerCircle1 + " " + (this.r + shape2.r) + " " + halfLen); + if (distance > 0) + { + return (this.centerCircle2 - centerShape).LengthSquared() <= TSMath.FastQuadratic(this.r + shape2.r); + } + else + { + return (this.centerCircle1 - centerShape).LengthSquared() <= TSMath.FastQuadratic(this.r + shape2.r); + } + } + else + { + //Debug.Log("Type3: " + distance + " " + deltaPos.LengthSquared() + " " + (this.r + shape2.r) + " " + halfLen); + //勾股定理 + return deltaPos.LengthSquared() - TSMath.FastQuadratic(distance) <= TSMath.FastQuadratic(this.r + shape2.r); + } + } + public override bool CheckCollide(ColliderBase shape2) + { + if (shape2 is CircleCollider sh) + { + return CircleCollideWithCircle(sh); + } + return CheckCollide(this, shape2); + } + public override void DebugDisplayColliderShape(Color color) + { + int circleCount = Mathf.FloorToInt(Mathf.Lerp(5, 8, ((float)r) / 72f)); + float angleDelta = 2 * Mathf.PI / circleCount; + + GL.Begin(GL.TRIANGLE_STRIP); + GL.Color(color); + + for (int i = 0; i < circleCount + 1; i++) + { + float angle = angleDelta * i; + float angleNext = angle + angleDelta; + Vector3 cent = centerCircle1.ToVector(); + Vector3 cent2 = new Vector3(Mathf.Cos(angle) * (float)r, Mathf.Sin(angle) * (float)r, 0) + cent; + GL.Vertex3(cent2.x, cent2.y, cent2.z); + GL.Vertex3(cent.x, cent.y, cent.z); + } + for (int i = 0; i < circleCount + 1; i++) + { + float angle = angleDelta * i; + float angleNext = angle + angleDelta; + Vector3 cent = centerCircle2.ToVector(); + Vector3 cent2 = new Vector3(Mathf.Cos(angle) * (float)r, Mathf.Sin(angle) * (float)r, 0) + cent; + GL.Vertex3(cent2.x, cent2.y, cent2.z); + GL.Vertex3(cent.x, cent.y, cent.z); + } + GL.End(); + } + } + [Serializable] + public class DoubleCircleCollider : DoubleCircleCollider, IMasteredCollider + { + T _master_; + public T Master + { + get => _master_; + set => _master_ = value; + } + + public DoubleCircleCollider(T master, FP R, TSVector2 center1,TSVector2 center2, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) : base(R, center1,center2, group) + { + this._master_ = master; + } + + } + [Serializable] + public class CollisionController:IDisposable { + /// + /// 这个用来防止报错,在正式版的时候 + /// + const bool strictMode = true; + static List emptyTmp = new List(); + static HashSet hashSetTmp = new HashSet();//在非严格模式下防止回收池后报奇怪的错 + public List Colliders = ListPool.Get(); + public HashSet hadCollider = HashSetPool.Get(); + public bool destroyed = false; + bool DestroyedChecker() { + if (strictMode) + { + if (destroyed) + { + Debug.LogError("Try To Use Collisions After Destoyed"); + return true; + } + else + { + return false; + } + } + else + { + return false; + } + } + public CollisionController(params ColliderBase[] collider) + { + SetCollidersIEnumerable(collider); + } + public CollisionController(List collider) + { + SetCollidersIEnumerable(collider); + } + public void SetCollidersIEnumerable(IEnumerable colliders) + { + if (DestroyedChecker()) return;//销毁后不允许再增加 + foreach (var item in Colliders) + { + CollisionManager.instance.RemoveShape(item);//添加物品 + } + hadCollider.Clear(); + Colliders.Clear(); + foreach (var item in colliders) + { + AppendCollider(item); + } + } + public void AppendCollider(ColliderBase item) { + if(DestroyedChecker()) return;//销毁后不允许再增加 + if (hadCollider.Add(item)) + { + Colliders.Add(item); + CollisionManager.instance.AddShape(item);//添加物品 + } + } + public void RemoveCollider(int startIndex,int length) { + if (DestroyedChecker()) return;//销毁后不允许再增加 + int endIndex = startIndex+length; + for (int i = startIndex;i collideEnter, Action collide, Action collideLeave, params CollisionManager.CollisionGroup[] collisionGroups) + { + if (DestroyedChecker()) return this;//销毁后不允许再增加 + foreach (var item in Colliders) + { + CollisionManager.instance.AddListener(item, collideEnter, collide, collideLeave, collisionGroups).multiColli=multiColli; + } + return this; + } + public CollisionController AddListener(Action collideEnter, Action collide, Action collideLeave,params CollisionManager.CollisionGroup[] collisionGroups) { + if (DestroyedChecker()) return this;//销毁后不允许再增加 + foreach (var item in Colliders) + { + CollisionManager.instance.AddListener(item, collideEnter, collide, collideLeave, collisionGroups); + } + return this; + } + public CollisionController AddListener(Action collide, params CollisionManager.CollisionGroup[] groups) { + return AddListener(null,collide,null,groups); + } + public CollisionController AddListener(Action collide, bool multiColli=false, params CollisionManager.CollisionGroup[] groups) + { + return AddListener(multiColli ,null, collide, null, groups); + } + public CollisionController MoveDeltaPos(in TSVector2 deltaPos) { + if (DestroyedChecker()) return this;//销毁后不允许再增加 + foreach (var i in Colliders) + { + CollisionManager.instance.SetCenter(i.GetCenter()+deltaPos, i); + } + return this; + } + public CollisionController SetCenter(in TSVector2 center) { + if (DestroyedChecker()) return this;//销毁后不允许再增加 + foreach (var i in Colliders) { + CollisionManager.instance.SetCenter(center, i); + } + return this; + } + public CollisionController SetEnabled(bool enabled) + { + if (DestroyedChecker()) return this;//销毁后不允许再增加 + foreach (var item in Colliders) + { + item.enabled = enabled; + } + return this; + } + public void Destroy() + { + if (destroyed) { + return; + } + destroyed = true; + foreach (var i in Colliders) + { + CollisionManager.instance.RemoveShape(i); + CollisionManager.instance.RemoveListener(i);//尝试停止所有的监听器 + CollisionManager.instance.RemoveReceiver(i);//尝试停止所有的监听器 + } + HashSetPool.Release(hadCollider); + ListPool.Release(Colliders); + hadCollider = null; + Colliders = null; + if (!strictMode) + { + Colliders = emptyTmp; + hadCollider = hashSetTmp; + Colliders.Clear(); + hadCollider.Clear(); + } + } + public void Dispose() { + Destroy(); + } + } + public class QuadTree where T : ICollideShape + { + public int cellSize = 64;//最小格子宽高 + public FP OneDivideCellSize; + public int depth = 6;//载入时的深度 + public int maxSize; + public int groupCnt = 1;//碰撞组的个数 + FP maxSizeFP,OneHalfMaxSizeFP; + FP[] log4Numbers, log2Numbers; + public TreeNode root = new TreeNode(); + public TreeNode[] treeNodeArr = new TreeNode[0];//用数组优化四叉树的读取 + //储存每个collider所在的坐标格子位置, + public Dictionary colliderPositions = new Dictionary(); + //public HashSet[] unmanagedColliders; + + protected void __init__(int dp = 6, int cw = 64) { + cellSize = cw; + depth = dp; + maxSize = cw << (dp); + maxSizeFP = maxSize; + OneHalfMaxSizeFP = maxSizeFP * 0.5; + OneDivideCellSize = FP.One / (FP)cw; + log4Numbers = new FP[depth + 1]; + log2Numbers = new FP[depth + 1]; + groupCnt = Enum.GetValues(typeof(CollisionManager.CollisionGroup)).Length; + for (int i = 1; i <= depth; i++) + { + //0 2 4 6 8 + log4Numbers[i] = FP.One / (FP)(i << 1); + log2Numbers[i] = FP.One / (FP)(i); + } + /*unmanagedColliders = new HashSet[groupCnt]; + for (int i = 0; i < groupCnt; i++) + { + unmanagedColliders[i] = new HashSet(); + }*/ + BuildTree(); + } + public static int FastPow(int a, int n) + { + int ans = 1; // 赋值为乘法单位元,可能要根据构造函数修改 + while (n != 0) + { + if ((n & 1) != 0) + { + ans *= a; // 这里就最好别用自乘了,不然重载完*还要重载*=,有点麻烦。 + } + n >>= 1; + a = a*a; + } + return ans; + } + /*public int CalcDepthCount(int dp) { + return (FastPow(4, dp+1)-1) / 3; + }*/ + public int CalcDepthCount(int dp) + { + return ((1<<((dp+1)<<1)) - 1) / 3;//等比数列求和 + } + //按照 + /* + root , + lt, + rt, + lb, + rb, + lt.lt, lt.rt,rt.lt,rt.rt, lt.lb, lt.rb,rt.lb,rt.rb , 4^n个 + 初始位置:4^0+...+4^(n-1) = 1*(1-4^n)/(1-4) + //以屏幕为左上角,坐标向右边和下面增加 + 坐标:floor(当前层左上坐标/当前层高度)*(最大层宽度/当前层宽度)+floor(当前左上坐标/当前层宽度) + */ + public int GetPosition(int curDepth,Vector2Int scaledPosition) + { + return CalcDepthCount(curDepth-1)+scaledPosition.y * (1 << (curDepth)) + scaledPosition.x; + } + //计算子四边形的缩放过的坐标 + /// + /// 把原始的四个边界从中间分成四份,然后再把坐标*2 + /// + /// 原始的四个边界 + /// + TSVector4[] splitRect(TSVector4 r) { + //originalRect *= 2; + /*return new TSVector4[] { + new TSVector4(originalRect.x,originalRect.y,(originalRect.z+originalRect.x)/2,(originalRect.w+originalRect.y)/2), + new TSVector4((originalRect.x+originalRect.z)/2,originalRect.y,(originalRect.x+originalRect.z)/2+(originalRect.z-originalRect.x)/2,(originalRect.w+originalRect.y)/2), + };*/ + /*originalRect.x += originalRect.x; + originalRect.y += originalRect.y; + originalRect.z += originalRect.x; + originalRect.w += originalRect.y;*/ + /* + x,y,x+(z-x)/2,y+(w-y)/2 + x+(z-x)/2,y,z,y+(w-y)/2 + x,y+(w-y)/2,x+(z-x)/2,w + x+(z-x)/2,y+(w-y)/2,z,w + + */ + /* + 2x,2y,x+z,y+w + x+z,2y,2z,y+w + 2x,y+w,x+z,2w + x+z,y+w,2z,2w + */ + /*return new TSVector4[] { + new TSVector4(originalRect.x,originalRect.y,originalRect.z,originalRect.w), + new TSVector4(originalRect.z,originalRect.y,originalRect.z+originalRect.z-originalRect.x,originalRect.w), + new TSVector4(originalRect.x,originalRect.w,originalRect.z,originalRect.w+originalRect.w-originalRect.y), + new TSVector4(originalRect.z,originalRect.w,originalRect.z+originalRect.z-originalRect.x,originalRect.w+originalRect.w-originalRect.y), + };*/ + FP a = r.x + r.x; + FP b = r.y + r.y; + FP c = r.x + r.z; + FP d = r.y + r.w; + FP e = r.z + r.z; + FP f = r.w + r.w; + return new TSVector4[] { + new TSVector4(a,b,c,d), + new TSVector4(c,b,e,d), + new TSVector4(a,d,c,f), + new TSVector4(c,d,e,f) + }; + } + //应该不是,直接用大小存吧…… + public class TreeNode { + public HashSet[] Values; + public TreeNode[] Children = new TreeNode[4]; + public TreeNode parent = null; + } + TSVector4 TransAxis(TSVector4 vec) { + vec.y = OneHalfMaxSizeFP - vec.y; + vec.w = OneHalfMaxSizeFP - vec.w; + vec.x += OneHalfMaxSizeFP; + vec.z += OneHalfMaxSizeFP; + return vec; + } + int GetDepth(int width) { //如果是>=1的话也要放在上(更大的)一层比如64的大小(格子也是64)就应该放在128,不然可能会出界什么的。。。 + int layer = 0;//1 2 4 8 + while (width >> layer > 1) + { + layer++; + } + return depth - layer; + } + public struct positionInformation { + public int layer; + public Vector2Int mainPos; + public Vector2Int rightBottom; + + public override bool Equals(object obj) + { + return obj is positionInformation other && Equals(other); + } + + public bool Equals(positionInformation other) + { + return this.layer == other.layer && + this.mainPos == other.mainPos && + this.rightBottom == other.rightBottom; + } + + public override int GetHashCode() + { + return HashCode.Combine(layer, mainPos, rightBottom); + } + + public static bool operator ==(positionInformation left, positionInformation right) + { + return left.Equals(right); + } + + public static bool operator !=(positionInformation left, positionInformation right) + { + return !(left == right); + } + + // New method to check if the current instance contains another instance's range + public bool Contains(positionInformation other) + { + return this.layer == other.layer && + this.mainPos.x <= other.mainPos.x && + this.mainPos.y <= other.mainPos.y && + this.rightBottom.x >= other.rightBottom.x && + this.rightBottom.y >= other.rightBottom.y; + } + public bool TrueContains(positionInformation other) + { + return this.layer == other.layer && + this.mainPos.x < other.mainPos.x && + this.mainPos.y < other.mainPos.y && + this.rightBottom.x > other.rightBottom.x && + this.rightBottom.y > other.rightBottom.y; + } + + // Overload >= operator to use the Contains method + public static bool operator >=(positionInformation left, positionInformation right) + { + return left.Contains(right); + } + public static bool operator <=(positionInformation left, positionInformation right) + { + return right.Contains(left); + } + public static bool operator >(positionInformation left, positionInformation right) + { + return left.TrueContains(right); + } + public static bool operator <(positionInformation left, positionInformation right) + { + return right.TrueContains(left); + } + } + //可能是一个或者四个坐标,插入一次或者四次 + public positionInformation GetCellIndex(TSVector4 rect) { + rect = TransAxis(rect);//乘1/最小格子大小可以得到64-->1 128 --> 2这样 + if (rect.x<0||rect.y<0||rect.z>maxSize||rect.w>maxSize) { + return new positionInformation { //出界了,这个应该放在第0层里面,不参与四叉树判断 + mainPos = Vector2Int.zero, + rightBottom = Vector2Int.zero, + layer = 0 + }; + } + rect *= OneDivideCellSize; + //获取应该放在哪一层 + int layer = GetDepth(TSMath.Ceil(TSMath.Max(rect.w - rect.y, rect.z - rect.x)).AsInt());//TSMath.Ceil(TSMath.Log2(TSMath.Max(rect.w - rect.y, rect.z - rect.x))).AsInt();//这个Log很慢,因为是定点数,自己写一个 + if (layer < 0) + { + return new positionInformation + { //出界了,这个应该放在第0层里面,不参与四叉树判断 + mainPos = Vector2Int.zero, + rightBottom = Vector2Int.zero, + layer = 0 + }; + } + int divide = depth - layer; + Vector2Int mainPos = new Vector2Int(rect.x.AsInt()>> divide, rect.y.AsInt()>> divide); + Vector2Int rightBottom = new Vector2Int((rect.z.AsInt() >> divide), (rect.w.AsInt() >> divide)); + return new positionInformation + { + mainPos = mainPos, + rightBottom = rightBottom, layer = layer + }; + } + /// + /// 根据坐标批量处理某个事 action传入的是 当前深度depth和坐标的参数 + /// + /// + /// + public void Manufacture(Action action,positionInformation area) + { + //对应级别的坐标 + Vector2Int nowPos = area.mainPos; + Vector2Int tar = area.rightBottom; + for(int i = nowPos.x; i <= tar.x; i++) + { + for (int j = nowPos.y;j<=tar.y;j++) { + Vector2Int pos = new Vector2Int(i,j); + action(area.layer,pos); + } + } + } + //带break的 + public bool Manufacture(Func action, positionInformation area) + { + //对应级别的坐标 + Vector2Int nowPos = area.mainPos; + Vector2Int tar = area.rightBottom; + for (int i = nowPos.x; i <= tar.x; i++) + { + for (int j = nowPos.y; j <= tar.y; j++) + { + Vector2Int pos = new Vector2Int(i, j); + if(!action(area.layer, pos)) { return false; } + } + } + return true; + } + public void RemoveCollider(T obj,bool insert=false) { + int grp = (int)obj.colliGroup; + if (colliderPositions.ContainsKey(obj)) + { + Manufacture((layer,posInArr) => { + //Debug.Log(layer+ " "+posInArr); + var objs = treeNodeArr[GetPosition(layer, posInArr)].Values[grp]; + objs.Remove(obj); + }, colliderPositions[obj]); + colliderPositions.Remove(obj); + }/*else + { + unmanagedColliders[grp].Remove(obj); + }*/ + } + public void ClearAllCollider() + { + foreach (var obj in colliderPositions) + { + RemoveCollider(obj.Key); + } + /*foreach (var obj in unmanagedColliders) { + obj.Clear(); + }*/ + } + public void InsertCollider(T obj) { + int grp = (int)obj.colliGroup; + TSVector4 rect = obj.GetBoundingBox();//获取物体的包围盒 + positionInformation positions = GetCellIndex(rect), + oldPosition; + bool hasObj = colliderPositions.ContainsKey(obj),flag=true; + if (hasObj) {//如果position和原position在是包含关系,这里不能替换成大于,因为 会比较图层是否相等 + oldPosition = colliderPositions[obj]; + if (!(oldPosition <= positions)) + { + RemoveCollider(obj,true); + } else if (oldPosition==positions) { + flag = false; + } + } + colliderPositions[obj] = positions; + if (flag){ + Manufacture((layer, posInArr) => { + var objs = treeNodeArr[GetPosition(layer, posInArr)].Values[grp]; + objs.Add(obj); + }, positions); + } + } + void BuildTree() { + int curDepth = 0; + int needCnt = CalcDepthCount(depth); + root = new TreeNode(); + treeNodeArr = new TreeNode[needCnt]; + TSVector4 nowRect = new TSVector4(0,0,1,1);//四边形的边框 + Dictionary> errorChecker = new Dictionary>(); + void dfs(TreeNode node=null) { + treeNodeArr[GetPosition(curDepth,new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt()))] = node;//存入数组 + if(errorChecker.ContainsKey(GetPosition(curDepth, new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt())))) + { + var conf = errorChecker[GetPosition(curDepth, new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt()))]; + if(curDepth!=conf.Item1||conf.Item2!= new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt())) + { + Debug.LogError("Big Append Error" + " " + curDepth + " " + new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt()) + " conflict with " + conf.Item1 + " " + conf.Item2); + + } + } + else + { + errorChecker.Add(GetPosition(curDepth, new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt())), new Tuple(curDepth, new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt()))); + } + /*if (curDepth == 2) { + Debug.Log(curDepth+" "+nowRect); + }*/ + //初始化碰撞组 + node.Values = new HashSet[groupCnt]; + for (int j = 0; j < groupCnt; j++) + { + node.Values[j] = new HashSet(); + } + + if (curDepth>=depth) + { + return; + } + TSVector4 tmpRect = nowRect; + TSVector4[] splited = splitRect(tmpRect); + /*StringBuilder sb = new StringBuilder(); + sb.Append(curDepth); + for (int i = 0;i[] groupedColliders;//这个到时候要改成LinkedHashSet之类的东西。。。 + public HashSet colliders = new HashSet(); + public LinkedDictionary> listeners = new LinkedDictionary>(); + public LinkedDictionary> receivers = new LinkedDictionary>(); + + public HashSet tmpDrawingHasCheckedObjectsInCurFrame = new HashSet();//用来debug有哪些物体当前帧被检查碰撞 + //readonly bool multiCollisionOptimize = false;//先关掉多碰撞优化,测试功能 + private Material _shapeMaterial;//测试 + public CollisionManager() { + groupedColliders = new LinkedHashSet[groupCnt]; + for (int i = 0; i < groupCnt; i++) { + groupedColliders[i] = new LinkedHashSet(); + } + } + public class __action_checkColli__ { + public ColliderBase collider; + public SortedSet checkGroups; + public Action callbackEnter, callback, callbackLeave; + public ColliderBase triggeringObj = null; + public CollisionGroup recieveGroup; + public bool multiColli = false; + } + public enum CollisionGroup + { + Default, + Hero, + HeroBullet, + Bullet, + Enemy, + EnemyCollideBullet, + Item + } + //方便过后删除掉 + //添加碰撞监听器 + //有多碰撞需求再改吧……反正就改个list现在仅支持碰一个物体 + public __action_checkColli__ AddListener(ColliderBase collider,Action callbackEnter, Action callback, Action callbackLeave, params CollisionGroup[] checkGroups) { + var obj = new __action_checkColli__ + { + collider = collider, + checkGroups = new SortedSet(checkGroups), + callbackEnter = callbackEnter, + callbackLeave = callbackLeave, + callback = callback + }; + if (listeners.ContainsKey(collider)) + { + listeners[collider].Add(obj); + } + else + { + var linkedSet = ObjectPool>.GetObject(); + linkedSet.Add(obj); + listeners.Add(collider, linkedSet); + } + return obj; + } + public __action_checkColli__ AddListener(ColliderBase collider, Action callback, params CollisionGroup[] checkGroups) + { + return AddListener(collider, null, callback, null, checkGroups); + } + //移除一个碰撞监听器行为 + public void RemoveListener(__action_checkColli__ action) + { + if (!listeners.ContainsKey(action.collider)) + { + return; + } + listeners[action.collider].Remove(action); + if (listeners[action.collider].Count == 0) + { + RemoveListener(action.collider); + return; + } + } + //移除整个碰撞监听器 + public void RemoveListener(ColliderBase collider) { + if (listeners.ContainsKey(collider)) { + ObjectPool>.ReturnObject(listeners[collider]); + } + listeners.Remove(collider); + } + //receiver不支持enter和leave + __action_checkColli__ AddReceiver(ColliderBase collider, Action callbackEnter, Action callback, Action callbackLeave, CollisionGroup recieveGroup) + { + var obj = new __action_checkColli__ + { + collider = collider, + callbackEnter = callbackEnter, + callbackLeave = callbackLeave, + callback = callback, + recieveGroup = recieveGroup + }; + if (receivers.ContainsKey(collider)) + { + receivers[collider][recieveGroup] = obj; + } + else + { + receivers.Add(collider, new LinkedDictionary { { recieveGroup, obj } }); + } + return obj; + } + public __action_checkColli__ AddReceiver(ColliderBase collider, Action callback, CollisionGroup recieveGroup) + { + return AddReceiver(collider, null, callback, null, recieveGroup); + } + //移除一个碰撞接受器行为 + public void RemoveReceiver(__action_checkColli__ action) + { + if (!receivers.ContainsKey(action.collider)) + { + return; + } + receivers[action.collider].Remove(action.recieveGroup); + if (receivers[action.collider].Count == 0) + { + RemoveReceiver(action.collider); + return; + } + } + //移除整个碰撞接受器 + public void RemoveReceiver(ColliderBase collider) + { + receivers.Remove(collider); + } + public CollisionManager AddShape(ColliderBase collider) { + /*if (multiCollisionOptimize) + { + quadTreeOptmize.InsertCollider(collider); + } + else*/ + { + int grp = (int)collider.colliGroup; + groupedColliders[grp].Add(collider); + } + colliders.Add(collider); + return this; + } + public void RemoveShape(ColliderBase collider) { + /*if (multiCollisionOptimize) + { + quadTreeOptmize.RemoveCollider(collider); + } + else*/ + { + int grp = (int)collider.colliGroup; + groupedColliders[grp].Remove(collider); + } + colliders.Remove(collider); + } + public void SetCenter(in TSVector2 Pos,ColliderBase shape) + { + shape.SetCenter(Pos); + /*if (multiCollisionOptimize) + { + quadTreeOptmize.InsertCollider(shape); + }*/ + } + + /*public void SwitchMultiColli(bool swit) { + if (multiCollisionOptimize == swit) { return; } + if (swit) + { + foreach(var i in colliders) + { + quadTreeOptmize.InsertCollider(i); + } + foreach (var groupHashSet in groupedColliders) { + groupHashSet.Clear(); + } + } + else + { + quadTreeOptmize.ClearAllCollider(); + foreach(var i in colliders) + { + AddShape(i); + } + } + multiCollisionOptimize = swit; + }*/ + public ColliderBase CheckCollision(ColliderBase obj,CollisionGroup group) { + if (!obj.enabled) + { + return null; + } + /*if (multiCollisionOptimize) + { + return quadTreeOptmize.CheckCollision(obj, (int)group); + } + else*/ + { + int grp = (int)group; + foreach(var i in groupedColliders[grp]) + { + if (!i.enabled) { continue; } + if (obj.CheckCollide(i)) + { + return i; + } + } + return null; + } + } + public void CheckCollision(ColliderBase obj, CollisionGroup group, ref List colliObj, bool force = false) { + if (!obj.enabled&&!force) + { + return; + } + { + int grp = (int)group; + foreach (var i in groupedColliders[grp]) + { + if (!i.enabled && !force) { continue; } + if (obj.CheckCollide(i)) + { + colliObj.Add(i); + } + } + } + } + + public void TraverseAllListener() { + { + tmpDrawingHasCheckedObjectsInCurFrame.Clear(); + } + foreach(var kvPair in listeners) + { + var val = kvPair.Value; + foreach (var obj in val) + { + if (!obj.collider.enabled) { continue; }//如果自身不允许碰撞就不碰 + foreach (var i in obj.checkGroups) + { + //多碰撞不支持接收器 + if (obj.multiColli) + { + List collis = ListPool.Get(); + CheckCollision(obj.collider, i, ref collis); + foreach(var retObj in collis) + { + callActionComponent(retObj, obj); + } + ListPool.Release(collis); + }else{ + var retObj = CheckCollision(obj.collider, i); + callActionComponent(retObj, obj); + //如果对方有接收器 + if (retObj != null && receivers.ContainsKey(retObj) && receivers[retObj].ContainsKey(obj.collider.colliGroup)) + { + callActionComponent(obj.collider, receivers[retObj][obj.collider.colliGroup]); + } + } + } + } + } + } + void callActionComponent(ColliderBase beCollidedObj,__action_checkColli__ action) { + if (beCollidedObj != null) + { + if (action.triggeringObj == null) + { + action.triggeringObj = beCollidedObj; + if (action.callbackEnter != null) + { + action.callbackEnter(beCollidedObj); + } + } + action.callback(beCollidedObj); + } + else if (action.triggeringObj != null) + { + if (action.callbackLeave != null) + { + action.callbackLeave(action.triggeringObj); + } + action.triggeringObj = null; + } + } + public void DebugDisplayShape(Matrix4x4 matrixTransform) { + if (_shapeMaterial == null) + { + _shapeMaterial = new Material(Shader.Find("Hidden/Internal-Colored")); + } + _shapeMaterial.SetPass(0); + GL.PushMatrix(); + GL.MultMatrix(matrixTransform); + /*if (!multiCollisionOptimize) + { + for (int i = 0; i < groupedColliders.Length; i++) + { + Color color = Color.Lerp(new Color(1, 0, 0, 0.2f), new Color(0, 0, 1, 0.2f), (float)i / groupCnt); + foreach (var collider in groupedColliders[i]) + { + collider.DebugDisplayColliderShape(color); + } + } + } + else*/ + { + foreach (var collider in colliders) + { + if (!collider.enabled || tmpDrawingHasCheckedObjectsInCurFrame.Contains(collider)) { continue; } + Color color = Color.HSVToRGB((float)collider.colliGroup / groupCnt, 1, 1); + color.a = 0.2f; + //Color color = Color.Lerp(new Color(1, 0, 0, 0.2f), new Color(0, 0, 1, 0.2f), (float)collider.colliGroup / groupCnt); + collider.DebugDisplayColliderShape(color); + } + foreach (var collider in tmpDrawingHasCheckedObjectsInCurFrame) + { + //Color color = Color.Lerp(new Color(1, 1, 0, 0.2f), new Color(0, 1, 1, 0.2f), (float)collider.colliGroup / groupCnt); + Color color = Color.HSVToRGB((float)collider.colliGroup / groupCnt, 2, 1); + color.a = 0.2f; + collider.DebugDisplayColliderShape(color); + } + } + GL.PopMatrix(); + } + } +/* + def GJK(s1,s2) +#两个形状s1,s2相交则返回True。所有的向量/点都是三维的,例如([x,y,0]) +#第一步:选择一个初始方向,这个初始方向可以是随机选择的,但通常来说是两个形状中心之间的向量,即: + d= normalize(s2.center-s1.center) +#第二步:找到支撑点,即第一个支撑点 + simplex=[support(s1,s2,d)] +#第三步:找到第一个支撑点后,以第一个支撑点为起点指向原点O的方向为新方向d + d=ORIGIN-simplex[0] +#第四步:开始循环,找下一个支撑点 + while True + A=[support(s1,s2,d)] +#当新的支撑点A没有经过原点,那我们就返回False,即两个形状没有相交 + if dot(A,d) <0: + return False +#否则,我们就将该点A加入到simplex中 + simplex.append(A) +#handleSimplex负责主要逻辑部分。主要负责处理寻找新方向和更新simplex的逻辑内容,当当前simplex包含原点,则返回Ture + if handleSimplex(simplex,d): + return Ture + +def handleSimplex(simplex,d) +#如果当前的simplex为直线情况,则进入lineCase(simplex,d)函数,寻找下一个方向d,并返回False,即直线情况下的simplex不包含原点 + if len(simplex==2): + return lineCase(simplex,d) +#如果当前的simplex为三角情况,则进入triangleCase(simplex,d, + return triangleCase(simplex,d) + +def lineCase(simplex,d) +#构建向量AB与AO,并使用三重积得到下一个方向 + B,A = simplex + AB,AO=B-A,ORIGIN-A + ABprep= tripleProd(AB,AO,AB) + d.set(ABprep) +#由于一条直线的情况下,原点不能包含在simplex中,所以返回False + return False + +def triangleCase(simplex,d) +#构建向量AB,AC与AO,并来检测原点在空间的哪个区域。 + C,B,A = simplex + AB,AC,AO=B-A,C-A,ORIGIN-A +#通过三重积分别得到垂直于AB、AC的向量,检测区域Rab、Rac中是否包含原点。 + ABprep= tripleProd(AC,AB,AB) + ACprep= tripleProd(AB,AC,AC) +#如果原点在AB区域中,我们移除点C以寻找更加完美的simplex,新的方向就是垂直于AB的向量 + if dot(ABprep,AO)>0: + simplex.remove(C);d.set(ABprep) + return False +#如果原点在AC区域中,我们移除点B以寻找更加完美的simplex,新的方向就是垂直于AC的向量 + elif dot(ACprep,AO)>0: + simplex.remove(Ba);d.set(ACprep) + return False +#如果这两种情况都不符合,那就说明当前的三角形中包含原点,两个形状相交 + return Ture + +def support(s1,s2,d) +#取第一个形状上方向d上最远点并减去第二个形状上相反反向(-d)上最远的点 + return s1.furthestPoint(d)-s2.furthestPoint(-d) + */ +} \ No newline at end of file diff --git a/Assets/ColliderObj.cs.meta b/Assets/ColliderObj.cs.meta new file mode 100644 index 0000000..780dbd0 --- /dev/null +++ b/Assets/ColliderObj.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d3bab7401f5d98b4fafe5ba92c3e2ab6 \ No newline at end of file diff --git a/Assets/ColliderStructure.cs b/Assets/ColliderStructure.cs new file mode 100644 index 0000000..54c6171 --- /dev/null +++ b/Assets/ColliderStructure.cs @@ -0,0 +1,378 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Core.Algorithm; +using TrueSync; +using Unity.Burst; +using Unity.Collections; + +namespace ZeroAs.DOTS.Colliders +{ + public enum ColliderType + { + Circle, + Oval, + Polygon, + DoubleCircle, + } + [StructLayout(LayoutKind.Sequential)] + public struct ColliderStructure + { + public ColliderType colliderType; + public TSVector2 center; + #region 圆形,和双头圆形 + public FP radius;//圆形半径 + #endregion + #region 椭圆形 + public TSVector2 Axis, SqrAxis; + public FP b2Dividea2,rot; + #endregion + #region 多边形 + public int vertexStartIndex, vertexCount; + #endregion + #region 双头圆形 + public TSVector2 circleCenter1{ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => this.Axis; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => this.Axis = value; + } + public TSVector2 circleCenter2{ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => this.SqrAxis; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => this.SqrAxis = value; + } + #endregion + } + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public struct GetFurthestPointExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static void RotateRad(out TSVector2 result, in TSVector2 self, in FP rad) + { + FP cos = FP.FastCos(rad); + FP sin = FP.FastSin(rad); + result.x = self.x * cos - self.y * sin; + result.y = self.x * sin + self.y * cos; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static void Negate(ref FP val) + { + val._serializedValue=val._serializedValue == MathBurstedFix.MIN_VALUE ? MathBurstedFix.MaxValue : (-val._serializedValue); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static void Negate(ref TSVector2 val) + { + Negate(ref val.x); + Negate(ref val.y); + } + static NativeArray points + { + get + { + throw new NotImplementedException(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static void Circle(out TSVector2 result,in TSVector2 center,in TSVector2 direction,in FP radius) + { + result = center + direction.normalized*radius; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static void Oval(out TSVector2 result, in TSVector2 _direction, + in TSVector2 centerPos,in FP rot,in TSVector2 Axis,in TSVector2 SqrAxis,in FP b2Dividea2) + { + //sin和cos还是很快的,因为是线性插值……有Lut + FP neg = rot; + Negate(ref neg); + RotateRad(out var direction,in _direction,in neg); + if (direction.x == 0) + { + RotateRad(out direction, TSMath.Sign(direction.y) * Axis.y * TSVector2.up, rot); + result = direction + centerPos; + return; + }else if (direction.y == 0) + { + RotateRad(out direction, (TSMath.Sign(direction.x) * Axis.x * TSVector2.right), rot); + result = direction + centerPos; + return; + } + FP signX = TSMath.Sign(direction.x); + FP k = direction.y / direction.x;//目标斜率 + FP a2 = SqrAxis.x; + FP b2 = SqrAxis.y; + FP ratio = FP.OverflowMul(k, b2Dividea2); + FP denominator = FP.OverflowAdd(1, FP.OverflowMul(k, ratio)); + if (denominator._serializedValue >= MathBurstedFix.MaxValue || denominator._serializedValue <= MathBurstedFix.MinValue) + { + //Debug.Log("denominatorOverflow "+ direction + " "+ new TSVector2(0, TSMath.Sign(direction.y) * Axis.y).RotateRad(rot)); + RotateRad(out direction, new TSVector2(0, TSMath.Sign(direction.y) * Axis.y), rot); + + result = direction + centerPos; + return; + } + FP value = 1.0/denominator; + + FP tarX = signX * (Axis.x*TSMath.Sqrt(value)); + FP tarY = FP.OverflowMul(tarX,ratio); + //Debug.Log("ovalthings: "+tarX+" "+tarY+" "+k+" "+ratio); + if (tarY._serializedValue >= MathBurstedFix.MaxValue||tarY._serializedValue<=MathBurstedFix.MinValue) + { + RotateRad(out direction, new TSVector2(0, TSMath.Sign(direction.y)*Axis.y), rot); + + result = direction + centerPos; + return; + } + RotateRad(out direction, new TSVector2(tarX,tarY), rot); + + result = direction+centerPos; + return; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static void Polygon(out TSVector2 result, in TSVector2 _direction, in NativeArray movedVertexs,int offset,int length) + { + TSVector2 direction = _direction.normalized; + FP maxLen,len; + maxLen._serializedValue = MathBurstedFix.MinValue; + TSVector2 pos = movedVertexs[offset]; + int len_ = offset + length; + for(int i = len_-1; i >= 0; --i) + { + if((len= TSVector2.Dot(direction, movedVertexs[i])) > maxLen) + { + maxLen = len; + pos = movedVertexs[i]; + } + } + result= pos; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static void DoubleCircle(out TSVector2 result,in TSVector2 direction,in TSVector2 centerCircle1,in TSVector2 centerCircle2,in FP r,in TSVector2 centerPos) + { + //d.normal* + if (TSVector2.Dot(direction, centerCircle1-centerPos) > 0) + { + result= direction.normalized * r + centerCircle1; + } + else + { + result= direction.normalized * r + centerCircle2; + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static void GetFurthestPoint(out TSVector2 result, in ColliderStructure structure,in TSVector2 direction) + { + switch (structure.colliderType) + { + case ColliderType.Circle: + Circle(out result,structure.center,direction,structure.radius); + return; + case ColliderType.Oval: + Oval(out result,direction,structure.center,structure.rot,structure.Axis,structure.SqrAxis,structure.b2Dividea2); + return; + case ColliderType.Polygon: + Polygon(out result,direction,points,structure.vertexStartIndex,structure.vertexCount); + return; + case ColliderType.DoubleCircle: + DoubleCircle(out result,direction,structure.circleCenter1,structure.circleCenter2,structure.radius,structure.center); + return; + default: + throw new NotImplementedException(); + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static void SupportFunc(out TSVector2 result,in ColliderStructure structure1,in ColliderStructure structure2,in TSVector2 direciton) { + GetFurthestPoint(out var resTmp,structure1,direciton); + TSVector2 negateDirection = direciton; + Negate(ref negateDirection); + GetFurthestPoint(out var resTmp2, structure2, negateDirection); + //Debug.Log("direction: "+direciton+" "+ shape1.GetFurthestPoint(direciton)+" "+shape2.GetFurthestPoint(-direciton)); + result=resTmp-resTmp2; + } + } + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public struct CollideExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static void Abs(out FP result,in FP value) { + if (value._serializedValue == MathBurstedFix.MIN_VALUE) { + result._serializedValue= MathBurstedFix.MaxValue; + return; + } + + // branchless implementation, see http://www.strchr.com/optimized_abs_function + var mask = value._serializedValue >> 63; + result._serializedValue = (value._serializedValue + mask) ^ mask; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static void TripleProduct2d(out TSVector2 result,in TSVector2 a,in TSVector2 b,in TSVector2 c) { + FP sign = (a.x * b.y - a.y * b.x); + FP cY = c.y; + GetFurthestPointExtensions.Negate(ref cY); + result = new TSVector2(cY, c.x) * sign; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static bool GJK(in ColliderStructure shape1, in ColliderStructure shape2) { + /* + #两个形状s1,s2相交则返回True。所有的向量/点都是二维的,例如([x,y]) + #第一步:选择一个初始方向,这个初始方向可以是随机选择的,但通常来说是两个形状中心之间的向量,即: + + */ + TSVector2 tmpVec; + TSVector2 direction = (shape2.center - shape1.center).normalized; + //#第二步:找到支撑点,即第一个支撑点(即闵可夫斯基差的边上的点之一……) + NativeArray Simplex = new NativeArray(3,Allocator.Temp);//单纯形数组,最多只能是3个 + GetFurthestPointExtensions.SupportFunc(out tmpVec,shape1, shape2, direction); + Simplex[0] = tmpVec; + int simplexLastInd = 1; + int interateTimeMax = 100;//最大迭代次数 + //#第三步:找到第一个支撑点后,以第一个支撑点为起点指向原点O的方向为新方向d + direction = tmpVec;//= -Simplex[0].normalized + GetFurthestPointExtensions.Negate(ref direction); + TSVector2.Normalize(direction,out direction); + //#第四步:开始循环,找下一个支撑点 + while (interateTimeMax-- > 0) + { + GetFurthestPointExtensions.SupportFunc(out var A,shape1,shape2,direction); + //因为A点是闵可夫斯基差形状在给定方向的最远点,如果那个点没有超过原点,就不想交 + //#当新的支撑点A没有包含原点,那我们就返回False,即两个形状没有相交 + if (TSVector2.Dot(A,direction)<0) + { + Simplex.Dispose(); + return false; + } + Simplex[simplexLastInd++] = A; + //Debug.Log("input: "+A+shape1.GetType()+" "+shape2.GetType()); + //处理为线段的情况 + if (simplexLastInd == 2) + { + //三维的处理方式 + /* + TSVector AB = Simplex[simplexLastInd-2] - Simplex[simplexLastInd - 1]; + TSVector AO = -Simplex[simplexLastInd-1]; + TSVector ABPrep = TSVector.Cross(TSVector.Cross(AB, AO),AB);//垂直于AB的那个点! + */ + //在2d里面可以这么简化 + TSVector2 AB = Simplex[simplexLastInd - 2] - Simplex[simplexLastInd - 1]; + TSVector2 AO = Simplex[simplexLastInd - 1]; + GetFurthestPointExtensions.Negate(ref AO);//这里记得取反 + TripleProduct2d(out var ABPrep,AB,AO,AB); + direction = ABPrep.normalized; + /* + * A是最新插入的点,B是第一次插入的点 + 当我们拥有两个点时,我们怎么选择新的方向? + 1. 构建向量: + o 构建向量 𝐴𝑂(从点A到原点O),即 𝐴𝑂=𝑂−𝐴 + o 构建向量 𝐴𝐵(从点A到点B),即 𝐴𝐵=𝐵−𝐴 + 2. 求解垂直向量: + o 通过叉积 𝐴𝐵×𝐴𝑂,我们可以得到一个垂直于这两个向量的向量。这个向量垂直于 𝐴𝐵 和 𝐴𝑂 所在的平面,并且指向由右手定则决定的方向。 + 3. 求解新的方向: + o 为了得到新的方向 𝑑,我们需要一个向量,这个向量既垂直于 𝐴𝐵×𝐴𝑂,又垂直于 𝐴𝐵。这可以通过三重积来实现,即: + 𝑑=(𝐴𝐵×𝐴𝑂)×𝐴𝐵 + 这个三重积的结果是一个向量,它垂直于 𝐴𝐵 和 𝐴𝐵×𝐴𝑂 所在的平面。换句话说,它是垂直于 𝐴𝐵 的并且指向原点的可能性最大。 + + 简单来说:通过选择垂直于 𝐴𝐵 的方向,我们可以在最有可能包含原点的方向上进行搜索,从而提高搜索效率。 + */ + } + else//处理为三角形的情况 + { + //C是单纯形第一次插入的元素,B是第二次插入的,A是最后插入的 + //构建向量AB,AC与AO,并来检测原点在空间的哪个沃罗诺伊区域(通过排除法可以知道肯定在AB或AC或ABC三角形内部区域) + TSVector2 AC = Simplex[simplexLastInd - 3] - Simplex[simplexLastInd - 1]; + TSVector2 AB = Simplex[simplexLastInd - 2] - Simplex[simplexLastInd - 1]; + TSVector2 AO = Simplex[simplexLastInd - 1]; + GetFurthestPointExtensions.Negate(ref AO);//这里记得取反 + //#通过三重积 分别得到垂直于AB、AC转向特定方向的的向量,检测区域Rab、Rac中是否包含原点。 + TripleProduct2d(out var ABPrep,AC,AB,AB); + //TSVector2 ABPrep = TripleProduct2d(AC, AB, AB).normalized; + TSVector2.Normalize(ABPrep,out ABPrep); + TripleProduct2d(out TSVector2 ACPrep,AB, AC, AC); + TSVector2.Normalize(ACPrep,out ACPrep); + //Debug.Log(ABPrep+" "+ACPrep+" "+AC+" "+AB+" "+AO); + //#如果原点在AB区域中,我们移除点C以寻找更加完美的simplex(C离原点最远),新的方向就是垂直于AB的向量 + if (TSVector2.Dot(ABPrep, AO) > 0) + { + for (int i = 1; i < 3; i++) + { + Simplex[i - 1] = Simplex[i]; + }//删除数组首个元素(C点),当前的单纯形并不包含原点, + simplexLastInd--; + direction = ABPrep; + } else if (TSVector2.Dot(ACPrep, AO) > 0) { + //#如果原点在AC区域中,我们移除点B以寻找更加完美的simplex,新的方向就是垂直于AC的向量 + Simplex[simplexLastInd - 2] = Simplex[simplexLastInd-1]; + simplexLastInd--; + direction = ACPrep; + } + else + { + //否则单纯形包含原点,碰到了 + Simplex.Dispose(); + return true; + } + } + } + //如果超过迭代次数都没有找到点,则判定为没有碰到。 + Simplex.Dispose(); + return false; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static bool CircleCollideWithCircle(in ColliderStructure circle1,in ColliderStructure circle2) + { + TSVector2.DistanceSquared(in circle1.center, in circle2.center, out var dis); + return dis <= TSMath.FastQuadratic(circle1.radius + circle2.radius); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public static bool CircleCollideWithDoubleCircle(in ColliderStructure doubleCircle,in ColliderStructure circle2) + { + TSVector2 centerShape = circle2.center; + TSVector2 deltaPos = centerShape-doubleCircle.center; + TSVector2 delta = (doubleCircle.circleCenter2 - doubleCircle.circleCenter1); + FP len = delta.magnitude; + FP halfLen = len * 0.5; + TSVector2 unit = delta/len; + FP distance = TSVector2.Dot(unit, deltaPos); + Abs(out var absDis,distance); + if (absDis > halfLen+doubleCircle.radius+circle2.radius) { + //Debug.Log("Type1: "+distance + " " + (this.r + shape2.r) + " " + halfLen); + return false; + } + if (absDis >= halfLen) + { + //Debug.Log("Type2: " + distance + " "+ centerShape + " " + this.centerCircle2+ " " + this.centerCircle1 + " " + (this.r + shape2.r) + " " + halfLen); + if (distance > 0) + { + return (doubleCircle.circleCenter2 - centerShape).LengthSquared() <= TSMath.FastQuadratic(doubleCircle.radius+circle2.radius); + } + else + { + return (doubleCircle.circleCenter1 - centerShape).LengthSquared() <= TSMath.FastQuadratic(doubleCircle.radius+circle2.radius); + } + } + else + { + //Debug.Log("Type3: " + distance + " " + deltaPos.LengthSquared() + " " + (this.r + shape2.r) + " " + halfLen); + //勾股定理 + return deltaPos.LengthSquared() - TSMath.FastQuadratic(distance) <= TSMath.FastQuadratic(doubleCircle.radius+circle2.radius); + } + } + } +} \ No newline at end of file diff --git a/Assets/ColliderStructure.cs.meta b/Assets/ColliderStructure.cs.meta new file mode 100644 index 0000000..df33911 --- /dev/null +++ b/Assets/ColliderStructure.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 74e57101ef3e4e26b1429e4a0aef7474 +timeCreated: 1744030070 \ No newline at end of file diff --git a/Assets/HashTypeHelpers.cs b/Assets/HashTypeHelpers.cs new file mode 100644 index 0000000..1d07d09 --- /dev/null +++ b/Assets/HashTypeHelpers.cs @@ -0,0 +1,458 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using MessagePack; + +namespace Core.Algorithm +{ + //给哈希类型添加上按序遍历的功能 + [Serializable] + [MessagePackObject] + public class DictionaryWrapper : IDictionary + { + [Key(0)] + protected IDictionary _dictionary; + public DictionaryWrapper() + { + _dictionary = new Dictionary(); + } + + public DictionaryWrapper(int capacity) + { + _dictionary = new Dictionary(capacity); + } + public DictionaryWrapper(IDictionary dictionary) + { + _dictionary = dictionary; + } + + public virtual TValue this[TKey key] + { + get => _dictionary[key]; + set => _dictionary[key] = value; + } + + public ICollection Keys => _dictionary.Keys; + + public ICollection Values => _dictionary.Values; + + public int Count => _dictionary.Count; + + public bool IsReadOnly => _dictionary.IsReadOnly; + + public virtual void Add(TKey key, TValue value) + { + _dictionary.Add(key, value); + } + + public virtual void Add(KeyValuePair item) + { + _dictionary.Add(item); + } + + public virtual void Clear() + { + _dictionary.Clear(); + } + + public bool Contains(KeyValuePair item) + { + return _dictionary.Contains(item); + } + + public bool ContainsKey(TKey key) + { + return _dictionary.ContainsKey(key); + } + + public virtual void CopyTo(KeyValuePair[] array, int arrayIndex) + { + _dictionary.CopyTo(array, arrayIndex); + } + + public virtual IEnumerator> GetEnumerator() + { + return _dictionary.GetEnumerator(); + } + + public virtual bool Remove(TKey key) + { + return _dictionary.Remove(key); + } + + public virtual bool Remove(KeyValuePair item) + { + return _dictionary.Remove(item); + } + + public bool TryGetValue(TKey key, out TValue value) + { + return _dictionary.TryGetValue(key, out value); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_dictionary).GetEnumerator(); + } + } + [Serializable] + [MessagePackObject(AllowPrivate = true)] + public class LinkedDictionary : DictionaryWrapper, IDictionary + { + [Key(0)] + private readonly Dictionary>> _savedNode = new Dictionary>>(); + [Key(1)] + private readonly LinkedList> _insertedOrderManager = new LinkedList>(); + public LinkedDictionary() + { + _dictionary = new Dictionary(); + } + + /*public DictionaryWrapper(int capacity) + { + _dictionary = new Dictionary(capacity); + }*/ + public LinkedDictionary(IDictionary dictionary) + { + _dictionary = dictionary; + loadNodes(); + } + private void loadNodes() + { + foreach (var i in _dictionary) + { + _insertedOrderManager.AddLast(i); + } + } + private void appendNode(TKey key,TValue value) { + var add = new LinkedListNode>(new KeyValuePair(key, value)); + if(_savedNode.ContainsKey(key)) + { + _insertedOrderManager.AddAfter(_savedNode[key],add); + _insertedOrderManager.Remove(_savedNode[key]); + _savedNode[key] = add; + } + else + { + _insertedOrderManager.AddLast(add); + _savedNode[key] = add; + } + } + private void removeNode(TKey key) { + if (_savedNode.ContainsKey(key)) + { + _insertedOrderManager.Remove(_savedNode[key]); + _savedNode.Remove(key); + } + } + public override TValue this[TKey key] + { + get => _dictionary[key]; + set { + _dictionary[key] = value; + appendNode(key, value); + } + } + + public override void Add(TKey key, TValue value) + { + _dictionary.Add(key, value); + appendNode(key, value); + } + + public override void Add(KeyValuePair item) + { + _dictionary.Add(item); + appendNode(item.Key, item.Value); + } + + public override void Clear() + { + _dictionary.Clear(); + _insertedOrderManager.Clear(); + _savedNode.Clear(); + } + + + public override void CopyTo(KeyValuePair[] array, int arrayIndex) + { + _insertedOrderManager.CopyTo(array, arrayIndex); + } + + public override IEnumerator> GetEnumerator() + { + return _insertedOrderManager.GetEnumerator(); + } + + public override bool Remove(TKey key) + { + var ret = _dictionary.Remove(key); + removeNode(key); + return ret; + } + + public override bool Remove(KeyValuePair item) + { + var ret = _dictionary.Remove(item); + Remove(item.Key); + return ret; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_insertedOrderManager).GetEnumerator(); + } + } + [MessagePackObject] + public class HashSetWrapper : ISet + { + [Key(0)] + protected readonly HashSet _hashSet; + public HashSetWrapper() + { + _hashSet = new HashSet(); + } + public HashSetWrapper(HashSet hashSet) + { + _hashSet = hashSet; + } + + public int Count => _hashSet.Count; + + public bool IsReadOnly => ((ICollection)_hashSet).IsReadOnly; + + public virtual bool Add(T item) + { + return _hashSet.Add(item); + } + + void ICollection.Add(T item) + { + _hashSet.Add(item); + } + + public virtual void Clear() + { + _hashSet.Clear(); + } + + public bool Contains(T item) + { + return _hashSet.Contains(item); + } + + public virtual void CopyTo(T[] array, int arrayIndex) + { + _hashSet.CopyTo(array, arrayIndex); + } + + public virtual void ExceptWith(IEnumerable other) + { + _hashSet.ExceptWith(other); + } + + public virtual IEnumerator GetEnumerator() + { + return _hashSet.GetEnumerator(); + } + + public virtual void IntersectWith(IEnumerable other) + { + _hashSet.IntersectWith(other); + } + + public bool IsProperSubsetOf(IEnumerable other) + { + return _hashSet.IsProperSubsetOf(other); + } + + public bool IsProperSupersetOf(IEnumerable other) + { + return _hashSet.IsProperSupersetOf(other); + } + + public bool IsSubsetOf(IEnumerable other) + { + return _hashSet.IsSubsetOf(other); + } + + public bool IsSupersetOf(IEnumerable other) + { + return _hashSet.IsSupersetOf(other); + } + + public bool Overlaps(IEnumerable other) + { + return _hashSet.Overlaps(other); + } + + public virtual bool Remove(T item) + { + return _hashSet.Remove(item); + } + + public bool SetEquals(IEnumerable other) + { + return _hashSet.SetEquals(other); + } + + public virtual void SymmetricExceptWith(IEnumerable other) + { + _hashSet.SymmetricExceptWith(other); + } + + public virtual void UnionWith(IEnumerable other) + { + _hashSet.UnionWith(other); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_hashSet).GetEnumerator(); + } + } + [Serializable] + [MessagePackObject(AllowPrivate = true)] + public class LinkedHashSet : HashSetWrapper, ISet + { + [Key(0)] + Dictionary> _savedNodes = new Dictionary>(); + [Key(1)] + LinkedList _insertedOrderSaver = new LinkedList(); + public override bool Add(T item) + { + if (_hashSet.Add(item)) + { + _insertedOrderSaver.AddLast(item); + _savedNodes.Add(item,_insertedOrderSaver.Last); + return true; + } + return false; + } + void ICollection.Add(T item) + { + Add(item); + } + public override void Clear() + { + _hashSet.Clear(); + _savedNodes.Clear(); + _insertedOrderSaver.Clear(); + } + public override void CopyTo(T[] array, int arrayIndex) + { + _insertedOrderSaver.CopyTo(array, arrayIndex); + } + public override void UnionWith(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException("other"); + } + + foreach (T item in other) + { + Add(item); + } + } + public override void ExceptWith(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException("other"); + } + + if (_hashSet.Count == 0) + { + return; + } + + if (other == this) + { + Clear(); + return; + } + + foreach (T item in other) + { + Remove(item); + } + } + public override IEnumerator GetEnumerator() + { + return _insertedOrderSaver.GetEnumerator(); + } + + public override void IntersectWith(IEnumerable other) + { + _hashSet.IntersectWith(other); + //求交集求完之后只会删掉元素…… + var node = _insertedOrderSaver.First; + LinkedListNode tmp = node; + while (node != null) { + tmp = node.Next; + if (node.Value==null||!_hashSet.Contains(node.Value)) + { + _insertedOrderSaver.Remove(node); + _savedNodes.Remove(node.Value); + } + node= tmp; + } + } + public override bool Remove(T item) + { + if (_savedNodes.ContainsKey(item)) + { + _insertedOrderSaver.Remove(_savedNodes[item]); + _savedNodes.Remove(item); + } + return _hashSet.Remove(item); + } + private static bool AreEqualityComparersEqual(HashSet set1, HashSet set2) + { + return set1.Comparer.Equals(set2.Comparer); + } + public override void SymmetricExceptWith(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException("other"); + } + + if (_hashSet.Count == 0) + { + UnionWith(other); + } + else if (other == this) + { + Clear(); + } + else if (other is HashSet hashSet && AreEqualityComparersEqual(_hashSet, hashSet)) + { + foreach (T item in other) + { + if (!Remove(item)) + { + Add(item); + } + } + } + else + { + foreach(T item in other) + { + if (!Add(item)) + { + Remove(item); + } + } + } + } + + } + [MessagePackObject] + public class LinkedPooledHashSet : LinkedHashSet, IPoolable + { + public void Reset() { Clear(); } + } +} \ No newline at end of file diff --git a/Assets/HashTypeHelpers.cs.meta b/Assets/HashTypeHelpers.cs.meta new file mode 100644 index 0000000..0a7a072 --- /dev/null +++ b/Assets/HashTypeHelpers.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 0a103d9faf2bced429ffa66fa45797f7 \ No newline at end of file diff --git a/Assets/JobsTesting.cs b/Assets/JobsTesting.cs index 1baa818..4a6fbfa 100644 --- a/Assets/JobsTesting.cs +++ b/Assets/JobsTesting.cs @@ -1,17 +1,87 @@ +using System; +using System.Collections.Generic; +using TrueSync; +using Unity.Burst; +using Unity.Collections; +using Unity.Jobs; using Unity.Mathematics; using UnityEngine; +[BurstCompile(DisableDirectCall = true)] +public struct testJob : IJobParallelFor +{ + public NativeArray values; + public void Execute(int index) + { + var tmp = values[index]; + tmp.center += TSVector2.left; + values[index] = tmp; + } +} + +public class someObjects +{ + public TSVector2 center; + public someObjectsToStruct ToStruct() + { + return new someObjectsToStruct() + { + center = center + }; + } +} + +public struct someObjectsToStruct +{ + public TSVector2 center; +} public class JobsTesting : MonoBehaviour { - // Start is called once before the first execution of Update after the MonoBehaviour is created - void Start() + List objs = new List(); + + private void Start() + { + for (int i = 0; i < 500000; i++) + { + var o = new someObjects(); + o.center = math.UnitVector(360*((FP)UnityEngine.Random.value))*(FP)UnityEngine.Random.value*100; + objs.Add(o); + } + } + + void BurstUpdate() { - + int len = objs.Count; + var job = new testJob(); + var values = new NativeArray(len, Allocator.TempJob); + for (int i = 0; i < len; i++) + { + values[i] = objs[i].ToStruct(); + } + job.values = values; + JobHandle handle = job.Schedule(values.Length, 64); + // 等待作业完成 + handle.Complete(); + for (int i = 0; i < len; i++) + { + objs[i].center = values[i].center; + } + values.Dispose(); } - // Update is called once per frame + void NormalUpdate() + { + int len = objs.Count; + for (int i = 0; i < len; i++) + { + objs[i].center += TSVector2.left; + } + } + + // Start is called once before the first execution of Update after the MonoBehaviour is created void Update() { - + BurstUpdate(); } + } diff --git a/Assets/PoolingManager.cs b/Assets/PoolingManager.cs new file mode 100644 index 0000000..2310e70 --- /dev/null +++ b/Assets/PoolingManager.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; + +namespace Core.Algorithm +{ + public interface IPoolable + { + public void Reset(); + } + + public static class ObjectPool where T : class, IPoolable, new() + { + private static readonly Stack _pool = new Stack(); + private static readonly object _lock = new object(); + + // 创建并初始化对象 + private static T CreateInstance() + { + var instance = new T(); + instance.Reset(); + return instance; + } + + // 静态泛型方法获取对象 + public static T GetObject() + { + if (_pool.Count > 0) + { + var instance = _pool.Pop(); + instance.Reset(); + return instance; + } + + // 如果没有可用对象,则创建一个新的实例 + return CreateInstance(); + } + + // 静态方法回收对象 + public static void ReturnObject(T obj) + { + if (obj == null) + return; + + _pool.Push(obj); + } + } + +} diff --git a/Assets/PoolingManager.cs.meta b/Assets/PoolingManager.cs.meta new file mode 100644 index 0000000..76eb66c --- /dev/null +++ b/Assets/PoolingManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2cd0b71914aa8544899db2eadf8ecd45 \ No newline at end of file diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 1c63aa8..a141fd2 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -38,12 +38,12 @@ RenderSettings: m_ReflectionIntensity: 1 m_CustomReflection: {fileID: 0} m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.18028378, g: 0.22571412, b: 0.30692285, a: 1} m_UseRadianceAmbientProbe: 0 --- !u!157 &3 LightmapSettings: m_ObjectHideFlags: 0 - serializedVersion: 12 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 m_GISettings: serializedVersion: 2 m_BounceScale: 1 @@ -131,6 +131,7 @@ GameObject: - component: {fileID: 330585545} - component: {fileID: 330585544} - component: {fileID: 330585547} + - component: {fileID: 330585548} m_Layer: 0 m_Name: Main Camera m_TagString: MainCamera @@ -250,12 +251,24 @@ MonoBehaviour: m_RequiresColorTexture: 0 m_Version: 2 m_TaaSettings: - quality: 3 - frameInfluence: 0.1 - jitterScale: 1 - mipBias: 0 - varianceClampScale: 0.9 - contrastAdaptiveSharpening: 0 + m_Quality: 3 + m_FrameInfluence: 0.1 + m_JitterScale: 1 + m_MipBias: 0 + m_VarianceClampScale: 0.9 + m_ContrastAdaptiveSharpening: 0 +--- !u!114 &330585548 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 330585543} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a3527897712cb704f9f4e04d329e7bba, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &410087039 GameObject: m_ObjectHideFlags: 0 @@ -336,6 +349,9 @@ Light: m_ForceVisible: 0 m_ShadowRadius: 0 m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 --- !u!4 &410087041 Transform: m_ObjectHideFlags: 0 diff --git a/Assets/TrueSync/Fix64.cs b/Assets/TrueSync/Fix64.cs index 4ddea00..eaaa6ee 100644 --- a/Assets/TrueSync/Fix64.cs +++ b/Assets/TrueSync/Fix64.cs @@ -3,6 +3,7 @@ using UnityEngine; using Unity.Burst; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using MessagePack; @@ -55,6 +56,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten /// [Serializable] [MessagePackObject] + [StructLayout(LayoutKind.Sequential)] public partial struct FP : IEquatable, IComparable { diff --git a/Assets/TrueSync/Fuck.cs b/Assets/TrueSync/Fuck.cs new file mode 100644 index 0000000..54bfe29 --- /dev/null +++ b/Assets/TrueSync/Fuck.cs @@ -0,0 +1,8 @@ +namespace TrueSync +{ + /*public partial struct FP + { + public static readonly long[] TanLut = { 1 }; + public static readonly long[] AcosLut = { 1 }; + }*/ +} \ No newline at end of file diff --git a/Assets/TrueSync/Fuck.cs.meta b/Assets/TrueSync/Fuck.cs.meta new file mode 100644 index 0000000..0ad40f9 --- /dev/null +++ b/Assets/TrueSync/Fuck.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 45df6d4ca1524c0f9e82eaf172ae5e9c +timeCreated: 1744036628 \ No newline at end of file diff --git a/Assets/TrueSync/TSVector2.cs b/Assets/TrueSync/TSVector2.cs index 68e8704..7284619 100644 --- a/Assets/TrueSync/TSVector2.cs +++ b/Assets/TrueSync/TSVector2.cs @@ -42,14 +42,14 @@ public struct TSVector2 : IEquatable { #region Private Fields - private static TSVector2 zeroVector = new TSVector2(0, 0); - private static TSVector2 oneVector = new TSVector2(1, 1); + private static readonly TSVector2 zeroVector = new TSVector2(0, 0); + private static readonly TSVector2 oneVector = new TSVector2(1, 1); - private static TSVector2 rightVector = new TSVector2(1, 0); - private static TSVector2 leftVector = new TSVector2(-1, 0); + private static readonly TSVector2 rightVector = new TSVector2(1, 0); + private static readonly TSVector2 leftVector = new TSVector2(-1, 0); - private static TSVector2 upVector = new TSVector2(0, 1); - private static TSVector2 downVector = new TSVector2(0, -1); + private static readonly TSVector2 upVector = new TSVector2(0, 1); + private static readonly TSVector2 downVector = new TSVector2(0, -1); #endregion Private Fields @@ -230,20 +230,20 @@ public static FP Distance(TSVector2 value1, TSVector2 value2) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Distance(ref TSVector2 value1, ref TSVector2 value2, out FP result) + public static void Distance(in TSVector2 value1, in TSVector2 value2, out FP result) { - DistanceSquared(ref value1, ref value2, out result); + DistanceSquared(in value1, in value2, out result); result = (FP) FP.Sqrt(result); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static FP DistanceSquared(TSVector2 value1, TSVector2 value2) { FP result; - DistanceSquared(ref value1, ref value2, out result); + DistanceSquared(in value1, in value2, out result); return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void DistanceSquared(ref TSVector2 value1, ref TSVector2 value2, out FP result) + public static void DistanceSquared(in TSVector2 value1, in TSVector2 value2, out FP result) { result._serializedValue=MathBurstedFix.DistanceSquared( (value1.x._serializedValue - value2.x._serializedValue), @@ -336,7 +336,7 @@ public FP magnitude { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { FP result; - DistanceSquared(ref this, ref zeroVector, out result); + DistanceSquared(in this, in zeroVector, out result); return FP.Sqrt(result); } } @@ -348,7 +348,7 @@ public static TSVector2 ClampMagnitude(TSVector2 vector, FP maxLength) { public FP LengthSquared() { FP result; - DistanceSquared(ref this, ref zeroVector, out result); + DistanceSquared(in this, in zeroVector, out result); return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -455,12 +455,12 @@ public static void Negate(ref TSVector2 value, out TSVector2 result) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Normalize() { - Normalize(ref this, out this); + Normalize(in this, out this); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TSVector2 Normalize(TSVector2 value) { - Normalize(ref value, out value); + Normalize(in value, out value); return value; } [IgnoreMember] @@ -468,16 +468,16 @@ public TSVector2 normalized { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { TSVector2 result; - TSVector2.Normalize(ref this, out result); + TSVector2.Normalize(in this, out result); return result; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Normalize(ref TSVector2 value, out TSVector2 result) + public static void Normalize(in TSVector2 value, out TSVector2 result) { FP factor; - DistanceSquared(ref value, ref zeroVector, out factor); + DistanceSquared(in value, in zeroVector, out factor); //UnityEngine.Debug.Log("value " + value); factor = 1f/(FP) FP.Sqrt(factor); result.x = value.x*factor; diff --git a/Assets/math.cs b/Assets/math.cs new file mode 100644 index 0000000..c258be6 --- /dev/null +++ b/Assets/math.cs @@ -0,0 +1,511 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System; +using TrueSync; + +namespace RandomBenchmark +{ + public class XorShiftRandom + { + private const double NormalizationFactor = 1.0 / int.MaxValue; + + private readonly ulong[] _state; + private ulong _seed; + private bool _takeMsb = true; + private ulong _currentPartialResult; + + public XorShiftRandom(int seed) + { + _seed = (ulong)seed; + _state = new[] { SplitMix64(), SplitMix64() }; + } + + public virtual int Next() + { + var sample = InternalSample() & int.MaxValue; + + return sample == int.MaxValue + ? --sample + : sample; + } + + public virtual int Next(int minValue, int maxValue) + { + if (minValue > maxValue) + throw new ArgumentOutOfRangeException(nameof(minValue)); + + var range = (long)maxValue - minValue; + + return minValue + (int)(range * NextDouble()); + } + + public virtual int Next(int maxValue) + { + if (maxValue < 0) + throw new ArgumentOutOfRangeException(nameof(maxValue)); + + return (int)(NextDouble() * maxValue); + } + + public virtual double NextDouble() + { + var sample = Next(); + return sample * NormalizationFactor; + } + + public virtual void NextBytes(byte[] buffer) + { + if (buffer == null) + throw new ArgumentNullException(nameof(buffer)); + + var tmp = BitConverter.GetBytes(InternalSample()); + short index = 0; + for (var i = 0; i < buffer.Length; ++i) + { + if (index == 4) + { + index = 0; + tmp = BitConverter.GetBytes(InternalSample()); + } + + buffer[i] = tmp[index++]; + } + } + + private int InternalSample() + { + int sample; + + if (_takeMsb) + { + _currentPartialResult = XorShift128Plus(); + sample = unchecked((int)(_currentPartialResult >> 32)); + } + else + { + sample = unchecked((int)_currentPartialResult); + } + + _takeMsb = !_takeMsb; + + return sample; + } + + private ulong SplitMix64() + { + var z = unchecked(_seed += 0x9E3779B97F4A7C15); + z = unchecked((z ^ (z >> 30)) * 0xBF58476D1CE4E5B9); + z = unchecked((z ^ (z >> 27)) * 0x94D049BB133111EB); + return z ^ (z >> 31); + } + + private ulong XorShift128Plus() + { + var s1 = _state[0]; + var s0 = _state[1]; + var result = s0 + s1; + _state[0] = s0; + s1 ^= s1 << 23; + _state[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5); + return result; + } + } +} +public class KalmanFilterVector3 +{ + + //----------------------------------------------------------------------------------------- + // Constants: + //----------------------------------------------------------------------------------------- + + public const float DEFAULT_Q = 0.000001f; + public const float DEFAULT_R = 0.01f; + + public const float DEFAULT_P = 1; + + //----------------------------------------------------------------------------------------- + // Private Fields: + //----------------------------------------------------------------------------------------- + + private float q; + private float r; + private float p = DEFAULT_P; + private Vector3 x; + private float k; + + //----------------------------------------------------------------------------------------- + // Constructors: + //----------------------------------------------------------------------------------------- + + // N.B. passing in DEFAULT_Q is necessary, even though we have the same value (as an optional parameter), because this + // defines a parameterless constructor, allowing us to be new()'d in generics contexts. + public KalmanFilterVector3() : this(DEFAULT_Q) { } + public KalmanFilterVector3 InitPosition(Vector3 initalPosition) { + x = initalPosition; + return this; + } + + public KalmanFilterVector3(float aQ = DEFAULT_Q, float aR = DEFAULT_R) + { + q = aQ; + r = aR; + } + + //----------------------------------------------------------------------------------------- + // Public Methods: + //----------------------------------------------------------------------------------------- + + public Vector3 Update(Vector3 measurement, float? newQ = null, float? newR = null) + { + + // update values if supplied. + if (newQ != null && q != newQ) + { + q = (float)newQ; + } + if (newR != null && r != newR) + { + r = (float)newR; + } + + // update measurement. + { + k = (p + q) / (p + q + r); + p = r * (p + q) / (r + p + q); + } + + // filter result back into calculation. + Vector3 result = x + (measurement - x) * k; + x = result; + return result; + } + + public Vector3 Update(List measurements, bool areMeasurementsNewestFirst = false, float? newQ = null, float? newR = null) + { + + Vector3 result = Vector3.zero; + int i = (areMeasurementsNewestFirst) ? measurements.Count - 1 : 0; + + while (i < measurements.Count && i >= 0) + { + + // decrement or increment the counter. + if (areMeasurementsNewestFirst) + { + --i; + } + else + { + ++i; + } + + result = Update(measurements[i], newQ, newR); + } + + return result; + } + + public void Reset(Vector3? InitPosition=null) + { + p = 1; + x = InitPosition??Vector3.zero; + k = 0; + } +} +public static class math +{ + public static readonly FP sqrt2 = FP.Sqrt(2); + public static bool checkOut(TSVector2 border, TSVector pos, TSVector2 size) + { + FP max = TSMath.Max(size.x,size.y); + border *= 0.5; + size = TSVector2.one * (max * sqrt2 * 0.5); + if (pos.x - size.x > border.x || pos.x + size.x < -border.x || pos.y - size.y > border.y || pos.y + size.y < -border.y) + { + return true; + } + return false; + } + /// + /// 圆弧接起来的曲线 + /// + /// 时间 + /// 半径 + /// 角速度 + /// 每个圆弧的弧度 + /// + public static Vector2 curve_joined_by_arc(float time,float r,float w,float theta) { + float theta2 = Mathf.PI / 2f - (2 * Mathf.PI - theta) / 2f; + float theta3 = Mathf.PI / 2f + (2 * Mathf.PI - theta) / 2f; + //目前处于的弧度 + float currentArc = ((w * time) % theta + theta3) * Mathf.Pow((-1) , Mathf.Floor((w*time) / theta)); + Vector2 circleCenter = new Vector2( + Mathf.Cos(theta2)*(2*Mathf.Floor((w*time) / theta + 1) -1)*r, + Mathf.Sin(theta2)*Mathf.Pow((-1) , Mathf.Floor((w*time) / theta + 1))*r + ); + return new Vector2(Mathf.Cos(currentArc), Mathf.Sin(currentArc))*r+circleCenter; + } + /// + ///Catmull-Rom线,会通过相关的控制点 + /// 根据起点,n个控制点,终点 计算Cspline曲线插值(首尾为必要的点,其余为控制点,所以至少有4个点) + /// + /// 起点,n-1个控制点,终点 + /// 当前插值位置0~1 ,0为起点,1为终点 + /// + public static TSVector Interp(TSVector[] pts, FP t) + { + t = TSMath.Clamp(t, 0.0, 2.0); + int numSections = pts.Length - 3; + int currPt = (int)TSMath.Min(TSMath.Floor(t * numSections), numSections - 1); + FP u = t * numSections - currPt; + TSVector a = pts[currPt]; + TSVector b = pts[currPt + 1]; + TSVector c = pts[currPt + 2]; + TSVector d = pts[currPt + 3]; + + return 0.5 * ( + ((TSVector.zero-a) + 3 * b - 3 * c + d) * (u * u * u) + + (2 * a - 5 * b + 4 * c - d) * (u * u) + + ((TSVector.zero - a) + c) * u + + 2 * b + ); + } + /// + /// n阶贝塞尔曲线插值计算函数 + /// 根据起点,n个控制点,终点 计算贝塞尔曲线插值 + /// + /// 起点,n-1个控制点,终点 + /// 当前插值位置0~1 ,0为起点,1为终点 + /// + public static Vector3 bezier_interpolation_func(Vector3[] points, float t) + { + Vector3 PointF = new Vector3(); + if (t == 1) + { + return points[points.Length - 1]; + } + int count = points.Length; + float[] part = new float[count]; + float sum_x = 0, sum_y = 0; + for (int i = 0; i < count; i++) + { + ulong tmp; + int n_order = count - 1; // 阶数 + tmp = calc_combination_number(n_order, i); + sum_x += (float)(tmp * points[i].x * Math.Pow((1 - t), n_order - i) * Math.Pow(t, i)); + sum_y += (float)(tmp * points[i].y * Math.Pow((1 - t), n_order - i) * Math.Pow(t, i)); + } + PointF.x = sum_x; + PointF.y = sum_y; + return PointF; + } + public static TSVector2 expandVectorOnTargetAngle(in TSVector2 vec,in TSVector2 scale,FP angle=default) + { + /* + * (a cos^2(d) + b sin^2(d) | a sin(d) cos(d) - b sin(d) cos(d) + a sin(d) cos(d) - b sin(d) cos(d) | a sin^2(d) + b cos^2(d)) + */ + angle*=TSMath.Deg2Rad; + FP sin = FP.FastSin(angle); + FP cos = FP.FastCos(angle); + FP sin2 = sin * sin; + FP cos2 = cos * cos; + FP sincos = sin * cos; + return new TSVector2( + (scale.x*cos2+scale.y*sin2)*vec.x+(scale.x-scale.y)*sincos*vec.y, + (scale.x-scale.y)*sincos*vec.x+(scale.x*sin2+scale.y*cos2)*vec.y + ); + } + /// + /// 计算组合数公式 + /// + /// + /// + /// + private static ulong calc_combination_number(int n, int k) + { + ulong[] result = new ulong[n + 1]; + for (int i = 1; i <= n; i++) + { + result[i] = 1; + for (int j = i - 1; j >= 1; j--) + result[j] += result[j - 1]; + result[0] = 1; + } + return result[k]; + } + + + public static long MoveToward(long target, long current, long maxDistanceDelta) + { + long num = target - current; + long power = num * num; + if (power == 0 || (maxDistanceDelta >= 0 && power <= maxDistanceDelta * maxDistanceDelta)) + { + return target; + } + long num5 = power; + return current + num / num5 * maxDistanceDelta; + } + public static Vector2 UnitVector(float ang) + { + return new Vector2(Mathf.Cos(ang * Mathf.Deg2Rad), Mathf.Sin(ang * Mathf.Deg2Rad)); + } + public static TSVector2 UnitVector(int ang) + { + return new TSVector2(FP.FastCos(ang * TSMath.Deg2Rad), FP.FastSin(ang * TSMath.Deg2Rad)); + } + public static TSVector2 UnitVector(FP ang) + { + return new TSVector2(FP.FastCos(ang * TSMath.Deg2Rad), FP.FastSin(ang * TSMath.Deg2Rad)); + } + public static Mesh CreateMesh(float radius, float innerradius, float angledegree, int segments) + { + //vertices(顶点): + int vertices_count = segments * 2 + 2; //因为vertices(顶点)的个数与triangles(索引三角形顶点数)必须匹配 + Vector3[] vertices = new Vector3[vertices_count]; + float angleRad = Mathf.Deg2Rad * angledegree; + float angleCur = angleRad; + float angledelta = angleRad / segments; + for (int i = 0; i < vertices_count; i += 2) + { + float cosA = Mathf.Cos(angleCur); + float sinA = Mathf.Sin(angleCur); + vertices[i] = new Vector3(radius * cosA, radius * sinA, 0); + vertices[i + 1] = new Vector3(innerradius * cosA, innerradius * sinA, 0); + angleCur -= angledelta; + } + //triangles: + int triangle_count = segments * 6; + int[] triangles = new int[triangle_count]; + for (int i = 0, vi = 0; i < triangle_count; i += 6, vi += 2) + { + triangles[i] = vi; + triangles[i + 1] = vi + 3; + triangles[i + 2] = vi + 1; + triangles[i + 3] = vi + 2; + triangles[i + 4] = vi + 3; + triangles[i + 5] = vi; + } + //uv: + Vector2[] uvs = new Vector2[vertices_count]; + for (int i = 0; i < vertices_count; i+=2) + { + uvs[i] = new Vector2((float)i / vertices_count, 1); + uvs[i+1] = new Vector2((float)i / vertices_count, 0); + } + //负载属性与mesh + Mesh mesh = new Mesh(); + mesh.vertices = vertices; + mesh.triangles = triangles; + mesh.uv = uvs; + return mesh; + } + public static FP MapAngleTo180Range(FP angle) + { + // 使用取余运算符,首先要将负数角度转换为正数,以便正确取余 + // 然后根据取余结果决定是否减去360度,转换回原区间并考虑正负 + return (angle + 540) % 360 - 180; + } + + public static bool CircleTriggerCircle(in TSVector point1, in FP r1, in TSVector point2, in FP r2, FP r1_width_height_ratio = default) + { + if (r1_width_height_ratio == 0) + { + r1_width_height_ratio = 1; + } + r1_width_height_ratio = (r1 * r1_width_height_ratio + r2) / (r1 + r2);//这个判定只适用于大椭圆与小圆判定,因为其实不是椭圆,只是近似为一个椭圆 + return (TSMath.FastQuadratic(TSMath.Abs((point2.x - point1.x) / r1_width_height_ratio)) + TSMath.FastQuadratic(TSMath.Abs(point2.y - point1.y))) <= TSMath.FastQuadratic(r1 + r2); + } +} +namespace ZeroAs.DataStructure { + + public class MaxHeap where T : IComparable + { + public List container = new List(); + int cnt = 0; + public int Count { get { return cnt; } } + protected virtual bool cmp(T a, T b) + { + return a.CompareTo(b) > 0; + } + void swap(int a, int b) + { + T tmp = container[a]; container[a] = container[b]; container[b] = tmp; + } + void up() + { + int pos = cnt - 1; + while (pos > 0) + { + int father = (pos - 1) >> 1; + //pos>father + if (cmp(container[pos], container[father])) + { + swap(pos, father); + pos = father; + } + else + { + break; + } + } + } + void down() + { + int pos = 0, leftChild; + while ((leftChild = (pos << 1) + 1) < cnt) + { + int swapper = leftChild; + if (leftChild + 1 < cnt && cmp(container[leftChild + 1], container[leftChild])) + { + //right>left + swapper++; + } + //swapper > pos + if (cmp(container[swapper], container[pos])) + { + swap(pos, swapper); + pos = swapper; + } + else + { + break; + } + } + } + public void Add(T item) + { + container.Add(item); + cnt++; + up(); + } + public bool IsEmpty + { + get { return cnt == 0; } + } + public T Pop() + { + if (this.IsEmpty) + { + throw new InvalidOperationException("堆为空"); + } + T res = container[0]; + --cnt; + container[0] = container[cnt]; + container.RemoveAt(cnt); + down(); + return res; + } + public T Peek() + { + if (this.IsEmpty) + { + throw new InvalidOperationException("堆为空"); + } + return container[0]; + } + } +} \ No newline at end of file diff --git a/Assets/math.cs.meta b/Assets/math.cs.meta new file mode 100644 index 0000000..f1f32e5 --- /dev/null +++ b/Assets/math.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 096c4a70d4e6a474784178f5dfa52f70 \ No newline at end of file diff --git a/Assets/tmpExtensions.cs b/Assets/tmpExtensions.cs new file mode 100644 index 0000000..0648017 --- /dev/null +++ b/Assets/tmpExtensions.cs @@ -0,0 +1,45 @@ +using TrueSync; +using UnityEngine; + +namespace Core.Algorithm +{ + public static class tmpExtensions + { + public static Vector2 RotateRad(this Vector2 self, float rad) + { + float cos = Mathf.Cos(rad), sin = Mathf.Cos(rad); + return new Vector2(self.x * cos - self.y * sin, self.x * sin + self.y * cos); + } + /// + /// 旋转一个二维向量 + /// + /// 该向量 + /// 弧度 + /// + public static TSVector2 RotateRad(this TSVector2 self, FP rad, TSVector2 original = (default)) + { + self -= original; + FP cos = FP.FastCos(rad), sin = FP.FastSin(rad); + return new TSVector2(self.x * cos - self.y * sin, self.x * sin + self.y * cos) + original; + } + public static TSVector RotateRad(this TSVector self, FP rad, TSVector original = (default)) + { + self -= original; + FP cos = FP.FastCos(rad), sin = FP.FastSin(rad); + return new TSVector(self.x * cos - self.y * sin, self.x * sin + self.y * cos, self.z) + original; + } + /// + /// 旋转一个二维向量 + /// + /// 该向量 + /// 角度 + /// + public static TSVector2 RotateAngle(this TSVector2 self, FP angle, TSVector2 original = (default)) { + return RotateRad(self, angle * TSMath.Deg2Rad, original); + } + public static TSVector RotateAngle(this TSVector self, FP angle, TSVector original = (default)) + { + return RotateRad(self, angle * TSMath.Deg2Rad, original); + } + } +} \ No newline at end of file diff --git a/Assets/tmpExtensions.cs.meta b/Assets/tmpExtensions.cs.meta new file mode 100644 index 0000000..95fd7d9 --- /dev/null +++ b/Assets/tmpExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: dbfc0cfa7fb2449fb1e7555d8b0e0f3f +timeCreated: 1744029491 \ No newline at end of file diff --git a/ProjectSettings/BurstAotSettings_StandaloneWindows.json b/ProjectSettings/BurstAotSettings_StandaloneWindows.json new file mode 100644 index 0000000..58cf25f --- /dev/null +++ b/ProjectSettings/BurstAotSettings_StandaloneWindows.json @@ -0,0 +1,18 @@ +{ + "MonoBehaviour": { + "Version": 4, + "EnableBurstCompilation": true, + "EnableOptimisations": true, + "EnableSafetyChecks": false, + "EnableDebugInAllBuilds": false, + "DebugDataKind": 1, + "EnableArmv9SecurityFeatures": false, + "CpuMinTargetX32": 0, + "CpuMaxTargetX32": 0, + "CpuMinTargetX64": 0, + "CpuMaxTargetX64": 0, + "CpuTargetsX32": 6, + "CpuTargetsX64": 72, + "OptimizeFor": 0 + } +} diff --git a/ProjectSettings/CommonBurstAotSettings.json b/ProjectSettings/CommonBurstAotSettings.json new file mode 100644 index 0000000..0293daf --- /dev/null +++ b/ProjectSettings/CommonBurstAotSettings.json @@ -0,0 +1,6 @@ +{ + "MonoBehaviour": { + "Version": 4, + "DisabledWarnings": "" + } +} diff --git a/ProjectSettings/SceneTemplateSettings.json b/ProjectSettings/SceneTemplateSettings.json new file mode 100644 index 0000000..ede5887 --- /dev/null +++ b/ProjectSettings/SceneTemplateSettings.json @@ -0,0 +1,121 @@ +{ + "templatePinStates": [], + "dependencyTypeInfos": [ + { + "userAdded": false, + "type": "UnityEngine.AnimationClip", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEditor.Animations.AnimatorController", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.AnimatorOverrideController", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEditor.Audio.AudioMixerController", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.ComputeShader", + "defaultInstantiationMode": 1 + }, + { + "userAdded": false, + "type": "UnityEngine.Cubemap", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.GameObject", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEditor.LightingDataAsset", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.LightingSettings", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Material", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEditor.MonoScript", + "defaultInstantiationMode": 1 + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicsMaterial", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicsMaterial2D", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.PostProcessing.PostProcessResources", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.VolumeProfile", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEditor.SceneAsset", + "defaultInstantiationMode": 1 + }, + { + "userAdded": false, + "type": "UnityEngine.Shader", + "defaultInstantiationMode": 1 + }, + { + "userAdded": false, + "type": "UnityEngine.ShaderVariantCollection", + "defaultInstantiationMode": 1 + }, + { + "userAdded": false, + "type": "UnityEngine.Texture", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Texture2D", + "defaultInstantiationMode": 0 + }, + { + "userAdded": false, + "type": "UnityEngine.Timeline.TimelineAsset", + "defaultInstantiationMode": 0 + } + ], + "defaultDependencyTypeInfo": { + "userAdded": false, + "type": "", + "defaultInstantiationMode": 1 + }, + "newSceneOverride": 0 +} \ No newline at end of file From bad94fe9db080fefa1f443cb801bc87f479a49e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B3=A0=E6=BC=AA?= <32807696+AngelShadow2017@users.noreply.github.com> Date: Sun, 13 Apr 2025 02:22:48 +0800 Subject: [PATCH 2/9] collis --- Assets/ColliUpdate.cs | 30 + Assets/ColliUpdate.cs.meta | 3 + Assets/ColliderObj.cs | 612 ++++----------- Assets/ColliderStructure.cs | 476 +++++++++++- Assets/ColliderTester.cs | 185 +++++ Assets/ColliderTester.cs.meta | 3 + .../NuGet/Editor/NuGetForUnity.PluginAPI.xml | 2 +- Assets/Scenes/New Folder.meta | 8 + Assets/Scenes/New Material.mat | 135 ++++ Assets/Scenes/New Material.mat.meta | 8 + Assets/Scenes/New Scene.unity | 708 ++++++++++++++++++ Assets/Scenes/New Scene.unity.meta | 7 + Assets/Scenes/SampleScene.unity | 193 ++++- Assets/Settings/DefaultVolumeProfile.asset | 5 +- Assets/TrueSync/TSMatrix4x4.cs | 12 +- Assets/tmpExtensions.cs | 2 +- Packages/manifest.json | 4 +- Packages/packages-lock.json | 170 +++-- ProjectSettings/GraphicsSettings.asset | 9 +- ProjectSettings/ProjectSettings.asset | 2 +- ProjectSettings/ProjectVersion.txt | 4 +- 21 files changed, 1992 insertions(+), 586 deletions(-) create mode 100644 Assets/ColliUpdate.cs create mode 100644 Assets/ColliUpdate.cs.meta create mode 100644 Assets/ColliderTester.cs create mode 100644 Assets/ColliderTester.cs.meta create mode 100644 Assets/Scenes/New Folder.meta create mode 100644 Assets/Scenes/New Material.mat create mode 100644 Assets/Scenes/New Material.mat.meta create mode 100644 Assets/Scenes/New Scene.unity create mode 100644 Assets/Scenes/New Scene.unity.meta diff --git a/Assets/ColliUpdate.cs b/Assets/ColliUpdate.cs new file mode 100644 index 0000000..f2c7fc4 --- /dev/null +++ b/Assets/ColliUpdate.cs @@ -0,0 +1,30 @@ +using System; +using Core.Algorithm; +using UnityEngine; + +namespace DefaultNamespace +{ + public class ColliUpdate:MonoBehaviour + { + void Awake() + { + this.transform.position=Vector3.zero; + CollisionManager.instance = new CollisionManager(); + } + + private void Update() + { + CollisionManager.instance.TraverseAllListener(); + } + + private void OnPostRender() + { + CollisionManager.instance.DebugDisplayShape(transform.localToWorldMatrix); + } + + private void OnDestroy() + { + CollisionManager.instance.Dispose(); + } + } +} \ No newline at end of file diff --git a/Assets/ColliUpdate.cs.meta b/Assets/ColliUpdate.cs.meta new file mode 100644 index 0000000..9fea738 --- /dev/null +++ b/Assets/ColliUpdate.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1ceed5607a5d49dca1e94035eaa2f698 +timeCreated: 1744470566 \ No newline at end of file diff --git a/Assets/ColliderObj.cs b/Assets/ColliderObj.cs index 5dc5eb8..1a29854 100644 --- a/Assets/ColliderObj.cs +++ b/Assets/ColliderObj.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; using TrueSync; +using Unity.Collections; using UnityEngine; using UnityEngine.Pool; using ZeroAs.DOTS.Colliders; @@ -20,6 +23,10 @@ public interface ICollideShape { public CollisionManager.CollisionGroup colliGroup { get; set; } public bool enabled { get; set; } public void DebugDisplayColliderShape(Color color); + + public void Destroy() + { + } } public interface IMasteredCollider { @@ -67,7 +74,7 @@ static TSVector2 TripleProduct2d(TSVector2 a,TSVector2 b,TSVector2 c) { public abstract TSVector4 GetBoundingBox(); public TSVector2 GetFurthestPoint(in TSVector2 direction) { - GetFurthestPointExtensions.GetFurthestPoint(out var result, collider, direction); + GetFurthestPointExtensions.GetFurthestPoint(out var result, collider, direction,ColliderVertexBuffer.instancedBuffer); return result; } public abstract void SetRotation(FP rotRad); @@ -164,10 +171,25 @@ o 为了得到新的方向 𝑑,我们需要一个向量,这个向量既垂 //如果超过迭代次数都没有找到点,则判定为没有碰到。 return false; } - public virtual bool CheckCollide(ColliderBase shape2) { + /*public bool CheckCollide(ColliderBase shape2) { return CheckCollide(this, shape2); + }*/ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual ColliderStructure GetRealCollider() + { + return Collider; } + + public bool CheckCollide(ColliderBase shape2) + { + return CollideExtensions.CheckCollide(this.GetRealCollider(), shape2.GetRealCollider(),ColliderVertexBuffer.instancedBuffer); + } + public virtual void DebugDisplayColliderShape(Color color) { } + + public virtual void Destroy() + { + } } [Serializable] public abstract class ColliderBase : ColliderBase @@ -179,13 +201,11 @@ public class CircleCollider : ColliderBase { public CircleCollider(FP R,TSVector2 center,CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) { - Collider = new ColliderStructure() - { - colliderType = ColliderType.Circle, - radius = R, - center = center - }; - + Collider = ColliderStructure.CreateInstance(); + Collider.colliderType = ColliderType.Circle; + Collider.radius = R; + Collider.center = center; + colliGroup = group; } public override void SetRotation(FP rotRad) { }//没错,圆形没有旋转 @@ -212,7 +232,7 @@ bool CircleCollideWithCircle(CircleCollider shape2) { return CollideExtensions.CircleCollideWithCircle(this.Collider,shape2.Collider); } - public override bool CheckCollide(ColliderBase shape2) + /*public override bool CheckCollide(ColliderBase shape2) { if(shape2 is CircleCollider sh) { @@ -224,11 +244,11 @@ public override bool CheckCollide(ColliderBase shape2) return d.CircleCollideWithCircle(this); } return CheckCollide(this, shape2); - } + }*/ public override void DebugDisplayColliderShape(Color color) { float r = (float)collider.radius; - int circleCount = Mathf.FloorToInt(Mathf.Lerp(5,8,((float)r)/72f)); + int circleCount = Mathf.FloorToInt(Mathf.Lerp(5,8,((float)r)/72f)*10); float angleDelta = 2 * Mathf.PI / circleCount; GL.Begin(GL.TRIANGLE_STRIP); @@ -270,12 +290,10 @@ public class OvalCollider : ColliderBase //TSVector2 centerPos; public OvalCollider(TSVector2 axis, TSVector2 center,in FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) { - collider = new ColliderStructure() - { - colliderType = ColliderType.Oval, - rot = rotation, - center = center - }; + collider = ColliderStructure.CreateInstance(); + collider.colliderType = ColliderType.Oval; + collider.rot = rotation; + collider.center = center; SetAxis(axis); colliGroup = group; } @@ -380,43 +398,61 @@ public OvalCollider(T master, TSVector2 axis, TSVector2 center, FP rotation, Col } [Serializable] - public class PolygonCollider : ColliderBase + public class PolygonCollider : ColliderBase,IDisposable { - public FP rot; - public TSVector2[] vertexs,movedVertexs; - public TSVector2 centerPos; + public TSVector2[] vertexs; + public NativeArray movedVertexs; TSVector4 _boundingBox_=TSVector4.zero; public PolygonCollider() { //throw new System.NotImplementedException("必须为顶点赋值"); } + + public void Dispose() + { + if (movedVertexs.IsCreated) + { + movedVertexs.Dispose(); + } + } + public PolygonCollider(TSVector2[] vertex, TSVector2 center, FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) { - movedVertexs = new TSVector2[vertex.Length]; //边数是不能变的 - centerPos = center; + collider = ColliderStructure.CreateInstance(); + collider.colliderType = ColliderType.Polygon; + collider.rot = rotation; + collider.center = center; + movedVertexs = new NativeArray(vertex.Length,Allocator.Persistent,NativeArrayOptions.UninitializedMemory); //边数是不能变的 + CollisionManager.instance.BufferManager.RegisterCollider(ref collider,vertex.Length); SetRotation(rotation); colliGroup = group; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override ColliderStructure GetRealCollider() + { + return CollisionManager.instance.BufferManager.colliders[collider.uniqueID]; + } + public override void SetRotation(FP rotRad) { - rot = rotRad; + collider.rot = rotRad; RotateVertexs(); }//没错,圆形没有旋转 public override void SetCenter(in TSVector2 center) { - MoveDeltaPos(center-centerPos); - centerPos = center; + MoveDeltaPos(center-collider.center); + collider.center = center; } public override TSVector2 GetCenter() { - return centerPos; + return collider.center; } void RotateVertexs() { TSVector4 tSVector4 = new TSVector4(FP.MaxValue, FP.MinValue, FP.MinValue, FP.MaxValue); for (int i = movedVertexs.Length - 1; i >= 0; --i) { - movedVertexs[i] = vertexs[i].RotateRad(rot) + centerPos; + movedVertexs[i] = vertexs[i].RotateRad(collider.rot) + collider.center; if (movedVertexs[i].x > tSVector4.z) { tSVector4.z= movedVertexs[i].x; @@ -434,6 +470,7 @@ void RotateVertexs() tSVector4.w = movedVertexs[i].y;//最小值,代表下方点 } } + CollisionManager.instance.BufferManager.ModifyCollider(collider,movedVertexs); _boundingBox_ = tSVector4; } void MoveDeltaPos(TSVector2 pos) @@ -442,14 +479,17 @@ void MoveDeltaPos(TSVector2 pos) { movedVertexs[i] += pos; } + //标注顶点缓冲区的移动 + CollisionManager.instance.BufferManager.ModifyCollider(collider,movedVertexs); _boundingBox_.x += pos.x; _boundingBox_.y += pos.y; _boundingBox_.z += pos.x; _boundingBox_.w += pos.y; } - public override TSVector2 GetFurthestPoint(TSVector2 direction) + /*public override TSVector2 GetFurthestPoint(in TSVector2 _direction) { - direction = direction.normalized; + TSVector2 result = base.GetFurthestPoint(_direction); + var direction = _direction.normalized; FP maxLen = FP.MinValue,len; TSVector2 pos = movedVertexs[0]; for(int i = movedVertexs.Length-1; i >= 0; --i) @@ -460,7 +500,19 @@ public override TSVector2 GetFurthestPoint(TSVector2 direction) pos = movedVertexs[i]; } } + if (result != pos) + { + var arr = ColliderVertexBuffer.instancedBuffer.ToArray(); + StringBuilder sb = new StringBuilder(); + sb.AppendJoin(", ", arr); + Debug.Log(result+" "+pos+" "+sb); + } return pos; + }*/ + public override void Destroy() + { + CollisionManager.instance.BufferManager.DeleteCollider(collider); + movedVertexs.Dispose(); } public override TSVector4 GetBoundingBox() @@ -476,11 +528,14 @@ public BoxCollider(TSVector2 widthHeight,TSVector2 center,FP rotation, Collision TSVector2 a = widthHeight * 0.5;//左下,左上,右上,右下 TSVector2 b = new TSVector2(a.x,-a.y); vertexs = new TSVector2[4] {-a,-b, a, b}; //边数是不能变的 - movedVertexs = new TSVector2[4]; //边数是不能变的 - centerPos = center; + movedVertexs = new NativeArray(4,Allocator.Persistent,NativeArrayOptions.UninitializedMemory); //边数是不能变的 + collider = ColliderStructure.CreateInstance(); + collider.colliderType = ColliderType.Polygon; + collider.rot = rotation; + collider.center = center; + CollisionManager.instance.BufferManager.RegisterCollider(ref collider,movedVertexs.Length); SetRotation(rotation); colliGroup = group; - } public override void DebugDisplayColliderShape(Color color) { @@ -520,8 +575,12 @@ public DiamondCollider(TSVector2 widthHeight, TSVector2 center, FP rotation, Col TSVector2 b = new TSVector2(widthHeight.x * 0.5, 0); TSVector2 c = new TSVector2(0, widthHeight.y * 0.5); vertexs = new TSVector2[4] { -b, c, b, -c }; //边数是不能变的 - movedVertexs = new TSVector2[4]; //边数是不能变的 - centerPos = center; + movedVertexs = new NativeArray(4,Allocator.Persistent,NativeArrayOptions.UninitializedMemory); //边数是不能变的 + collider = ColliderStructure.CreateInstance(); + collider.colliderType = ColliderType.Polygon; + collider.rot = rotation; + collider.center = center; + CollisionManager.instance.BufferManager.RegisterCollider(ref collider,movedVertexs.Length); SetRotation(rotation); colliGroup = group; } @@ -531,45 +590,43 @@ public DiamondCollider(TSVector2 widthHeight, TSVector2 center, FP rotation, Col //两个相同的圆中间连线 public class DoubleCircleCollider : ColliderBase { - public FP r; - protected TSVector2 centerPos; - public TSVector2 centerCircle1; - public TSVector2 centerCircle2; public DoubleCircleCollider(FP R, TSVector2 center1,TSVector2 center2, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) { + collider = ColliderStructure.CreateInstance(); + collider.colliderType = ColliderType.DoubleCircle; + collider.radius = R; SetCircleCenters(center1,center2); - r = R; colliGroup = group; } public override void SetRotation(FP rotRad) { }//没错,圆形没有旋转 public override void SetCenter(in TSVector2 center) { - TSVector2 delta = center - centerPos; - centerCircle1 += delta; - centerCircle2 += delta; - centerPos = center; + TSVector2 delta = center - collider.center; + collider.circleCenter1 += delta; + collider.circleCenter2 += delta; + collider.center = center; } - public void SetCircleCenters(TSVector2 center1,TSVector2 center2) { - - centerCircle1 = center1; - centerCircle2 = center2; - centerPos = (center1 + center2) * 0.5; + public void SetCircleCenters(in TSVector2 center1,in TSVector2 center2) + { + collider.circleCenter1 = center1; + collider.circleCenter2 = center2; + collider.center = (center1 + center2) * 0.5; } - public void SetCircleCenter2(TSVector2 center2) + public void SetCircleCenter2(in TSVector2 center2) { - centerCircle2 = center2; - centerPos = (centerCircle1 + center2) * 0.5; + collider.circleCenter2 = center2; + collider.center = (collider.circleCenter1 + center2) * 0.5; } - public void SetCircleCenter1(TSVector2 center1) + public void SetCircleCenter1(in TSVector2 center1) { - centerCircle1 = center1; - centerPos = (centerCircle2 + center1) * 0.5; + collider.circleCenter1 = center1; + collider.center = (collider.circleCenter2 + center1) * 0.5; } public override TSVector2 GetCenter() { - return centerPos; + return collider.center; } - public override TSVector2 GetFurthestPoint(TSVector2 direction) + /*public override TSVector2 GetFurthestPoint(TSVector2 direction) { //d.normal* if (TSVector2.Dot(direction, centerCircle1-centerPos) > 0) @@ -580,39 +637,41 @@ public override TSVector2 GetFurthestPoint(TSVector2 direction) { return direction.normalized * r + centerCircle2; } - } + }*/ public override TSVector4 GetBoundingBox() { FP minX; FP minY; FP maxX; FP maxY; - if (centerCircle1.x where T : ICollideShape - { - public int cellSize = 64;//最小格子宽高 - public FP OneDivideCellSize; - public int depth = 6;//载入时的深度 - public int maxSize; - public int groupCnt = 1;//碰撞组的个数 - FP maxSizeFP,OneHalfMaxSizeFP; - FP[] log4Numbers, log2Numbers; - public TreeNode root = new TreeNode(); - public TreeNode[] treeNodeArr = new TreeNode[0];//用数组优化四叉树的读取 - //储存每个collider所在的坐标格子位置, - public Dictionary colliderPositions = new Dictionary(); - //public HashSet[] unmanagedColliders; + public class CollisionManager:IDisposable { + public static void voidFunction(ColliderBase c) { } + private static CollisionManager _instance; - protected void __init__(int dp = 6, int cw = 64) { - cellSize = cw; - depth = dp; - maxSize = cw << (dp); - maxSizeFP = maxSize; - OneHalfMaxSizeFP = maxSizeFP * 0.5; - OneDivideCellSize = FP.One / (FP)cw; - log4Numbers = new FP[depth + 1]; - log2Numbers = new FP[depth + 1]; - groupCnt = Enum.GetValues(typeof(CollisionManager.CollisionGroup)).Length; - for (int i = 1; i <= depth; i++) - { - //0 2 4 6 8 - log4Numbers[i] = FP.One / (FP)(i << 1); - log2Numbers[i] = FP.One / (FP)(i); - } - /*unmanagedColliders = new HashSet[groupCnt]; - for (int i = 0; i < groupCnt; i++) - { - unmanagedColliders[i] = new HashSet(); - }*/ - BuildTree(); - } - public static int FastPow(int a, int n) + public static CollisionManager instance { - int ans = 1; // 赋值为乘法单位元,可能要根据构造函数修改 - while (n != 0) + get => _instance; + set { - if ((n & 1) != 0) + if (_instance != null&&_instance!=value) { - ans *= a; // 这里就最好别用自乘了,不然重载完*还要重载*=,有点麻烦。 + _instance.Dispose(); } - n >>= 1; - a = a*a; + _instance = value; } - return ans; - } - /*public int CalcDepthCount(int dp) { - return (FastPow(4, dp+1)-1) / 3; - }*/ - public int CalcDepthCount(int dp) - { - return ((1<<((dp+1)<<1)) - 1) / 3;//等比数列求和 - } - //按照 - /* - root , - lt, - rt, - lb, - rb, - lt.lt, lt.rt,rt.lt,rt.rt, lt.lb, lt.rb,rt.lb,rt.rb , 4^n个 - 初始位置:4^0+...+4^(n-1) = 1*(1-4^n)/(1-4) - //以屏幕为左上角,坐标向右边和下面增加 - 坐标:floor(当前层左上坐标/当前层高度)*(最大层宽度/当前层宽度)+floor(当前左上坐标/当前层宽度) - */ - public int GetPosition(int curDepth,Vector2Int scaledPosition) - { - return CalcDepthCount(curDepth-1)+scaledPosition.y * (1 << (curDepth)) + scaledPosition.x; - } - //计算子四边形的缩放过的坐标 - /// - /// 把原始的四个边界从中间分成四份,然后再把坐标*2 - /// - /// 原始的四个边界 - /// - TSVector4[] splitRect(TSVector4 r) { - //originalRect *= 2; - /*return new TSVector4[] { - new TSVector4(originalRect.x,originalRect.y,(originalRect.z+originalRect.x)/2,(originalRect.w+originalRect.y)/2), - new TSVector4((originalRect.x+originalRect.z)/2,originalRect.y,(originalRect.x+originalRect.z)/2+(originalRect.z-originalRect.x)/2,(originalRect.w+originalRect.y)/2), - };*/ - /*originalRect.x += originalRect.x; - originalRect.y += originalRect.y; - originalRect.z += originalRect.x; - originalRect.w += originalRect.y;*/ - /* - x,y,x+(z-x)/2,y+(w-y)/2 - x+(z-x)/2,y,z,y+(w-y)/2 - x,y+(w-y)/2,x+(z-x)/2,w - x+(z-x)/2,y+(w-y)/2,z,w - - */ - /* - 2x,2y,x+z,y+w - x+z,2y,2z,y+w - 2x,y+w,x+z,2w - x+z,y+w,2z,2w - */ - /*return new TSVector4[] { - new TSVector4(originalRect.x,originalRect.y,originalRect.z,originalRect.w), - new TSVector4(originalRect.z,originalRect.y,originalRect.z+originalRect.z-originalRect.x,originalRect.w), - new TSVector4(originalRect.x,originalRect.w,originalRect.z,originalRect.w+originalRect.w-originalRect.y), - new TSVector4(originalRect.z,originalRect.w,originalRect.z+originalRect.z-originalRect.x,originalRect.w+originalRect.w-originalRect.y), - };*/ - FP a = r.x + r.x; - FP b = r.y + r.y; - FP c = r.x + r.z; - FP d = r.y + r.w; - FP e = r.z + r.z; - FP f = r.w + r.w; - return new TSVector4[] { - new TSVector4(a,b,c,d), - new TSVector4(c,b,e,d), - new TSVector4(a,d,c,f), - new TSVector4(c,d,e,f) - }; - } - //应该不是,直接用大小存吧…… - public class TreeNode { - public HashSet[] Values; - public TreeNode[] Children = new TreeNode[4]; - public TreeNode parent = null; } - TSVector4 TransAxis(TSVector4 vec) { - vec.y = OneHalfMaxSizeFP - vec.y; - vec.w = OneHalfMaxSizeFP - vec.w; - vec.x += OneHalfMaxSizeFP; - vec.z += OneHalfMaxSizeFP; - return vec; - } - int GetDepth(int width) { //如果是>=1的话也要放在上(更大的)一层比如64的大小(格子也是64)就应该放在128,不然可能会出界什么的。。。 - int layer = 0;//1 2 4 8 - while (width >> layer > 1) - { - layer++; - } - return depth - layer; - } - public struct positionInformation { - public int layer; - public Vector2Int mainPos; - public Vector2Int rightBottom; - - public override bool Equals(object obj) - { - return obj is positionInformation other && Equals(other); - } - public bool Equals(positionInformation other) - { - return this.layer == other.layer && - this.mainPos == other.mainPos && - this.rightBottom == other.rightBottom; - } - - public override int GetHashCode() - { - return HashCode.Combine(layer, mainPos, rightBottom); - } - - public static bool operator ==(positionInformation left, positionInformation right) - { - return left.Equals(right); - } - - public static bool operator !=(positionInformation left, positionInformation right) - { - return !(left == right); - } - - // New method to check if the current instance contains another instance's range - public bool Contains(positionInformation other) - { - return this.layer == other.layer && - this.mainPos.x <= other.mainPos.x && - this.mainPos.y <= other.mainPos.y && - this.rightBottom.x >= other.rightBottom.x && - this.rightBottom.y >= other.rightBottom.y; - } - public bool TrueContains(positionInformation other) - { - return this.layer == other.layer && - this.mainPos.x < other.mainPos.x && - this.mainPos.y < other.mainPos.y && - this.rightBottom.x > other.rightBottom.x && - this.rightBottom.y > other.rightBottom.y; - } - - // Overload >= operator to use the Contains method - public static bool operator >=(positionInformation left, positionInformation right) - { - return left.Contains(right); - } - public static bool operator <=(positionInformation left, positionInformation right) - { - return right.Contains(left); - } - public static bool operator >(positionInformation left, positionInformation right) - { - return left.TrueContains(right); - } - public static bool operator <(positionInformation left, positionInformation right) - { - return right.TrueContains(left); - } - } - //可能是一个或者四个坐标,插入一次或者四次 - public positionInformation GetCellIndex(TSVector4 rect) { - rect = TransAxis(rect);//乘1/最小格子大小可以得到64-->1 128 --> 2这样 - if (rect.x<0||rect.y<0||rect.z>maxSize||rect.w>maxSize) { - return new positionInformation { //出界了,这个应该放在第0层里面,不参与四叉树判断 - mainPos = Vector2Int.zero, - rightBottom = Vector2Int.zero, - layer = 0 - }; - } - rect *= OneDivideCellSize; - //获取应该放在哪一层 - int layer = GetDepth(TSMath.Ceil(TSMath.Max(rect.w - rect.y, rect.z - rect.x)).AsInt());//TSMath.Ceil(TSMath.Log2(TSMath.Max(rect.w - rect.y, rect.z - rect.x))).AsInt();//这个Log很慢,因为是定点数,自己写一个 - if (layer < 0) - { - return new positionInformation - { //出界了,这个应该放在第0层里面,不参与四叉树判断 - mainPos = Vector2Int.zero, - rightBottom = Vector2Int.zero, - layer = 0 - }; - } - int divide = depth - layer; - Vector2Int mainPos = new Vector2Int(rect.x.AsInt()>> divide, rect.y.AsInt()>> divide); - Vector2Int rightBottom = new Vector2Int((rect.z.AsInt() >> divide), (rect.w.AsInt() >> divide)); - return new positionInformation - { - mainPos = mainPos, - rightBottom = rightBottom, layer = layer - }; - } - /// - /// 根据坐标批量处理某个事 action传入的是 当前深度depth和坐标的参数 - /// - /// - /// - public void Manufacture(Action action,positionInformation area) - { - //对应级别的坐标 - Vector2Int nowPos = area.mainPos; - Vector2Int tar = area.rightBottom; - for(int i = nowPos.x; i <= tar.x; i++) - { - for (int j = nowPos.y;j<=tar.y;j++) { - Vector2Int pos = new Vector2Int(i,j); - action(area.layer,pos); - } - } - } - //带break的 - public bool Manufacture(Func action, positionInformation area) + public void Dispose() { - //对应级别的坐标 - Vector2Int nowPos = area.mainPos; - Vector2Int tar = area.rightBottom; - for (int i = nowPos.x; i <= tar.x; i++) + foreach (var colliderBase in colliders) { - for (int j = nowPos.y; j <= tar.y; j++) + if (colliderBase is IDisposable c) { - Vector2Int pos = new Vector2Int(i, j); - if(!action(area.layer, pos)) { return false; } + c.Dispose(); } } - return true; + BufferManager.Dispose(); } - public void RemoveCollider(T obj,bool insert=false) { - int grp = (int)obj.colliGroup; - if (colliderPositions.ContainsKey(obj)) - { - Manufacture((layer,posInArr) => { - //Debug.Log(layer+ " "+posInArr); - var objs = treeNodeArr[GetPosition(layer, posInArr)].Values[grp]; - objs.Remove(obj); - }, colliderPositions[obj]); - colliderPositions.Remove(obj); - }/*else - { - unmanagedColliders[grp].Remove(obj); - }*/ - } - public void ClearAllCollider() - { - foreach (var obj in colliderPositions) - { - RemoveCollider(obj.Key); - } - /*foreach (var obj in unmanagedColliders) { - obj.Clear(); - }*/ - } - public void InsertCollider(T obj) { - int grp = (int)obj.colliGroup; - TSVector4 rect = obj.GetBoundingBox();//获取物体的包围盒 - positionInformation positions = GetCellIndex(rect), - oldPosition; - bool hasObj = colliderPositions.ContainsKey(obj),flag=true; - if (hasObj) {//如果position和原position在是包含关系,这里不能替换成大于,因为 会比较图层是否相等 - oldPosition = colliderPositions[obj]; - if (!(oldPosition <= positions)) - { - RemoveCollider(obj,true); - } else if (oldPosition==positions) { - flag = false; - } - } - colliderPositions[obj] = positions; - if (flag){ - Manufacture((layer, posInArr) => { - var objs = treeNodeArr[GetPosition(layer, posInArr)].Values[grp]; - objs.Add(obj); - }, positions); - } - } - void BuildTree() { - int curDepth = 0; - int needCnt = CalcDepthCount(depth); - root = new TreeNode(); - treeNodeArr = new TreeNode[needCnt]; - TSVector4 nowRect = new TSVector4(0,0,1,1);//四边形的边框 - Dictionary> errorChecker = new Dictionary>(); - void dfs(TreeNode node=null) { - treeNodeArr[GetPosition(curDepth,new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt()))] = node;//存入数组 - if(errorChecker.ContainsKey(GetPosition(curDepth, new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt())))) - { - var conf = errorChecker[GetPosition(curDepth, new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt()))]; - if(curDepth!=conf.Item1||conf.Item2!= new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt())) - { - Debug.LogError("Big Append Error" + " " + curDepth + " " + new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt()) + " conflict with " + conf.Item1 + " " + conf.Item2); - - } - } - else - { - errorChecker.Add(GetPosition(curDepth, new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt())), new Tuple(curDepth, new Vector2Int(nowRect.x.AsInt(), nowRect.y.AsInt()))); - } - /*if (curDepth == 2) { - Debug.Log(curDepth+" "+nowRect); - }*/ - //初始化碰撞组 - node.Values = new HashSet[groupCnt]; - for (int j = 0; j < groupCnt; j++) - { - node.Values[j] = new HashSet(); - } - - if (curDepth>=depth) - { - return; - } - TSVector4 tmpRect = nowRect; - TSVector4[] splited = splitRect(tmpRect); - /*StringBuilder sb = new StringBuilder(); - sb.Append(curDepth); - for (int i = 0;i[] groupedColliders;//这个到时候要改成LinkedHashSet之类的东西。。。 public HashSet colliders = new HashSet(); @@ -1247,6 +950,7 @@ public static void voidFunction(ColliderBase c) { } public HashSet tmpDrawingHasCheckedObjectsInCurFrame = new HashSet();//用来debug有哪些物体当前帧被检查碰撞 //readonly bool multiCollisionOptimize = false;//先关掉多碰撞优化,测试功能 private Material _shapeMaterial;//测试 + public ColliderVertexBuffer BufferManager = new ColliderVertexBuffer(); public CollisionManager() { groupedColliders = new LinkedHashSet[groupCnt]; for (int i = 0; i < groupCnt; i++) { @@ -1387,6 +1091,8 @@ public void RemoveShape(ColliderBase collider) { int grp = (int)collider.colliGroup; groupedColliders[grp].Remove(collider); } + //调用销毁清理函数 + collider.Destroy(); colliders.Remove(collider); } public void SetCenter(in TSVector2 Pos,ColliderBase shape) diff --git a/Assets/ColliderStructure.cs b/Assets/ColliderStructure.cs index 54c6171..92044e2 100644 --- a/Assets/ColliderStructure.cs +++ b/Assets/ColliderStructure.cs @@ -1,10 +1,13 @@ using System; +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Core.Algorithm; using TrueSync; using Unity.Burst; using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using UnityEngine.UIElements; namespace ZeroAs.DOTS.Colliders { @@ -16,8 +19,10 @@ public enum ColliderType DoubleCircle, } [StructLayout(LayoutKind.Sequential)] - public struct ColliderStructure + public struct ColliderStructure:IEquatable { + private static int _globalIDCounter = 0; + public ColliderType colliderType; public TSVector2 center; #region 圆形,和双头圆形 @@ -28,7 +33,15 @@ public struct ColliderStructure public FP b2Dividea2,rot; #endregion #region 多边形 - public int vertexStartIndex, vertexCount; + + /// + /// 目前进行过修改的vertexStartIndex没同步到主线程上!!! + /// + public int vertexStartIndex; + /// + /// 注意,vertexCount不可变 + /// + public int vertexCount,uniqueID;//indexInArray若设置为小于0就代表会被删除 #endregion #region 双头圆形 public TSVector2 circleCenter1{ @@ -44,12 +57,27 @@ public TSVector2 circleCenter2{ set => this.SqrAxis = value; } #endregion + + + public static ColliderStructure CreateInstance() + { + var t = new ColliderStructure + { + uniqueID = _globalIDCounter++ + }; + return t; + } + + public bool Equals(ColliderStructure other) + { + return this.uniqueID==other.uniqueID; + } } [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] public struct GetFurthestPointExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] public static void RotateRad(out TSVector2 result, in TSVector2 self, in FP rad) { FP cos = FP.FastCos(rad); @@ -59,35 +87,28 @@ public static void RotateRad(out TSVector2 result, in TSVector2 self, in FP rad) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] public static void Negate(ref FP val) { val._serializedValue=val._serializedValue == MathBurstedFix.MIN_VALUE ? MathBurstedFix.MaxValue : (-val._serializedValue); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] public static void Negate(ref TSVector2 val) { Negate(ref val.x); Negate(ref val.y); } - static NativeArray points - { - get - { - throw new NotImplementedException(); - } - } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] public static void Circle(out TSVector2 result,in TSVector2 center,in TSVector2 direction,in FP radius) { result = center + direction.normalized*radius; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] public static void Oval(out TSVector2 result, in TSVector2 _direction, in TSVector2 centerPos,in FP rot,in TSVector2 Axis,in TSVector2 SqrAxis,in FP b2Dividea2) { @@ -138,16 +159,17 @@ public static void Oval(out TSVector2 result, in TSVector2 _direction, return; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] - public static void Polygon(out TSVector2 result, in TSVector2 _direction, in NativeArray movedVertexs,int offset,int length) + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + public static void Polygon(out TSVector2 result, in TSVector2 _direction, in NativeArray.ReadOnly movedVertexs,int offset,int length) { TSVector2 direction = _direction.normalized; FP maxLen,len; maxLen._serializedValue = MathBurstedFix.MinValue; TSVector2 pos = movedVertexs[offset]; - int len_ = offset + length; - for(int i = len_-1; i >= 0; --i) + int len_ = length; + for(int ia = len_-1; ia >= 0; --ia) { + int i = offset+ia; if((len= TSVector2.Dot(direction, movedVertexs[i])) > maxLen) { maxLen = len; @@ -157,7 +179,7 @@ public static void Polygon(out TSVector2 result, in TSVector2 _direction, in Nat result= pos; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] public static void DoubleCircle(out TSVector2 result,in TSVector2 direction,in TSVector2 centerCircle1,in TSVector2 centerCircle2,in FP r,in TSVector2 centerPos) { //d.normal* @@ -172,7 +194,7 @@ public static void DoubleCircle(out TSVector2 result,in TSVector2 direction,in T } [MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] - public static void GetFurthestPoint(out TSVector2 result, in ColliderStructure structure,in TSVector2 direction) + public static void GetFurthestPoint(out TSVector2 result, in ColliderStructure structure,in TSVector2 direction,in NativeArray.ReadOnly buffer) { switch (structure.colliderType) { @@ -183,8 +205,10 @@ public static void GetFurthestPoint(out TSVector2 result, in ColliderStructure s Oval(out result,direction,structure.center,structure.rot,structure.Axis,structure.SqrAxis,structure.b2Dividea2); return; case ColliderType.Polygon: - Polygon(out result,direction,points,structure.vertexStartIndex,structure.vertexCount); + { + Polygon(out result,direction, buffer,structure.vertexStartIndex,structure.vertexCount); return; + } case ColliderType.DoubleCircle: DoubleCircle(out result,direction,structure.circleCenter1,structure.circleCenter2,structure.radius,structure.center); return; @@ -193,12 +217,12 @@ public static void GetFurthestPoint(out TSVector2 result, in ColliderStructure s } } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] - public static void SupportFunc(out TSVector2 result,in ColliderStructure structure1,in ColliderStructure structure2,in TSVector2 direciton) { - GetFurthestPoint(out var resTmp,structure1,direciton); + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + public static void SupportFunc(out TSVector2 result,in ColliderStructure structure1,in ColliderStructure structure2,in TSVector2 direciton,in NativeArray.ReadOnly buffer) { + GetFurthestPoint(out var resTmp,structure1,direciton,buffer); TSVector2 negateDirection = direciton; Negate(ref negateDirection); - GetFurthestPoint(out var resTmp2, structure2, negateDirection); + GetFurthestPoint(out var resTmp2, structure2, negateDirection,buffer); //Debug.Log("direction: "+direciton+" "+ shape1.GetFurthestPoint(direciton)+" "+shape2.GetFurthestPoint(-direciton)); result=resTmp-resTmp2; } @@ -207,7 +231,7 @@ public static void SupportFunc(out TSVector2 result,in ColliderStructure structu public struct CollideExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] public static void Abs(out FP result,in FP value) { if (value._serializedValue == MathBurstedFix.MIN_VALUE) { result._serializedValue= MathBurstedFix.MaxValue; @@ -219,7 +243,7 @@ public static void Abs(out FP result,in FP value) { result._serializedValue = (value._serializedValue + mask) ^ mask; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] public static void TripleProduct2d(out TSVector2 result,in TSVector2 a,in TSVector2 b,in TSVector2 c) { FP sign = (a.x * b.y - a.y * b.x); FP cY = c.y; @@ -227,8 +251,8 @@ public static void TripleProduct2d(out TSVector2 result,in TSVector2 a,in TSVect result = new TSVector2(cY, c.x) * sign; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] - public static bool GJK(in ColliderStructure shape1, in ColliderStructure shape2) { + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + public static bool GJK(in ColliderStructure shape1, in ColliderStructure shape2,in NativeArray.ReadOnly buffer) { /* #两个形状s1,s2相交则返回True。所有的向量/点都是二维的,例如([x,y]) #第一步:选择一个初始方向,这个初始方向可以是随机选择的,但通常来说是两个形状中心之间的向量,即: @@ -238,10 +262,10 @@ public static bool GJK(in ColliderStructure shape1, in ColliderStructure shape2) TSVector2 direction = (shape2.center - shape1.center).normalized; //#第二步:找到支撑点,即第一个支撑点(即闵可夫斯基差的边上的点之一……) NativeArray Simplex = new NativeArray(3,Allocator.Temp);//单纯形数组,最多只能是3个 - GetFurthestPointExtensions.SupportFunc(out tmpVec,shape1, shape2, direction); + GetFurthestPointExtensions.SupportFunc(out tmpVec,shape1, shape2, direction,buffer); Simplex[0] = tmpVec; int simplexLastInd = 1; - int interateTimeMax = 100;//最大迭代次数 + int interateTimeMax = 10;//最大迭代次数 //#第三步:找到第一个支撑点后,以第一个支撑点为起点指向原点O的方向为新方向d direction = tmpVec;//= -Simplex[0].normalized GetFurthestPointExtensions.Negate(ref direction); @@ -249,7 +273,7 @@ public static bool GJK(in ColliderStructure shape1, in ColliderStructure shape2) //#第四步:开始循环,找下一个支撑点 while (interateTimeMax-- > 0) { - GetFurthestPointExtensions.SupportFunc(out var A,shape1,shape2,direction); + GetFurthestPointExtensions.SupportFunc(out var A,shape1,shape2,direction,buffer); //因为A点是闵可夫斯基差形状在给定方向的最远点,如果那个点没有超过原点,就不想交 //#当新的支撑点A没有包含原点,那我们就返回False,即两个形状没有相交 if (TSVector2.Dot(A,direction)<0) @@ -333,14 +357,14 @@ o 为了得到新的方向 𝑑,我们需要一个向量,这个向量既垂 return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] public static bool CircleCollideWithCircle(in ColliderStructure circle1,in ColliderStructure circle2) { TSVector2.DistanceSquared(in circle1.center, in circle2.center, out var dis); return dis <= TSMath.FastQuadratic(circle1.radius + circle2.radius); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] public static bool CircleCollideWithDoubleCircle(in ColliderStructure doubleCircle,in ColliderStructure circle2) { TSVector2 centerShape = circle2.center; @@ -374,5 +398,389 @@ public static bool CircleCollideWithDoubleCircle(in ColliderStructure doubleCirc return deltaPos.LengthSquared() - TSMath.FastQuadratic(distance) <= TSMath.FastQuadratic(doubleCircle.radius+circle2.radius); } } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false, OptimizeFor = OptimizeFor.Performance)] + public static bool CheckCollide(in ColliderStructure shape1, in ColliderStructure shape2,in NativeArray.ReadOnly buffer) + { + // 圆形 vs 圆形 + if (shape1.colliderType == ColliderType.Circle && + shape2.colliderType == ColliderType.Circle) + { + return CircleCollideWithCircle(shape1, shape2); + } + + // 双圆 vs 圆形(处理两种顺序情况) + if ((shape1.colliderType == ColliderType.DoubleCircle && + shape2.colliderType == ColliderType.Circle) || + (shape2.colliderType == ColliderType.DoubleCircle && + shape1.colliderType == ColliderType.Circle)) + { + var doubleCircle = shape1.colliderType == ColliderType.DoubleCircle ? shape1 : shape2; + var circle = shape1.colliderType == ColliderType.Circle ? shape1 : shape2; + return CircleCollideWithDoubleCircle(doubleCircle, circle); + } + + // 其他所有情况使用GJK算法 + return GJK(shape1, shape2,buffer); + } + } + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public class ColliderVertexBuffer:IDisposable{ + public static NativeArray.ReadOnly instancedBuffer => CollisionManager.instance.BufferManager.vertices.AsReadOnly(); + public NativeHashMap colliders = new NativeHashMap(16,Allocator.Persistent); + public NativeList vertices = new NativeList(Allocator.Persistent); + + public int removedDelta = 0; + //public SegmentManager removedIndexs = new SegmentManager(Allocator.Persistent); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + static void RegisterCollider( + in NativeHashMap colliders,in NativeList vertices, + ref ColliderStructure colli,in int vertexCount + ) + { + colli.vertexCount=vertexCount; + //注意目前没同步到主线程上 + colli.vertexStartIndex = vertices.Length; + colliders.Add(colli.uniqueID,colli); + + //不需要清理内存,因为马上就会被设置 + vertices.Resize(colli.vertexStartIndex+vertexCount,NativeArrayOptions.UninitializedMemory); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RegisterCollider(ref ColliderStructure colli,in int vertexCount) + { + RegisterCollider(colliders,vertices,ref colli,vertexCount); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + static void ModifyCollider( + ref NativeHashMap colliders,ref NativeList vertices, + in ColliderStructure colli, in NativeArray modify + ) + { + //获取实际上的colli + var realColli = colliders[colli.uniqueID]; + NativeArray.Copy(modify,0,vertices,realColli.vertexStartIndex,realColli.vertexCount); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ModifyCollider(in ColliderStructure colli, in NativeArray modify) + { + ModifyCollider(ref colliders,ref vertices,in colli,modify); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + static void DeleteCollider(ref int removedDelta,ref NativeHashMap colliders,in ColliderStructure colli) + { + removedDelta += colli.vertexCount; + //var realColli = colliders[colli.uniqueID]; + //removedIndexs.Add(realColli.vertexStartIndex,realColli.vertexStartIndex+realColli.vertexCount-1); + colliders.Remove(colli.uniqueID); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + public void DeleteCollider(in ColliderStructure colli) + { + DeleteCollider(ref removedDelta,ref colliders,colli); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")] + static void CheckIndexCount(int index, int count,int length) + { + if (count < 0) + { + throw new ArgumentOutOfRangeException($"Value for count {count} must be positive."); + } + + if (index < 0) + { + throw new IndexOutOfRangeException($"Value for index {index} must be positive."); + } + + if (index > length) + { + throw new IndexOutOfRangeException($"Value for index {index} is out of bounds."); + } + + if (index + count > length) + { + throw new ArgumentOutOfRangeException($"Value for count {count} is out of bounds."); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + public static void MoveLeft(in NativeList arr,int srcStart, int count,int offset) where T : unmanaged + { + CheckIndexCount(srcStart, count,arr.Length); + var arrayPointer = arr.AsArray(); + NativeArray.Copy(arrayPointer,srcStart,arrayPointer,srcStart-offset,count); + } + /// + /// 移除vertexbuffer的洞洞,注意这是个比较消耗性能的操作,并且要在主线程中同步所有的结构体的顶点位置?(提供同步方法,如果需要的话可以同步,貌似目前不需要,只是会throw出错而已) + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + public static unsafe void CompactVertexBuffers( + ref int removedDelta,ref NativeHashMap colliders, + ref NativeList vertices + ) + { + if (!vertices.IsCreated) + { + throw new NullReferenceException("vertices数组未创建"); + } + NativeList newList = new NativeList(vertices.Length-removedDelta,Allocator.Persistent); + var listArrayPointer = vertices.GetUnsafeReadOnlyPtr(); + var _sizeof_ = UnsafeUtility.SizeOf(); + foreach (var ele in colliders) + { + ref var val = ref ele.Value; + var newStartIndex = newList.Length; + newList.AddRangeNoResize(((byte*)listArrayPointer+(_sizeof_*val.vertexStartIndex)), val.vertexCount); + val.vertexStartIndex = newStartIndex; + } + vertices.Dispose(); + vertices = newList; + removedDelta = 0; + } + /// + /// 移除vertexbuffer的洞洞,注意这是个比较消耗性能的操作,并且要在主线程中同步所有的结构体的顶点位置?(提供同步方法,如果需要的话可以同步,貌似目前不需要,只是会throw出错而已) + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + public void CompactVertexBuffers() + { + CompactVertexBuffers(ref removedDelta,ref colliders,ref vertices); + } + + public void Dispose() + { + if(vertices.IsCreated) + vertices.Dispose(); + //removedIndexs.Dispose(); + if (colliders.IsCreated) + { + colliders.Dispose(); + } + + } + /*[MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public void ClearDeletedColliders() + { + int len = colliders.Length; + int thisTimeDeletionCount = 0;//这次删多少个 + int gappedPosition = -1; + int gappedVertexPosition = -1; + int offset = 0; + int vertexOffset = 0; + int lastAvailableVertexEnd = 0; + for (int i =0;i=0) + { + MoveLeft(vertices,gappedVertexPosition, + lastAvailableVertexEnd-(gappedVertexPosition-vertexOffset),vertexOffset + ); + MoveLeft(colliders,gappedPosition,i-gappedPosition,offset); + //colliders.CopyFrom(); + gappedPosition = -1; + gappedVertexPosition = -1; + } + thisTimeDeletionCount++; + } + else if(thisTimeDeletionCount>0) + { + gappedPosition = i; + gappedVertexPosition = ele.vertexStartIndex; + offset += thisTimeDeletionCount; + //lastAvailableVertexEnd是虚假偏移值,是假装已经偏移过后得到的顶点结束位置 + vertexOffset = ele.vertexStartIndex - lastAvailableVertexEnd; + thisTimeDeletionCount = 0; + } + + if (ele.indexInArray >= 0) + { + ele.indexInArray -= offset; + ele.vertexStartIndex -= vertexOffset; + lastAvailableVertexEnd = ele.vertexStartIndex + ele.vertexCount; + } + } + //最后是有重合的 + if (gappedPosition>=0) + { + MoveLeft(vertices,gappedVertexPosition, + lastAvailableVertexEnd-(gappedVertexPosition-vertexOffset),vertexOffset + ); + MoveLeft(colliders,gappedPosition,colliders.Length-gappedPosition,offset); + //colliders.CopyFrom(); + //gappedPosition = -1; + //gappedVertexPosition = -1; + } + //最后一个有效位置的起始点 + //会变小,所以不用清除内存 + colliders.Resize(colliders.Length-offset-thisTimeDeletionCount,NativeArrayOptions.UninitializedMemory); + vertices.Resize(lastAvailableVertexEnd,NativeArrayOptions.UninitializedMemory); + }*/ + } + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public struct SegmentManager : IDisposable + { + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public struct Segment + { + public readonly int Start; + public readonly int End; + + public Segment(int start, int end) + { + Start = start; + End = end; + } + + public override string ToString() + { + return $"({Start}, {End})"; + } + } + private NativeList segments; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public void Add(int start, int end) + { + // 确保起点小于等于终点 + if (start > end) + { + (start, end) = (end, start); + } + + // 找到插入位置 + int insertIndex = FindInsertIndex(start); + + int left = insertIndex - 1; + int right = insertIndex; + + int currentStart = start; + int currentEnd = end; + + // 向左合并线段 + while (left >= 0 && segments[left].End >= currentStart-1) + { + currentStart = Math.Min(segments[left].Start, currentStart); + currentEnd = Math.Max(segments[left].End, currentEnd); + left--; + } + + int len = segments.Length; + // 向右合并线段 + while (right < len && segments[right].Start <= currentEnd+1) + { + currentEnd = Math.Max(segments[right].End, currentEnd); + right++; + } + + + // 删除被合并的线段并插入新线段 + if (left + 1 < len&&right - (left + 2)>=0) + { + segments.RemoveRange(left + 2, right - (left + 2)); + } + else + { + segments.ResizeUninitialized(len+1); + ColliderVertexBuffer.MoveLeft(segments,left+1,len-left-1,-1); + } + segments[left + 1]=new Segment(currentStart, currentEnd); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true, OptimizeFor = OptimizeFor.Performance)] + public void AddPoint(int point) + { + // 找到插入位置 + int insertIndex = FindInsertIndex(point); + + int left = insertIndex - 1; + int right = insertIndex; + + int currentStart = point; + int currentEnd = point; + + // 向左合并线段 + if (left >= 0 && segments[left].End >= currentStart - 1) + { + currentStart = Math.Min(segments[left].Start, currentStart); + currentEnd = Math.Max(segments[left].End, currentEnd); + left--; + } + + int len = segments.Length; + // 向右合并线段 + if (right < len && segments[right].Start <= currentEnd + 1) + { + currentEnd = Math.Max(segments[right].End, currentEnd); + right++; + } + + // 删除被合并的线段并插入新线段 + if (left + 1 < len&&right - (left + 2)>=0) + { + segments.RemoveRange(left + 2, right - (left + 2)); + } + else + { + segments.ResizeUninitialized(len+1); + ColliderVertexBuffer.MoveLeft(segments,left+1,len-left-1,-1); + } + segments[left + 1]=new Segment(currentStart, currentEnd); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + private int FindInsertIndex(int s) + { + int low = 0; + int high = segments.Length - 1; + int index = segments.Length; // 默认插入到最后 + + while (low <= high) + { + int mid = (low + high) / 2; + if (segments[mid].Start > s) + { + index = mid; + high = mid - 1; + } + else + { + low = mid + 1; + } + } + + return index; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public void Clear() + { + segments.Clear(); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SegmentManager(Allocator allocator) + { + segments = new NativeList(allocator); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = true, OptimizeFor = OptimizeFor.Performance)] + public void Dispose() + { + segments.Dispose(); + } } } \ No newline at end of file diff --git a/Assets/ColliderTester.cs b/Assets/ColliderTester.cs new file mode 100644 index 0000000..0e2b481 --- /dev/null +++ b/Assets/ColliderTester.cs @@ -0,0 +1,185 @@ +using System; +using Core.Algorithm; +using UnityEngine; +using ZeroAs.DOTS.Colliders; +using UnityEngine; +using TrueSync; +using System.Collections.Generic; +using BoxCollider = Core.Algorithm.BoxCollider; + +namespace DefaultNamespace +{ + + [RequireComponent(typeof(MeshRenderer))] + public class ColliderTester : MonoBehaviour + { + public enum MoveMode { Keyboard, Circular, Horizontal, Custom } + + [Header("Collider Settings")] + public ColliderType colliderType = ColliderType.Circle; + public FP radius = 1; + public TSVector2 boxSize = new TSVector2(2, 2); + public TSVector2 ovalAxis = new TSVector2(2, 1); + public TSVector2 doubleCircleOffset = new TSVector2(1, 0); + + [Header("Movement Settings")] + public MoveMode moveMode = MoveMode.Keyboard; + public FP moveSpeed = 5; + public FP rotationSpeed = 90; + public FP amplitude = 3; // For horizontal/circular motion + public FP frequency = 1; + + private CollisionController controller; + private MeshRenderer meshRenderer; + private TSVector2 startPosition; + private FP currentRotation; + private FP timeCounter; + + void Start() + { + meshRenderer = GetComponent(); + startPosition = transform.position.ToTSVector2(); + CreateCollider(); + } + + void CreateCollider() + { + TSVector2 pos = transform.position.ToTSVector2(); + ColliderBase collider; + switch (colliderType) + { + case ColliderType.Circle: + collider = new CircleCollider(radius, pos); + break; + case ColliderType.Oval: + collider = new OvalCollider(ovalAxis, pos, 0); + break; + case ColliderType.DoubleCircle: + collider = new DoubleCircleCollider( + radius, + pos - doubleCircleOffset, + pos + doubleCircleOffset + ); + break; + case ColliderType.Polygon: + collider = new BoxCollider(boxSize, pos, 0); + break; + default: + throw new Exception("not initialized"); + } + collider.enabled = true; + if (moveMode == MoveMode.Keyboard) + { + collider.colliGroup = CollisionManager.CollisionGroup.Default; + } + else + { + collider.colliGroup = CollisionManager.CollisionGroup.Bullet; + } + controller = new CollisionController(collider); + if (moveMode == MoveMode.Keyboard) + { + controller.AddListener(false, (obj) => + { + meshRenderer.material.color=Color.red; + Debug.Log("collide enter"); + },CollisionManager.voidFunction,(obj) => + { + meshRenderer.material.color=Color.green; + Debug.Log("collide exit"); + },CollisionManager.CollisionGroup.Bullet); + } + } + + void Update() + { + if (Input.GetKey(KeyCode.K)) + { + currentRotation+=rotationSpeed*Time.deltaTime*Mathf.Deg2Rad; + foreach (var controllerCollider in controller.Colliders) + { + controllerCollider.SetRotation(currentRotation); + } + } + + HandleMovement(Time.deltaTime); + } + + void HandleMovement(float deltaTime) + { + timeCounter += deltaTime * frequency; + + switch (moveMode) + { + case MoveMode.Keyboard: + KeyboardControl(deltaTime); + break; + case MoveMode.Circular: + CircularMotion(); + break; + case MoveMode.Horizontal: + HorizontalMotion(); + break; + case MoveMode.Custom: + CustomMotion(); + break; + } + gameObject.transform.position = startPosition.ToVector(); + gameObject.transform.position += Vector3.forward*10; + } + + void KeyboardControl(float deltaTime) + { + Vector2 input = new Vector2( + Input.GetAxisRaw("Horizontal"), + Input.GetAxisRaw("Vertical") + ).normalized; + + TSVector2 movement = input.ToTSVector2() * moveSpeed * deltaTime; + startPosition += movement; + controller.SetCenter(startPosition); + } + + void CircularMotion() + { + currentRotation += rotationSpeed * Time.deltaTime; + TSVector2 offset = new TSVector2( + TSMath.Cos(currentRotation * Mathf.Deg2Rad) * amplitude, + TSMath.Sin(currentRotation * Mathf.Deg2Rad) * amplitude + ); + controller.SetCenter(startPosition + offset); + } + + void HorizontalMotion() + { + FP xOffset = TSMath.Sin(timeCounter) * amplitude; + controller.SetCenter(startPosition + new TSVector2(xOffset, 0)); + } + + void CustomMotion() + { + // 示例:8字形运动 + FP x = TSMath.Sin(timeCounter) * amplitude; + FP y = TSMath.Sin(2 * timeCounter) * amplitude / 2; + controller.SetCenter(startPosition + new TSVector2(x, y)); + } + + + + void OnDestroy() + { + if (controller != null) + { + controller.Destroy(); + } + } + + /*private void OnRenderObject() + { + foreach (var controllerCollider in controller.Colliders) + { + controllerCollider.DebugDisplayColliderShape(meshRenderer.material.color); + } + }*/ + } +} \ No newline at end of file diff --git a/Assets/ColliderTester.cs.meta b/Assets/ColliderTester.cs.meta new file mode 100644 index 0000000..624a72a --- /dev/null +++ b/Assets/ColliderTester.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ea915761c8274bf983b476e4ad15da36 +timeCreated: 1744470894 \ No newline at end of file diff --git a/Assets/NuGet/Editor/NuGetForUnity.PluginAPI.xml b/Assets/NuGet/Editor/NuGetForUnity.PluginAPI.xml index eb40c81..c9b4dbd 100644 --- a/Assets/NuGet/Editor/NuGetForUnity.PluginAPI.xml +++ b/Assets/NuGet/Editor/NuGetForUnity.PluginAPI.xml @@ -80,7 +80,7 @@ NugetForUnity will call this method automatically so you can tell it what custom functionalities your plugin is providing. - The registry where extension points can be registered to. + The registry where extension vertices can be registered to. diff --git a/Assets/Scenes/New Folder.meta b/Assets/Scenes/New Folder.meta new file mode 100644 index 0000000..7e68f5d --- /dev/null +++ b/Assets/Scenes/New Folder.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9f62fe42e87b122428bcb90a341606a6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/New Material.mat b/Assets/Scenes/New Material.mat new file mode 100644 index 0000000..e5c79f7 --- /dev/null +++ b/Assets/Scenes/New Material.mat @@ -0,0 +1,135 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: New Material + m_Shader: {fileID: 10755, guid: 0000000000000000f000000000000000, type: 0} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 + - _GlossMapScale: 0 + - _Glossiness: 0 + - _GlossyReflections: 0 + - _Metallic: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.005 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Smoothness: 0.5 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _WorkflowMode: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 1, g: 1, b: 1, a: 1} + - _Color: {r: 0.4056604, g: 0.4056604, b: 0.4056604, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &166495376294266923 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 9 diff --git a/Assets/Scenes/New Material.mat.meta b/Assets/Scenes/New Material.mat.meta new file mode 100644 index 0000000..2a39cdd --- /dev/null +++ b/Assets/Scenes/New Material.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cb388a83031c8b5449b266658342ab83 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/New Scene.unity b/Assets/Scenes/New Scene.unity new file mode 100644 index 0000000..81960cb --- /dev/null +++ b/Assets/Scenes/New Scene.unity @@ -0,0 +1,708 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 1 + m_PVRFilteringGaussRadiusAO: 1 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &596138205 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 596138207} + - component: {fileID: 596138206} + - component: {fileID: 596138208} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &596138206 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 596138205} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 1 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &596138207 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 596138205} + serializedVersion: 2 + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!114 &596138208 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 596138205} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &842675857 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 842675860} + - component: {fileID: 842675859} + - component: {fileID: 842675858} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &842675858 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 842675857} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3} + m_Name: + m_EditorClassIdentifier: + m_SendPointerHoverToParent: 1 + m_MoveRepeatDelay: 0.5 + m_MoveRepeatRate: 0.1 + m_XRTrackingOrigin: {fileID: 0} + m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_PointAction: {fileID: -1654692200621890270, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_MoveAction: {fileID: -8784545083839296357, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_SubmitAction: {fileID: 392368643174621059, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_CancelAction: {fileID: 7727032971491509709, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_LeftClickAction: {fileID: 3001919216989983466, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_MiddleClickAction: {fileID: -2185481485913320682, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_RightClickAction: {fileID: -4090225696740746782, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_ScrollWheelAction: {fileID: 6240969308177333660, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_TrackedDevicePositionAction: {fileID: 6564999863303420839, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_TrackedDeviceOrientationAction: {fileID: 7970375526676320489, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_DeselectOnBackgroundClick: 1 + m_PointerBehavior: 0 + m_CursorLockBehavior: 0 + m_ScrollDeltaPerTick: 6 +--- !u!114 &842675859 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 842675857} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &842675860 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 842675857} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &970346963 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 970346967} + - component: {fileID: 970346966} + - component: {fileID: 970346965} + - component: {fileID: 970346964} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &970346964 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970346963} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ea915761c8274bf983b476e4ad15da36, type: 3} + m_Name: + m_EditorClassIdentifier: + colliderType: 3 + radius: + _serializedValue: 4294967296 + boxSize: + x: + _serializedValue: 8589934592 + y: + _serializedValue: 8589934592 + ovalAxis: + x: + _serializedValue: 8589934592 + y: + _serializedValue: 4294967296 + doubleCircleOffset: + x: + _serializedValue: 4294967296 + y: + _serializedValue: 0 + moveMode: 0 + moveSpeed: + _serializedValue: 21474836480 + rotationSpeed: + _serializedValue: -158913789952 + amplitude: + _serializedValue: 12884901888 + frequency: + _serializedValue: 4294967296 +--- !u!23 &970346965 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970346963} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: cb388a83031c8b5449b266658342ab83, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &970346966 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970346963} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &970346967 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970346963} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1155883975 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1155883978} + - component: {fileID: 1155883976} + - component: {fileID: 1155883979} + - component: {fileID: 1155883980} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1155883976 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1155883975} + m_Enabled: 1 +--- !u!4 &1155883978 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1155883975} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1411761322} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!20 &1155883979 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1155883975} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 2 + m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: -10 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 15 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!114 &1155883980 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1155883975} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1ceed5607a5d49dca1e94035eaa2f698, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &1411761320 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1411761322} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1411761322 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1411761320} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1155883978} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1685858033 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1685858037} + - component: {fileID: 1685858036} + - component: {fileID: 1685858035} + - component: {fileID: 1685858034} + m_Layer: 0 + m_Name: OFF + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1685858034 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1685858033} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ea915761c8274bf983b476e4ad15da36, type: 3} + m_Name: + m_EditorClassIdentifier: + colliderType: 2 + radius: + _serializedValue: 8589934592 + boxSize: + x: + _serializedValue: 8589934592 + y: + _serializedValue: 8589934592 + ovalAxis: + x: + _serializedValue: 8589934592 + y: + _serializedValue: 4294967296 + doubleCircleOffset: + x: + _serializedValue: 4294967296 + y: + _serializedValue: 0 + moveMode: 2 + moveSpeed: + _serializedValue: 0 + rotationSpeed: + _serializedValue: 386547056640 + amplitude: + _serializedValue: 12884901888 + frequency: + _serializedValue: 4294967296 +--- !u!23 &1685858035 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1685858033} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: cb388a83031c8b5449b266658342ab83, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1685858036 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1685858033} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1685858037 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1685858033} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 4, z: 0} + m_LocalScale: {x: 1, y: 1, z: 4} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 1155883978} + - {fileID: 596138207} + - {fileID: 970346967} + - {fileID: 1685858037} + - {fileID: 842675860} diff --git a/Assets/Scenes/New Scene.unity.meta b/Assets/Scenes/New Scene.unity.meta new file mode 100644 index 0000000..1383480 --- /dev/null +++ b/Assets/Scenes/New Scene.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b1c08a7ecf0baff4dbe2dd6ea6c85de0 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index a141fd2..1187d56 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -119,6 +119,50 @@ NavMeshSettings: debug: m_Flags: 0 m_NavMeshData: {fileID: 0} +--- !u!1 &112231250 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 112231252} + - component: {fileID: 112231251} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &112231251 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 112231250} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1ceed5607a5d49dca1e94035eaa2f698, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &112231252 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 112231250} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &330585543 GameObject: m_ObjectHideFlags: 0 @@ -131,7 +175,6 @@ GameObject: - component: {fileID: 330585545} - component: {fileID: 330585544} - component: {fileID: 330585547} - - component: {fileID: 330585548} m_Layer: 0 m_Name: Main Camera m_TagString: MainCamera @@ -178,11 +221,11 @@ Camera: y: 0 width: 1 height: 1 - near clip plane: 0.3 + near clip plane: -1 far clip plane: 1000 field of view: 60 - orthographic: 0 - orthographic size: 5 + orthographic: 1 + orthographic size: 20 m_Depth: -1 m_CullingMask: serializedVersion: 2 @@ -257,18 +300,6 @@ MonoBehaviour: m_MipBias: 0 m_VarianceClampScale: 0.9 m_ContrastAdaptiveSharpening: 0 ---- !u!114 &330585548 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 330585543} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a3527897712cb704f9f4e04d329e7bba, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!1 &410087039 GameObject: m_ObjectHideFlags: 0 @@ -414,7 +445,7 @@ MonoBehaviour: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 832575517} - m_Enabled: 1 + m_Enabled: 0 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 172515602e62fb746b5d573b38a5fe58, type: 3} m_Name: @@ -439,6 +470,132 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1430430700 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1430430704} + - component: {fileID: 1430430703} + - component: {fileID: 1430430702} + - component: {fileID: 1430430705} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &1430430702 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1430430700} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1430430703 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1430430700} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1430430704 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1430430700} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1430430705 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1430430700} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ea915761c8274bf983b476e4ad15da36, type: 3} + m_Name: + m_EditorClassIdentifier: + colliderType: 0 + radius: + _serializedValue: 4294967296 + boxSize: + x: + _serializedValue: 8589934592 + y: + _serializedValue: 8589934592 + ovalAxis: + x: + _serializedValue: 8589934592 + y: + _serializedValue: 4294967296 + doubleCircleOffset: + x: + _serializedValue: 4294967296 + y: + _serializedValue: 0 + moveMode: 0 + moveSpeed: + _serializedValue: 21474836480 + rotationSpeed: + _serializedValue: 386547056640 + amplitude: + _serializedValue: 12884901888 + frequency: + _serializedValue: 4294967296 --- !u!1660057539 &9223372036854775807 SceneRoots: m_ObjectHideFlags: 0 @@ -446,3 +603,5 @@ SceneRoots: - {fileID: 330585546} - {fileID: 410087041} - {fileID: 832575519} + - {fileID: 1430430704} + - {fileID: 112231252} diff --git a/Assets/Settings/DefaultVolumeProfile.asset b/Assets/Settings/DefaultVolumeProfile.asset index 6fb1822..9e4bbfd 100644 --- a/Assets/Settings/DefaultVolumeProfile.asset +++ b/Assets/Settings/DefaultVolumeProfile.asset @@ -342,6 +342,9 @@ MonoBehaviour: skyOcclusionIntensityMultiplier: m_OverrideState: 1 m_Value: 1 + worldOffset: + m_OverrideState: 1 + m_Value: {x: 0, y: 0, z: 0} --- !u!114 &-1216621516061285780 MonoBehaviour: m_ObjectHideFlags: 3 @@ -462,8 +465,6 @@ MonoBehaviour: - {fileID: -6288072647309666549} - {fileID: 7518938298396184218} - {fileID: -1410297666881709256} - - {fileID: -7750755424749557576} - - {fileID: -5139089513906902183} --- !u!114 &853819529557874667 MonoBehaviour: m_ObjectHideFlags: 3 diff --git a/Assets/TrueSync/TSMatrix4x4.cs b/Assets/TrueSync/TSMatrix4x4.cs index 3cbe2ee..4d693d6 100644 --- a/Assets/TrueSync/TSMatrix4x4.cs +++ b/Assets/TrueSync/TSMatrix4x4.cs @@ -880,7 +880,7 @@ public static TSMatrix4x4 Scale(FP scale, TSVector centerPoint) } /// - /// Creates a matrix for rotating points around the X-axis. + /// Creates a matrix for rotating vertices around the X-axis. /// /// The amount, in radians, by which to rotate around the X-axis. /// The rotation matrix. @@ -916,7 +916,7 @@ public static TSMatrix4x4 RotateX(FP radians) } /// - /// Creates a matrix for rotating points around the X-axis, from a center point. + /// Creates a matrix for rotating vertices around the X-axis, from a center point. /// /// The amount, in radians, by which to rotate around the X-axis. /// The center point. @@ -956,7 +956,7 @@ public static TSMatrix4x4 RotateX(FP radians, TSVector centerPoint) } /// - /// Creates a matrix for rotating points around the Y-axis. + /// Creates a matrix for rotating vertices around the Y-axis. /// /// The amount, in radians, by which to rotate around the Y-axis. /// The rotation matrix. @@ -992,7 +992,7 @@ public static TSMatrix4x4 RotateY(FP radians) } /// - /// Creates a matrix for rotating points around the Y-axis, from a center point. + /// Creates a matrix for rotating vertices around the Y-axis, from a center point. /// /// The amount, in radians, by which to rotate around the Y-axis. /// The center point. @@ -1032,7 +1032,7 @@ public static TSMatrix4x4 RotateY(FP radians, TSVector centerPoint) } /// - /// Creates a matrix for rotating points around the Z-axis. + /// Creates a matrix for rotating vertices around the Z-axis. /// /// The amount, in radians, by which to rotate around the Z-axis. /// The rotation matrix. @@ -1068,7 +1068,7 @@ public static TSMatrix4x4 RotateZ(FP radians) } /// - /// Creates a matrix for rotating points around the Z-axis, from a center point. + /// Creates a matrix for rotating vertices around the Z-axis, from a center point. /// /// The amount, in radians, by which to rotate around the Z-axis. /// The center point. diff --git a/Assets/tmpExtensions.cs b/Assets/tmpExtensions.cs index 0648017..1602f1f 100644 --- a/Assets/tmpExtensions.cs +++ b/Assets/tmpExtensions.cs @@ -7,7 +7,7 @@ public static class tmpExtensions { public static Vector2 RotateRad(this Vector2 self, float rad) { - float cos = Mathf.Cos(rad), sin = Mathf.Cos(rad); + float cos = Mathf.Cos(rad), sin = Mathf.Sin(rad); return new Vector2(self.x * cos - self.y * sin, self.x * sin + self.y * cos); } /// diff --git a/Packages/manifest.json b/Packages/manifest.json index 0c4acda..9444e62 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -2,11 +2,11 @@ "dependencies": { "com.unity.ai.navigation": "2.0.6", "com.unity.collab-proxy": "2.7.1", + "com.unity.feature.2d": "2.0.1", "com.unity.ide.rider": "3.0.31", "com.unity.ide.visualstudio": "2.0.22", - "com.unity.inputsystem": "1.13.1", + "com.unity.inputsystem": "1.14.0", "com.unity.multiplayer.center": "1.0.0", - "com.unity.render-pipelines.universal": "17.0.4", "com.unity.test-framework": "1.5.1", "com.unity.timeline": "1.8.7", "com.unity.ugui": "2.0.0", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index e545425..c834979 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -1,5 +1,97 @@ { "dependencies": { + "com.unity.2d.animation": { + "version": "10.1.4", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.2d.common": "9.0.7", + "com.unity.2d.sprite": "1.0.0", + "com.unity.collections": "1.2.4", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.uielements": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.2d.aseprite": { + "version": "1.1.9", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.2d.common": "6.0.6", + "com.unity.2d.sprite": "1.0.0", + "com.unity.mathematics": "1.2.6", + "com.unity.modules.animation": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.2d.common": { + "version": "9.0.7", + "depth": 2, + "source": "registry", + "dependencies": { + "com.unity.burst": "1.8.4", + "com.unity.2d.sprite": "1.0.0", + "com.unity.mathematics": "1.1.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.uielements": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.2d.pixel-perfect": { + "version": "5.0.3", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.2d.psdimporter": { + "version": "9.0.3", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.2d.common": "9.0.4", + "com.unity.2d.sprite": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.2d.sprite": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": {} + }, + "com.unity.2d.spriteshape": { + "version": "10.0.7", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.2d.common": "9.0.7", + "com.unity.mathematics": "1.1.0", + "com.unity.modules.physics2d": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.2d.tilemap": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.uielements": "1.0.0" + } + }, + "com.unity.2d.tilemap.extras": { + "version": "4.1.0", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.2d.tilemap": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, "com.unity.ai.navigation": { "version": "2.0.6", "depth": 0, @@ -11,7 +103,7 @@ }, "com.unity.burst": { "version": "1.8.19", - "depth": 2, + "depth": 3, "source": "registry", "dependencies": { "com.unity.mathematics": "1.2.1", @@ -44,6 +136,21 @@ "source": "builtin", "dependencies": {} }, + "com.unity.feature.2d": { + "version": "2.0.1", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.2d.animation": "10.1.4", + "com.unity.2d.pixel-perfect": "5.0.3", + "com.unity.2d.psdimporter": "9.0.3", + "com.unity.2d.sprite": "1.0.0", + "com.unity.2d.spriteshape": "10.0.7", + "com.unity.2d.tilemap": "1.0.0", + "com.unity.2d.tilemap.extras": "4.1.0", + "com.unity.2d.aseprite": "1.1.9" + } + }, "com.unity.ide.rider": { "version": "3.0.31", "depth": 0, @@ -63,7 +170,7 @@ "url": "https://packages.unity.com" }, "com.unity.inputsystem": { - "version": "1.13.1", + "version": "1.14.0", "depth": 0, "source": "registry", "dependencies": { @@ -93,65 +200,6 @@ "dependencies": {}, "url": "https://packages.unity.com" }, - "com.unity.render-pipelines.core": { - "version": "17.0.4", - "depth": 1, - "source": "builtin", - "dependencies": { - "com.unity.burst": "1.8.14", - "com.unity.mathematics": "1.3.2", - "com.unity.ugui": "2.0.0", - "com.unity.collections": "2.4.3", - "com.unity.modules.physics": "1.0.0", - "com.unity.modules.terrain": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0", - "com.unity.rendering.light-transport": "1.0.1" - } - }, - "com.unity.render-pipelines.universal": { - "version": "17.0.4", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.render-pipelines.core": "17.0.4", - "com.unity.shadergraph": "17.0.4", - "com.unity.render-pipelines.universal-config": "17.0.3" - } - }, - "com.unity.render-pipelines.universal-config": { - "version": "17.0.3", - "depth": 1, - "source": "builtin", - "dependencies": { - "com.unity.render-pipelines.core": "17.0.3" - } - }, - "com.unity.rendering.light-transport": { - "version": "1.0.1", - "depth": 2, - "source": "builtin", - "dependencies": { - "com.unity.collections": "2.2.0", - "com.unity.mathematics": "1.2.4", - "com.unity.modules.terrain": "1.0.0" - } - }, - "com.unity.searcher": { - "version": "4.9.3", - "depth": 2, - "source": "registry", - "dependencies": {}, - "url": "https://packages.unity.com" - }, - "com.unity.shadergraph": { - "version": "17.0.4", - "depth": 1, - "source": "builtin", - "dependencies": { - "com.unity.render-pipelines.core": "17.0.4", - "com.unity.searcher": "4.9.3" - } - }, "com.unity.test-framework": { "version": "1.5.1", "depth": 0, diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset index aa5a1c3..fe3b265 100644 --- a/ProjectSettings/GraphicsSettings.asset +++ b/ProjectSettings/GraphicsSettings.asset @@ -36,10 +36,8 @@ GraphicsSettings: - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} m_PreloadedShaders: [] m_PreloadShadersBatchTimeLimit: -1 - m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, - type: 0} - m_CustomRenderPipeline: {fileID: 11400000, guid: 4b83569d67af61e458304325a23e5dfd, - type: 2} + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_CustomRenderPipeline: {fileID: 0} m_TransparencySortMode: 0 m_TransparencySortAxis: {x: 0, y: 0, z: 1} m_DefaultRenderingPath: 1 @@ -60,8 +58,7 @@ GraphicsSettings: m_FogKeepExp2: 1 m_AlbedoSwatchInfos: [] m_RenderPipelineGlobalSettingsMap: - UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: 18dc0cd2c080841dea60987a38ce93fa, - type: 2} + UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: 18dc0cd2c080841dea60987a38ce93fa, type: 2} m_LightsUseLinearIntensity: 1 m_LightsUseColorTemperature: 1 m_LogWhenShaderIsCompiled: 0 diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index ac5ce5f..a09e05c 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -827,7 +827,7 @@ PlayerSettings: managedStrippingLevel: {} incrementalIl2cppBuild: {} suppressCommonWarnings: 1 - allowUnsafeCode: 0 + allowUnsafeCode: 1 useDeterministicCompilation: 1 additionalIl2CppArgs: scriptingRuntimeVersion: 1 diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index 6a73247..2795afa 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 6000.0.44f1 -m_EditorVersionWithRevision: 6000.0.44f1 (101c91f3a8fb) +m_EditorVersion: 6000.0.45f1 +m_EditorVersionWithRevision: 6000.0.45f1 (d91bd3d4e081) From 2f91041881249a1f97448c504473a7f9638bbb4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B3=A0=E6=BC=AA?= <32807696+AngelShadow2017@users.noreply.github.com> Date: Sun, 13 Apr 2025 12:59:30 +0800 Subject: [PATCH 3/9] e --- Assets/ColliUpdate.cs | 5 + Assets/ColliderObj.cs | 5 +- Assets/ColliderStructure.cs | 32 ++++- Assets/Scenes/New Scene.unity | 258 +++++++++++++++++++++++++++++++++- 4 files changed, 289 insertions(+), 11 deletions(-) diff --git a/Assets/ColliUpdate.cs b/Assets/ColliUpdate.cs index f2c7fc4..a2d9b8a 100644 --- a/Assets/ColliUpdate.cs +++ b/Assets/ColliUpdate.cs @@ -17,6 +17,11 @@ private void Update() CollisionManager.instance.TraverseAllListener(); } + private void LateUpdate() + { + CollisionManager.instance.BufferManager.CompactVertexBuffers(); + } + private void OnPostRender() { CollisionManager.instance.DebugDisplayShape(transform.localToWorldMatrix); diff --git a/Assets/ColliderObj.cs b/Assets/ColliderObj.cs index 1a29854..242f697 100644 --- a/Assets/ColliderObj.cs +++ b/Assets/ColliderObj.cs @@ -512,7 +512,8 @@ void MoveDeltaPos(TSVector2 pos) public override void Destroy() { CollisionManager.instance.BufferManager.DeleteCollider(collider); - movedVertexs.Dispose(); + if(movedVertexs.IsCreated) + movedVertexs.Dispose(); } public override TSVector4 GetBoundingBox() @@ -953,7 +954,7 @@ public void Dispose() public ColliderVertexBuffer BufferManager = new ColliderVertexBuffer(); public CollisionManager() { groupedColliders = new LinkedHashSet[groupCnt]; - for (int i = 0; i < groupCnt; i++) { + for (int i = 0; i < groupCnt; i++) { groupedColliders[i] = new LinkedHashSet(); } } diff --git a/Assets/ColliderStructure.cs b/Assets/ColliderStructure.cs index 92044e2..0fe9ffa 100644 --- a/Assets/ColliderStructure.cs +++ b/Assets/ColliderStructure.cs @@ -427,7 +427,14 @@ public static bool CheckCollide(in ColliderStructure shape1, in ColliderStructur } [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] public class ColliderVertexBuffer:IDisposable{ - public static NativeArray.ReadOnly instancedBuffer => CollisionManager.instance.BufferManager.vertices.AsReadOnly(); + public static NativeArray.ReadOnly instancedBuffer + { + get + { + return CollisionManager.instance.BufferManager.vertices.AsReadOnly(); + } + } + public NativeHashMap colliders = new NativeHashMap(16,Allocator.Persistent); public NativeList vertices = new NativeList(Allocator.Persistent); @@ -476,7 +483,8 @@ static void DeleteCollider(ref int removedDelta,ref NativeHashMap(in NativeList arr,int srcStart, int count,int /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] - public static unsafe void CompactVertexBuffers( + public static void CompactVertexBuffers( ref int removedDelta,ref NativeHashMap colliders, ref NativeList vertices ) @@ -533,14 +541,19 @@ ref NativeList vertices throw new NullReferenceException("vertices数组未创建"); } NativeList newList = new NativeList(vertices.Length-removedDelta,Allocator.Persistent); - var listArrayPointer = vertices.GetUnsafeReadOnlyPtr(); - var _sizeof_ = UnsafeUtility.SizeOf(); + newList.ResizeUninitialized(vertices.Length - removedDelta); + //var listArrayPointer = vertices.GetUnsafeReadOnlyPtr(); + var listArray = vertices.AsReadOnly(); + var newListArray = newList.AsArray(); + int newStartIndex = 0; + //var _sizeof_ = UnsafeUtility.SizeOf(); foreach (var ele in colliders) { ref var val = ref ele.Value; - var newStartIndex = newList.Length; - newList.AddRangeNoResize(((byte*)listArrayPointer+(_sizeof_*val.vertexStartIndex)), val.vertexCount); + NativeArray.Copy(listArray,val.vertexStartIndex,newListArray,newStartIndex,val.vertexCount); + //newList.AddRangeNoResize(((byte*)listArrayPointer+(_sizeof_*val.vertexStartIndex)), val.vertexCount); val.vertexStartIndex = newStartIndex; + newStartIndex += val.vertexCount; } vertices.Dispose(); vertices = newList; @@ -783,4 +796,9 @@ public void Dispose() segments.Dispose(); } } + [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] + public struct CollisionManagerBurst + { + + } } \ No newline at end of file diff --git a/Assets/Scenes/New Scene.unity b/Assets/Scenes/New Scene.unity index 81960cb..f159803 100644 --- a/Assets/Scenes/New Scene.unity +++ b/Assets/Scenes/New Scene.unity @@ -339,7 +339,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: ea915761c8274bf983b476e4ad15da36, type: 3} m_Name: m_EditorClassIdentifier: - colliderType: 3 + colliderType: 1 radius: _serializedValue: 4294967296 boxSize: @@ -571,6 +571,258 @@ Transform: m_Children: [] m_Father: {fileID: 1155883978} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1633608431 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1633608435} + - component: {fileID: 1633608434} + - component: {fileID: 1633608433} + - component: {fileID: 1633608432} + m_Layer: 0 + m_Name: 1as + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1633608432 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633608431} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ea915761c8274bf983b476e4ad15da36, type: 3} + m_Name: + m_EditorClassIdentifier: + colliderType: 2 + radius: + _serializedValue: 8589934592 + boxSize: + x: + _serializedValue: 8589934592 + y: + _serializedValue: 8589934592 + ovalAxis: + x: + _serializedValue: 8589934592 + y: + _serializedValue: 4294967296 + doubleCircleOffset: + x: + _serializedValue: 4294967296 + y: + _serializedValue: 21474836480 + moveMode: 2 + moveSpeed: + _serializedValue: 0 + rotationSpeed: + _serializedValue: 545460846592 + amplitude: + _serializedValue: 12884901888 + frequency: + _serializedValue: 4294967296 +--- !u!23 &1633608433 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633608431} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: cb388a83031c8b5449b266658342ab83, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1633608434 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633608431} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1633608435 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633608431} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -6, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 4} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1641945847 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1641945851} + - component: {fileID: 1641945850} + - component: {fileID: 1641945849} + - component: {fileID: 1641945848} + m_Layer: 0 + m_Name: OFF 3 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1641945848 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1641945847} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ea915761c8274bf983b476e4ad15da36, type: 3} + m_Name: + m_EditorClassIdentifier: + colliderType: 2 + radius: + _serializedValue: 8589934592 + boxSize: + x: + _serializedValue: 21474836480 + y: + _serializedValue: 21474836480 + ovalAxis: + x: + _serializedValue: 8589934592 + y: + _serializedValue: 4294967296 + doubleCircleOffset: + x: + _serializedValue: 4294967296 + y: + _serializedValue: 21474836480 + moveMode: 2 + moveSpeed: + _serializedValue: 0 + rotationSpeed: + _serializedValue: 300647710720 + amplitude: + _serializedValue: 12884901888 + frequency: + _serializedValue: 4294967296 +--- !u!23 &1641945849 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1641945847} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: cb388a83031c8b5449b266658342ab83, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1641945850 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1641945847} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1641945851 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1641945847} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 5, y: 4, z: 0} + m_LocalScale: {x: 1, y: 1, z: 4} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1685858033 GameObject: m_ObjectHideFlags: 0 @@ -619,7 +871,7 @@ MonoBehaviour: x: _serializedValue: 4294967296 y: - _serializedValue: 0 + _serializedValue: 21474836480 moveMode: 2 moveSpeed: _serializedValue: 0 @@ -705,4 +957,6 @@ SceneRoots: - {fileID: 596138207} - {fileID: 970346967} - {fileID: 1685858037} + - {fileID: 1641945851} + - {fileID: 1633608435} - {fileID: 842675860} From b42f608f098bbb5eff4c54e760e012200d92a636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B3=A0=E6=BC=AA?= <32807696+AngelShadow2017@users.noreply.github.com> Date: Sun, 13 Apr 2025 15:19:42 +0800 Subject: [PATCH 4/9] native things --- Assets/ColliUpdate.cs | 2 +- Assets/ColliderObj.cs | 177 ++++++++++++++++++++++-------------- Assets/ColliderStructure.cs | 59 ++++++++++-- Assets/ColliderTester.cs | 6 +- 4 files changed, 164 insertions(+), 80 deletions(-) diff --git a/Assets/ColliUpdate.cs b/Assets/ColliUpdate.cs index a2d9b8a..4518c9a 100644 --- a/Assets/ColliUpdate.cs +++ b/Assets/ColliUpdate.cs @@ -19,7 +19,7 @@ private void Update() private void LateUpdate() { - CollisionManager.instance.BufferManager.CompactVertexBuffers(); + CollisionManager.instance.nativeCollisionManager.CompactVertexBuffers(); } private void OnPostRender() diff --git a/Assets/ColliderObj.cs b/Assets/ColliderObj.cs index 242f697..dc10133 100644 --- a/Assets/ColliderObj.cs +++ b/Assets/ColliderObj.cs @@ -11,6 +11,7 @@ namespace Core.Algorithm { public interface ICollideShape { + public bool Registered { get; set; } public ref ColliderStructure Collider { get; } //获取在某个方向上的最远点 public TSVector2 GetFurthestPoint(in TSVector2 direction); @@ -20,7 +21,7 @@ public interface ICollideShape { public TSVector2 GetCenter(); //左上点和右下点!!! public TSVector4 GetBoundingBox(); - public CollisionManager.CollisionGroup colliGroup { get; set; } + public CollisionGroup colliGroup { get; set; } public bool enabled { get; set; } public void DebugDisplayColliderShape(Color color); @@ -35,21 +36,16 @@ public interface IMasteredCollider [Serializable] public abstract class ColliderBase : ICollideShape { + public bool Registered { get; set; } = false; public ColliderStructure collider; public ref ColliderStructure Collider => ref collider; - protected CollisionManager.CollisionGroup __colli__ = CollisionManager.CollisionGroup.Default; + //protected CollisionGroup __colli__ = CollisionGroup.Default; protected bool __enabled__ = true; public int tag = -1;//用来识别特定的tag - public CollisionManager.CollisionGroup colliGroup { - get - { - return __colli__; - } - set - { - __colli__ = value; - } + public CollisionGroup colliGroup { + get => collider.collisionGroup; + set => collider.collisionGroup = value;//记得sync } public bool enabled { @@ -62,7 +58,7 @@ public bool enabled __enabled__ = value; } } - + static TSVector2 SupportFunc(ColliderBase shape1,ColliderBase shape2,TSVector2 direciton) { //Debug.Log("direction: "+direciton+" "+ shape1.GetFurthestPoint(direciton)+" "+shape2.GetFurthestPoint(-direciton)); return shape1.GetFurthestPoint(direciton) - shape2.GetFurthestPoint(-direciton); @@ -74,7 +70,8 @@ static TSVector2 TripleProduct2d(TSVector2 a,TSVector2 b,TSVector2 c) { public abstract TSVector4 GetBoundingBox(); public TSVector2 GetFurthestPoint(in TSVector2 direction) { - GetFurthestPointExtensions.GetFurthestPoint(out var result, collider, direction,ColliderVertexBuffer.instancedBuffer); + CheckEssentialValues(); + GetFurthestPointExtensions.GetFurthestPoint(out var result, collider, direction,ColliderNativeHelper.instancedBuffer); return result; } public abstract void SetRotation(FP rotRad); @@ -91,7 +88,7 @@ public static bool CheckCollide(ColliderBase shape1, ColliderBase shape2) { TSVector2[] Simplex = new TSVector2[3];//单纯形数组,最多只能是3个 Simplex[0] = SupportFunc(shape1, shape2, direction); int simplexLastInd = 1; - int interateTimeMax = 100;//最大迭代次数 + int interateTimeMax = 10;//最大迭代次数 //#第三步:找到第一个支撑点后,以第一个支撑点为起点指向原点O的方向为新方向d direction = -Simplex[0].normalized; //#第四步:开始循环,找下一个支撑点 @@ -179,10 +176,36 @@ public virtual ColliderStructure GetRealCollider() { return Collider; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected void CheckEssentialValues() + { + +#if UNITY_EDITOR + if (!Registered) + { + throw new NotSupportedException("没有把当前物体注册入控制管理器中"); + } + var judg = CollisionManager.instance?.nativeCollisionManager.colliders.IsCreated; + if (!judg.HasValue||!judg.Value) + { + throw new NotSupportedException("控制器单例不存在或buffer已被销毁"); + } +#endif + } + + /// + /// 设置完属性后必须调用这个函数 + /// + public virtual void SaveState() + { + CheckEssentialValues(); + CollisionManager.instance.nativeCollisionManager.SyncCollider(ref collider); + } public bool CheckCollide(ColliderBase shape2) { - return CollideExtensions.CheckCollide(this.GetRealCollider(), shape2.GetRealCollider(),ColliderVertexBuffer.instancedBuffer); + CheckEssentialValues(); + return CollideExtensions.CheckCollide(this.GetRealCollider(), shape2.GetRealCollider(),ColliderNativeHelper.instancedBuffer); } public virtual void DebugDisplayColliderShape(Color color) { } @@ -199,14 +222,13 @@ public abstract class ColliderBase : ColliderBase [Serializable] public class CircleCollider : ColliderBase { - public CircleCollider(FP R,TSVector2 center,CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) + public CircleCollider(FP R,TSVector2 center,CollisionGroup group = CollisionGroup.Default) { - Collider = ColliderStructure.CreateInstance(); - Collider.colliderType = ColliderType.Circle; - Collider.radius = R; - Collider.center = center; - - colliGroup = group; + collider = ColliderStructure.CreateInstance(); + collider.colliderType = ColliderType.Circle; + collider.radius = R; + collider.center = center; + collider.collisionGroup = group; } public override void SetRotation(FP rotRad) { }//没错,圆形没有旋转 public override void SetCenter(in TSVector2 center) @@ -276,7 +298,7 @@ public T Master { set => _master_ = value; } - public CircleCollider(T master,FP R, TSVector2 center, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) : base(R, center, group) + public CircleCollider(T master,FP R, TSVector2 center, CollisionGroup group = CollisionGroup.Default) : base(R, center, group) { this._master_ = master; } @@ -288,14 +310,14 @@ public class OvalCollider : ColliderBase //public FP rot, b2Dividea2;//旋转,长轴方除以短轴方,因为定点数除法……真的太慢了。。。 //public TSVector2 Axis,SqrAxis;//半长轴和半短轴?其实应该叫水平轴和竖直轴 //TSVector2 centerPos; - public OvalCollider(TSVector2 axis, TSVector2 center,in FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) + public OvalCollider(TSVector2 axis, TSVector2 center,in FP rotation, CollisionGroup group = CollisionGroup.Default) { collider = ColliderStructure.CreateInstance(); collider.colliderType = ColliderType.Oval; collider.rot = rotation; collider.center = center; SetAxis(axis); - colliGroup = group; + collider.collisionGroup = group; } public void SetAxis(TSVector2 axis) { collider.Axis = axis; @@ -391,7 +413,7 @@ public T Master set => _master_ = value; } - public OvalCollider(T master, TSVector2 axis, TSVector2 center, FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) : base(axis, center,rotation, group) + public OvalCollider(T master, TSVector2 axis, TSVector2 center, FP rotation, CollisionGroup group = CollisionGroup.Default) : base(axis, center,rotation, group) { this._master_ = master; } @@ -416,21 +438,27 @@ public void Dispose() } } - public PolygonCollider(TSVector2[] vertex, TSVector2 center, FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) + public PolygonCollider(TSVector2[] vertex, TSVector2 center, FP rotation, CollisionGroup group = CollisionGroup.Default) { collider = ColliderStructure.CreateInstance(); collider.colliderType = ColliderType.Polygon; collider.rot = rotation; collider.center = center; + collider.collisionGroup = group; + collider.vertexCount = vertex.Length; movedVertexs = new NativeArray(vertex.Length,Allocator.Persistent,NativeArrayOptions.UninitializedMemory); //边数是不能变的 - CollisionManager.instance.BufferManager.RegisterCollider(ref collider,vertex.Length); - SetRotation(rotation); - colliGroup = group; + RotateVertexs(false); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public override ColliderStructure GetRealCollider() { - return CollisionManager.instance.BufferManager.colliders[collider.uniqueID]; + return CollisionManager.instance.nativeCollisionManager.colliders[collider.uniqueID]; + } + + public sealed override void SaveState() + { + base.SaveState(); + CollisionManager.instance.nativeCollisionManager.ModifyCollider(collider,movedVertexs); } public override void SetRotation(FP rotRad) @@ -447,7 +475,7 @@ public override TSVector2 GetCenter() { return collider.center; } - void RotateVertexs() + protected void RotateVertexs(bool saveState=true) { TSVector4 tSVector4 = new TSVector4(FP.MaxValue, FP.MinValue, FP.MinValue, FP.MaxValue); for (int i = movedVertexs.Length - 1; i >= 0; --i) @@ -470,8 +498,11 @@ void RotateVertexs() tSVector4.w = movedVertexs[i].y;//最小值,代表下方点 } } - CollisionManager.instance.BufferManager.ModifyCollider(collider,movedVertexs); _boundingBox_ = tSVector4; + if (saveState) + { + SaveState(); + } } void MoveDeltaPos(TSVector2 pos) { @@ -480,7 +511,7 @@ void MoveDeltaPos(TSVector2 pos) movedVertexs[i] += pos; } //标注顶点缓冲区的移动 - CollisionManager.instance.BufferManager.ModifyCollider(collider,movedVertexs); + SaveState(); _boundingBox_.x += pos.x; _boundingBox_.y += pos.y; _boundingBox_.z += pos.x; @@ -502,7 +533,7 @@ void MoveDeltaPos(TSVector2 pos) } if (result != pos) { - var arr = ColliderVertexBuffer.instancedBuffer.ToArray(); + var arr = ColliderNativeHelper.instancedBuffer.ToArray(); StringBuilder sb = new StringBuilder(); sb.AppendJoin(", ", arr); Debug.Log(result+" "+pos+" "+sb); @@ -511,7 +542,7 @@ void MoveDeltaPos(TSVector2 pos) }*/ public override void Destroy() { - CollisionManager.instance.BufferManager.DeleteCollider(collider); + CollisionManager.instance.nativeCollisionManager.DeleteCollider(collider); if(movedVertexs.IsCreated) movedVertexs.Dispose(); } @@ -524,7 +555,7 @@ public override TSVector4 GetBoundingBox() [Serializable] public class BoxCollider : PolygonCollider { - public BoxCollider(TSVector2 widthHeight,TSVector2 center,FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) + public BoxCollider(TSVector2 widthHeight,TSVector2 center,FP rotation, CollisionGroup group = CollisionGroup.Default) { TSVector2 a = widthHeight * 0.5;//左下,左上,右上,右下 TSVector2 b = new TSVector2(a.x,-a.y); @@ -534,9 +565,9 @@ public BoxCollider(TSVector2 widthHeight,TSVector2 center,FP rotation, Collision collider.colliderType = ColliderType.Polygon; collider.rot = rotation; collider.center = center; - CollisionManager.instance.BufferManager.RegisterCollider(ref collider,movedVertexs.Length); - SetRotation(rotation); - colliGroup = group; + collider.vertexCount = vertexs.Length; + collider.collisionGroup = group; + RotateVertexs(false); } public override void DebugDisplayColliderShape(Color color) { @@ -562,7 +593,7 @@ public T Master set => _master_ = value; } - public BoxCollider(T master, TSVector2 widthHeight, TSVector2 center, FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) : base(widthHeight, center, rotation, group) + public BoxCollider(T master, TSVector2 widthHeight, TSVector2 center, FP rotation, CollisionGroup group = CollisionGroup.Default) : base(widthHeight, center, rotation, group) { this._master_ = master; } @@ -571,7 +602,7 @@ public BoxCollider(T master, TSVector2 widthHeight, TSVector2 center, FP rotatio [Serializable] public class DiamondCollider : PolygonCollider { - public DiamondCollider(TSVector2 widthHeight, TSVector2 center, FP rotation, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) + public DiamondCollider(TSVector2 widthHeight, TSVector2 center, FP rotation, CollisionGroup group = CollisionGroup.Default) { TSVector2 b = new TSVector2(widthHeight.x * 0.5, 0); TSVector2 c = new TSVector2(0, widthHeight.y * 0.5); @@ -581,9 +612,9 @@ public DiamondCollider(TSVector2 widthHeight, TSVector2 center, FP rotation, Col collider.colliderType = ColliderType.Polygon; collider.rot = rotation; collider.center = center; - CollisionManager.instance.BufferManager.RegisterCollider(ref collider,movedVertexs.Length); - SetRotation(rotation); - colliGroup = group; + collider.vertexCount = vertexs.Length; + collider.collisionGroup = group; + RotateVertexs(false); } } @@ -591,13 +622,13 @@ public DiamondCollider(TSVector2 widthHeight, TSVector2 center, FP rotation, Col //两个相同的圆中间连线 public class DoubleCircleCollider : ColliderBase { - public DoubleCircleCollider(FP R, TSVector2 center1,TSVector2 center2, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) + public DoubleCircleCollider(FP R, TSVector2 center1,TSVector2 center2, CollisionGroup group = CollisionGroup.Default) { collider = ColliderStructure.CreateInstance(); collider.colliderType = ColliderType.DoubleCircle; collider.radius = R; + collider.collisionGroup = group; SetCircleCenters(center1,center2); - colliGroup = group; } public override void SetRotation(FP rotRad) { }//没错,圆形没有旋转 public override void SetCenter(in TSVector2 center) @@ -753,7 +784,7 @@ public T Master set => _master_ = value; } - public DoubleCircleCollider(T master, FP R, TSVector2 center1,TSVector2 center2, CollisionManager.CollisionGroup group = CollisionManager.CollisionGroup.Default) : base(R, center1,center2, group) + public DoubleCircleCollider(T master, FP R, TSVector2 center1,TSVector2 center2, CollisionGroup group = CollisionGroup.Default) : base(R, center1,center2, group) { this._master_ = master; } @@ -838,7 +869,7 @@ public void RemoveCollider(int startIndex,int length) { public void SetColliders(params ColliderBase[] colliders) { SetCollidersIEnumerable(colliders); } - public CollisionController AddListener(bool multiColli,Action collideEnter, Action collide, Action collideLeave, params CollisionManager.CollisionGroup[] collisionGroups) + public CollisionController AddListener(bool multiColli,Action collideEnter, Action collide, Action collideLeave, params CollisionGroup[] collisionGroups) { if (DestroyedChecker()) return this;//销毁后不允许再增加 foreach (var item in Colliders) @@ -847,7 +878,7 @@ public CollisionController AddListener(bool multiColli,Action coll } return this; } - public CollisionController AddListener(Action collideEnter, Action collide, Action collideLeave,params CollisionManager.CollisionGroup[] collisionGroups) { + public CollisionController AddListener(Action collideEnter, Action collide, Action collideLeave,params CollisionGroup[] collisionGroups) { if (DestroyedChecker()) return this;//销毁后不允许再增加 foreach (var item in Colliders) { @@ -855,10 +886,10 @@ public CollisionController AddListener(Action collideEnter, Action } return this; } - public CollisionController AddListener(Action collide, params CollisionManager.CollisionGroup[] groups) { + public CollisionController AddListener(Action collide, params CollisionGroup[] groups) { return AddListener(null,collide,null,groups); } - public CollisionController AddListener(Action collide, bool multiColli=false, params CollisionManager.CollisionGroup[] groups) + public CollisionController AddListener(Action collide, bool multiColli=false, params CollisionGroup[] groups) { return AddListener(multiColli ,null, collide, null, groups); } @@ -940,7 +971,7 @@ public void Dispose() c.Dispose(); } } - BufferManager.Dispose(); + nativeCollisionManager.Dispose(); } public int groupCnt = Enum.GetValues(typeof(CollisionGroup)).Length; public LinkedHashSet[] groupedColliders;//这个到时候要改成LinkedHashSet之类的东西。。。 @@ -951,7 +982,7 @@ public void Dispose() public HashSet tmpDrawingHasCheckedObjectsInCurFrame = new HashSet();//用来debug有哪些物体当前帧被检查碰撞 //readonly bool multiCollisionOptimize = false;//先关掉多碰撞优化,测试功能 private Material _shapeMaterial;//测试 - public ColliderVertexBuffer BufferManager = new ColliderVertexBuffer(); + public ColliderNativeHelper nativeCollisionManager = new ColliderNativeHelper(); public CollisionManager() { groupedColliders = new LinkedHashSet[groupCnt]; for (int i = 0; i < groupCnt; i++) { @@ -966,16 +997,7 @@ public class __action_checkColli__ { public CollisionGroup recieveGroup; public bool multiColli = false; } - public enum CollisionGroup - { - Default, - Hero, - HeroBullet, - Bullet, - Enemy, - EnemyCollideBullet, - Item - } + //方便过后删除掉 //添加碰撞监听器 //有多碰撞需求再改吧……反正就改个list现在仅支持碰一个物体 @@ -1080,6 +1102,16 @@ public CollisionManager AddShape(ColliderBase collider) { groupedColliders[grp].Add(collider); } colliders.Add(collider); + if (collider.collider.colliderType == ColliderType.Polygon) + { + nativeCollisionManager.RegisterCollider(ref collider.collider,collider.collider.vertexCount); + } + else + { + nativeCollisionManager.RegisterCollider(ref collider.collider); + } + collider.Registered = true; + collider.SaveState(); return this; } public void RemoveShape(ColliderBase collider) { @@ -1092,9 +1124,11 @@ public void RemoveShape(ColliderBase collider) { int grp = (int)collider.colliGroup; groupedColliders[grp].Remove(collider); } + nativeCollisionManager.DeleteCollider(collider.collider); + colliders.Remove(collider); //调用销毁清理函数 collider.Destroy(); - colliders.Remove(collider); + collider.Registered = false; } public void SetCenter(in TSVector2 Pos,ColliderBase shape) { @@ -1265,7 +1299,18 @@ public void DebugDisplayShape(Matrix4x4 matrixTransform) { GL.PopMatrix(); } } -/* + + public enum CollisionGroup + { + Default, + Hero, + HeroBullet, + Bullet, + Enemy, + EnemyCollideBullet, + Item + } + /* def GJK(s1,s2) #两个形状s1,s2相交则返回True。所有的向量/点都是三维的,例如([x,y,0]) #第一步:选择一个初始方向,这个初始方向可以是随机选择的,但通常来说是两个形状中心之间的向量,即: diff --git a/Assets/ColliderStructure.cs b/Assets/ColliderStructure.cs index 0fe9ffa..56b7dcc 100644 --- a/Assets/ColliderStructure.cs +++ b/Assets/ColliderStructure.cs @@ -22,8 +22,9 @@ public enum ColliderType public struct ColliderStructure:IEquatable { private static int _globalIDCounter = 0; - + public ColliderType colliderType; + public CollisionGroup collisionGroup; public TSVector2 center; #region 圆形,和双头圆形 public FP radius;//圆形半径 @@ -37,7 +38,7 @@ public struct ColliderStructure:IEquatable /// /// 目前进行过修改的vertexStartIndex没同步到主线程上!!! /// - public int vertexStartIndex; + internal int vertexStartIndex; /// /// 注意,vertexCount不可变 /// @@ -63,15 +64,21 @@ public static ColliderStructure CreateInstance() { var t = new ColliderStructure { - uniqueID = _globalIDCounter++ + uniqueID = _globalIDCounter++, + collisionGroup = CollisionGroup.Default, }; return t; } - + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(ColliderStructure other) { return this.uniqueID==other.uniqueID; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override int GetHashCode() + { + return uniqueID; + } } [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] public struct GetFurthestPointExtensions @@ -426,16 +433,16 @@ public static bool CheckCollide(in ColliderStructure shape1, in ColliderStructur } } [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] - public class ColliderVertexBuffer:IDisposable{ + public class ColliderNativeHelper:IDisposable{ public static NativeArray.ReadOnly instancedBuffer { get { - return CollisionManager.instance.BufferManager.vertices.AsReadOnly(); + return CollisionManager.instance.nativeCollisionManager.vertices.AsReadOnly(); } } - - public NativeHashMap colliders = new NativeHashMap(16,Allocator.Persistent); + + public NativeHashMap colliders = new NativeHashMap(2048,Allocator.Persistent); public NativeList vertices = new NativeList(Allocator.Persistent); public int removedDelta = 0; @@ -456,11 +463,26 @@ static void RegisterCollider( vertices.Resize(colli.vertexStartIndex+vertexCount,NativeArrayOptions.UninitializedMemory); } [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + static void RegisterCollider( + in NativeHashMap colliders,in NativeList vertices, + ref ColliderStructure colli + ) + { + colli.vertexCount = 0; + colliders.Add(colli.uniqueID,colli); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RegisterCollider(ref ColliderStructure colli,in int vertexCount) { RegisterCollider(colliders,vertices,ref colli,vertexCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RegisterCollider(ref ColliderStructure colli) + { + RegisterCollider(colliders,vertices,ref colli); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] static void ModifyCollider( ref NativeHashMap colliders,ref NativeList vertices, @@ -478,6 +500,22 @@ public void ModifyCollider(in ColliderStructure colli, in NativeArray } [MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + static void SyncCollider( + ref NativeHashMap colliders, + ref ColliderStructure colli + ) + { + var realColli = colliders[colli.uniqueID]; + colli.vertexStartIndex = realColli.vertexStartIndex;//顶点起始坐标同步,但是请不要在主程序中使用 + colliders[colli.uniqueID] = colli; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SyncCollider(ref ColliderStructure colli) + { + SyncCollider(ref colliders,ref colli); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] static void DeleteCollider(ref int removedDelta,ref NativeHashMap colliders,in ColliderStructure colli) { removedDelta += colli.vertexCount; @@ -550,6 +588,7 @@ ref NativeList vertices foreach (var ele in colliders) { ref var val = ref ele.Value; + if(val.vertexCount==0){continue;} NativeArray.Copy(listArray,val.vertexStartIndex,newListArray,newStartIndex,val.vertexCount); //newList.AddRangeNoResize(((byte*)listArrayPointer+(_sizeof_*val.vertexStartIndex)), val.vertexCount); val.vertexStartIndex = newStartIndex; @@ -707,7 +746,7 @@ public void Add(int start, int end) else { segments.ResizeUninitialized(len+1); - ColliderVertexBuffer.MoveLeft(segments,left+1,len-left-1,-1); + ColliderNativeHelper.MoveLeft(segments,left+1,len-left-1,-1); } segments[left + 1]=new Segment(currentStart, currentEnd); } @@ -749,7 +788,7 @@ public void AddPoint(int point) else { segments.ResizeUninitialized(len+1); - ColliderVertexBuffer.MoveLeft(segments,left+1,len-left-1,-1); + ColliderNativeHelper.MoveLeft(segments,left+1,len-left-1,-1); } segments[left + 1]=new Segment(currentStart, currentEnd); } diff --git a/Assets/ColliderTester.cs b/Assets/ColliderTester.cs index 0e2b481..e097e7c 100644 --- a/Assets/ColliderTester.cs +++ b/Assets/ColliderTester.cs @@ -70,11 +70,11 @@ void CreateCollider() collider.enabled = true; if (moveMode == MoveMode.Keyboard) { - collider.colliGroup = CollisionManager.CollisionGroup.Default; + collider.colliGroup = CollisionGroup.Default; } else { - collider.colliGroup = CollisionManager.CollisionGroup.Bullet; + collider.colliGroup = CollisionGroup.Bullet; } controller = new CollisionController(collider); if (moveMode == MoveMode.Keyboard) @@ -87,7 +87,7 @@ void CreateCollider() { meshRenderer.material.color=Color.green; Debug.Log("collide exit"); - },CollisionManager.CollisionGroup.Bullet); + },CollisionGroup.Bullet); } } From 2dd869c9ffb6132bb210b3fe0a6d7a95ba295077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B3=A0=E6=BC=AA?= <32807696+AngelShadow2017@users.noreply.github.com> Date: Sun, 13 Apr 2025 16:48:55 +0800 Subject: [PATCH 5/9] move enabled to structure --- Assets/ColliderObj.cs | 11 ++++------- Assets/ColliderStructure.cs | 19 ++++++++----------- Assets/ColliderTester.cs | 2 +- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/Assets/ColliderObj.cs b/Assets/ColliderObj.cs index dc10133..722aa15 100644 --- a/Assets/ColliderObj.cs +++ b/Assets/ColliderObj.cs @@ -41,7 +41,6 @@ public abstract class ColliderBase : ICollideShape public ref ColliderStructure Collider => ref collider; //protected CollisionGroup __colli__ = CollisionGroup.Default; - protected bool __enabled__ = true; public int tag = -1;//用来识别特定的tag public CollisionGroup colliGroup { get => collider.collisionGroup; @@ -49,13 +48,11 @@ public CollisionGroup colliGroup { } public bool enabled { - get - { - return __enabled__; - } + get => collider.enabled!=0; set { - __enabled__ = value; + collider.enabled = value ? (byte)1 : (byte)0; + SaveState(); } } @@ -450,7 +447,7 @@ public PolygonCollider(TSVector2[] vertex, TSVector2 center, FP rotation, Collis RotateVertexs(false); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override ColliderStructure GetRealCollider() + public sealed override ColliderStructure GetRealCollider() { return CollisionManager.instance.nativeCollisionManager.colliders[collider.uniqueID]; } diff --git a/Assets/ColliderStructure.cs b/Assets/ColliderStructure.cs index 56b7dcc..97b7fd8 100644 --- a/Assets/ColliderStructure.cs +++ b/Assets/ColliderStructure.cs @@ -22,7 +22,7 @@ public enum ColliderType public struct ColliderStructure:IEquatable { private static int _globalIDCounter = 0; - + public byte enabled; public ColliderType colliderType; public CollisionGroup collisionGroup; public TSVector2 center; @@ -66,6 +66,7 @@ public static ColliderStructure CreateInstance() { uniqueID = _globalIDCounter++, collisionGroup = CollisionGroup.Default, + enabled=0 }; return t; } @@ -445,7 +446,6 @@ public static NativeArray.ReadOnly instancedBuffer public NativeHashMap colliders = new NativeHashMap(2048,Allocator.Persistent); public NativeList vertices = new NativeList(Allocator.Persistent); - public int removedDelta = 0; //public SegmentManager removedIndexs = new SegmentManager(Allocator.Persistent); [MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] @@ -469,7 +469,6 @@ static void RegisterCollider( ref ColliderStructure colli ) { - colli.vertexCount = 0; colliders.Add(colli.uniqueID,colli); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -516,9 +515,8 @@ public void SyncCollider(ref ColliderStructure colli) } [MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] - static void DeleteCollider(ref int removedDelta,ref NativeHashMap colliders,in ColliderStructure colli) + static void DeleteCollider(ref NativeHashMap colliders,in ColliderStructure colli) { - removedDelta += colli.vertexCount; //var realColli = colliders[colli.uniqueID]; //removedIndexs.Add(realColli.vertexStartIndex,realColli.vertexStartIndex+realColli.vertexCount-1); if(colliders.IsCreated) @@ -528,7 +526,7 @@ static void DeleteCollider(ref int removedDelta,ref NativeHashMap(in NativeList arr,int srcStart, int count,int [MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] public static void CompactVertexBuffers( - ref int removedDelta,ref NativeHashMap colliders, + ref NativeHashMap colliders, ref NativeList vertices ) { @@ -578,8 +576,8 @@ ref NativeList vertices { throw new NullReferenceException("vertices数组未创建"); } - NativeList newList = new NativeList(vertices.Length-removedDelta,Allocator.Persistent); - newList.ResizeUninitialized(vertices.Length - removedDelta); + NativeList newList = new NativeList(vertices.Length,Allocator.Persistent); + newList.ResizeUninitialized(vertices.Length); //var listArrayPointer = vertices.GetUnsafeReadOnlyPtr(); var listArray = vertices.AsReadOnly(); var newListArray = newList.AsArray(); @@ -596,7 +594,6 @@ ref NativeList vertices } vertices.Dispose(); vertices = newList; - removedDelta = 0; } /// /// 移除vertexbuffer的洞洞,注意这是个比较消耗性能的操作,并且要在主线程中同步所有的结构体的顶点位置?(提供同步方法,如果需要的话可以同步,貌似目前不需要,只是会throw出错而已) @@ -605,7 +602,7 @@ ref NativeList vertices [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] public void CompactVertexBuffers() { - CompactVertexBuffers(ref removedDelta,ref colliders,ref vertices); + CompactVertexBuffers(ref colliders,ref vertices); } public void Dispose() diff --git a/Assets/ColliderTester.cs b/Assets/ColliderTester.cs index e097e7c..a321bf5 100644 --- a/Assets/ColliderTester.cs +++ b/Assets/ColliderTester.cs @@ -67,7 +67,6 @@ void CreateCollider() default: throw new Exception("not initialized"); } - collider.enabled = true; if (moveMode == MoveMode.Keyboard) { collider.colliGroup = CollisionGroup.Default; @@ -77,6 +76,7 @@ void CreateCollider() collider.colliGroup = CollisionGroup.Bullet; } controller = new CollisionController(collider); + collider.enabled = true; if (moveMode == MoveMode.Keyboard) { controller.AddListener(false, (obj) => From 712fad8ee6312dad40301b9107ea7e1e96fc00d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B3=A0=E6=BC=AA?= <32807696+AngelShadow2017@users.noreply.github.com> Date: Sun, 13 Apr 2025 21:28:35 +0800 Subject: [PATCH 6/9] preparation --- Assets/ColliderNativeJobs.cs | 9 +++++++ Assets/ColliderNativeJobs.cs.meta | 3 +++ Assets/ColliderStructure.cs | 41 ++++++++++++++++++++++--------- Assets/TrueSync/Fuck.cs | 8 ------ Assets/TrueSync/Fuck.cs.meta | 3 --- 5 files changed, 41 insertions(+), 23 deletions(-) create mode 100644 Assets/ColliderNativeJobs.cs create mode 100644 Assets/ColliderNativeJobs.cs.meta delete mode 100644 Assets/TrueSync/Fuck.cs delete mode 100644 Assets/TrueSync/Fuck.cs.meta diff --git a/Assets/ColliderNativeJobs.cs b/Assets/ColliderNativeJobs.cs new file mode 100644 index 0000000..7f1ddbf --- /dev/null +++ b/Assets/ColliderNativeJobs.cs @@ -0,0 +1,9 @@ +using TrueSync; +using Unity.Burst; +using Unity.Collections; +using Unity.Jobs; +using ZeroAs.DOTS.Colliders; + +namespace ZeroAs.DOTS.Colliders.Jobs +{ +} \ No newline at end of file diff --git a/Assets/ColliderNativeJobs.cs.meta b/Assets/ColliderNativeJobs.cs.meta new file mode 100644 index 0000000..af23c20 --- /dev/null +++ b/Assets/ColliderNativeJobs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 84c8556bd8874013b10bdd5a04a216ae +timeCreated: 1744534219 \ No newline at end of file diff --git a/Assets/ColliderStructure.cs b/Assets/ColliderStructure.cs index 97b7fd8..f493d6d 100644 --- a/Assets/ColliderStructure.cs +++ b/Assets/ColliderStructure.cs @@ -18,23 +18,16 @@ public enum ColliderType Polygon, DoubleCircle, } + [BurstCompile(OptimizeFor = OptimizeFor.Performance)] [StructLayout(LayoutKind.Sequential)] public struct ColliderStructure:IEquatable { - private static int _globalIDCounter = 0; + //从 1 开始,代表uniqueID如果是0就有问题了,因为这代表是从new创建出来的,不支持从new创建 + private static int _globalIDCounter = 1; public byte enabled; public ColliderType colliderType; public CollisionGroup collisionGroup; - public TSVector2 center; - #region 圆形,和双头圆形 - public FP radius;//圆形半径 - #endregion - #region 椭圆形 - public TSVector2 Axis, SqrAxis; - public FP b2Dividea2,rot; - #endregion #region 多边形 - /// /// 目前进行过修改的vertexStartIndex没同步到主线程上!!! /// @@ -44,6 +37,13 @@ public struct ColliderStructure:IEquatable /// public int vertexCount,uniqueID;//indexInArray若设置为小于0就代表会被删除 #endregion + #region 圆形,和双头圆形 + public FP radius;//圆形半径 + #endregion + #region 椭圆形 + public FP b2Dividea2,rot; + public TSVector2 Axis, SqrAxis; + #endregion #region 双头圆形 public TSVector2 circleCenter1{ [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -59,25 +59,42 @@ public TSVector2 circleCenter2{ } #endregion - + public TSVector2 center; public static ColliderStructure CreateInstance() { var t = new ColliderStructure { uniqueID = _globalIDCounter++, collisionGroup = CollisionGroup.Default, - enabled=0 + enabled=1 }; return t; } + [BurstCompile, MethodImpl(MethodImplOptions.AggressiveInlining)] + static void CheckInvalidNew(in ColliderStructure structure) + { +#if UNITY_EDITOR + if (structure.uniqueID==0) + { + throw new InvalidOperationException("该结构不能从new初始化,请使用CreateInstance函数获取新实例"); + } +#endif + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(ColliderStructure other) { + #if UNITY_EDITOR + CheckInvalidNew(this); + #endif return this.uniqueID==other.uniqueID; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() { +#if UNITY_EDITOR + CheckInvalidNew(this); +#endif return uniqueID; } } diff --git a/Assets/TrueSync/Fuck.cs b/Assets/TrueSync/Fuck.cs deleted file mode 100644 index 54bfe29..0000000 --- a/Assets/TrueSync/Fuck.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace TrueSync -{ - /*public partial struct FP - { - public static readonly long[] TanLut = { 1 }; - public static readonly long[] AcosLut = { 1 }; - }*/ -} \ No newline at end of file diff --git a/Assets/TrueSync/Fuck.cs.meta b/Assets/TrueSync/Fuck.cs.meta deleted file mode 100644 index 0ad40f9..0000000 --- a/Assets/TrueSync/Fuck.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 45df6d4ca1524c0f9e82eaf172ae5e9c -timeCreated: 1744036628 \ No newline at end of file From d4b92e92f18b34646c040347b9ecd3242c17fa2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B3=A0=E6=BC=AA?= <32807696+AngelShadow2017@users.noreply.github.com> Date: Mon, 14 Apr 2025 14:00:38 +0800 Subject: [PATCH 7/9] Multi threading collision engine. --- Assets/ColliUpdate.cs | 7 + Assets/ColliderNativeJobs.cs | 373 ++++++++++++++++++++++++- Assets/ColliderObj.cs | 284 +++++++++++++++---- Assets/ColliderStructure.cs | 72 ++++- Assets/ColliderTester.cs | 15 +- Assets/JobsTesting.cs | 2 +- Assets/{math.cs => Mathz.cs} | 2 +- Assets/{math.cs.meta => Mathz.cs.meta} | 0 Assets/RandomClones.cs | 26 ++ Assets/RandomClones.cs.meta | 2 + Assets/Scenes/New Scene.unity | 52 +++- Packages/manifest.json | 2 +- Packages/packages-lock.json | 2 +- 13 files changed, 768 insertions(+), 71 deletions(-) rename Assets/{math.cs => Mathz.cs} (99%) rename Assets/{math.cs.meta => Mathz.cs.meta} (100%) create mode 100644 Assets/RandomClones.cs create mode 100644 Assets/RandomClones.cs.meta diff --git a/Assets/ColliUpdate.cs b/Assets/ColliUpdate.cs index 4518c9a..fe74f85 100644 --- a/Assets/ColliUpdate.cs +++ b/Assets/ColliUpdate.cs @@ -14,7 +14,14 @@ void Awake() private void Update() { + //CollisionManager.instance.ReloadJobCollisionChecker(); CollisionManager.instance.TraverseAllListener(); + if ( + CollisionManager.instance.converterManager.IsCreated) + { + + CollisionManager.instance.converterManager.Dispose(); + } } private void LateUpdate() diff --git a/Assets/ColliderNativeJobs.cs b/Assets/ColliderNativeJobs.cs index 7f1ddbf..4531c43 100644 --- a/Assets/ColliderNativeJobs.cs +++ b/Assets/ColliderNativeJobs.cs @@ -1,9 +1,380 @@ -using TrueSync; +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Core.Algorithm; +using TrueSync; using Unity.Burst; using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; using Unity.Jobs; +using UnityEngine; using ZeroAs.DOTS.Colliders; namespace ZeroAs.DOTS.Colliders.Jobs { + + + + [BurstCompile(OptimizeFor = OptimizeFor.Performance)] + public struct CollisionGroupHashSetToArrayManager:IDisposable + { + + private NativeReference _destroyFlag; + private byte _isCreated; + + private bool convertIsCreateBool + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => _isCreated != 0; + } + public bool IsCreated + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + #if UNITY_EDITOR + if (_destroyFlag.IsCreated!=convertIsCreateBool) + { + throw new InvalidOperationException("忘记释放CollisionGroupHashSetToArrayManager内存"); + } + #endif + + return convertIsCreateBool; + } + } + + public bool Available + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { +#if UNITY_EDITOR + if (_destroyFlag.IsCreated!=convertIsCreateBool) + { + throw new InvalidOperationException("忘记释放CollisionGroupHashSetToArrayManager内存"); + } +#endif + + return _destroyFlag.IsCreated; + } + } + [StructLayout(LayoutKind.Sequential)] + public struct ColliGroupJobData + { + public byte created; + public JobHandle handle; + } + //可以在其他的代码中向这里Complete来保证所有任务完成 + public NativeList _allHandles; + //这里是 + public NativeArray _collisionGroupInfos; + public NativeArray _collisionGroupObjs; + + private NativeArray>.ReadOnly useOutSideHashSets; + public NativeArray>.ReadOnly GroupedColliders => useOutSideHashSets; + // 初始化方法 + public CollisionGroupHashSetToArrayManager(NativeArray>.ReadOnly hashset) + { + _isCreated = 1; + _allHandles = new NativeList(CollisionManager.groupCnt, Allocator.TempJob); + _collisionGroupInfos = new NativeArray(CollisionManager.groupCnt, Allocator.TempJob); + _collisionGroupObjs = new NativeArray(CollisionManager.groupCnt, Allocator.TempJob); + useOutSideHashSets = hashset; + _destroyFlag=new NativeReference(Allocator.Temp, NativeArrayOptions.UninitializedMemory); + } + [MethodImpl(MethodImplOptions.AggressiveInlining),BurstCompile(OptimizeFor = OptimizeFor.Performance)] + public static void GetJobData( + ref NativeArray _collisionGroupInfos, + ref NativeArray _collisionGroupObjs, + in NativeArray>.ReadOnly useOutSideHashSets, + ref NativeList _allHandles, + in int index, + out ColliGroupJobData data + ) + { + //避免重复获取job,如果已经有正在执行中的复制job则获取那个就行 + if (_collisionGroupInfos[index].created != 0) + { + data = _collisionGroupInfos[index]; + return; + } + var job = new ColliGroupJobData(); + job.created = (byte)1; + var getCollisionArrayJob = new ConvertCheckGroupToArrayJob(); + //自动创建Hashset转数组的job并添加到资源里面 + getCollisionArrayJob.checkGroupArray = new NativeArray(useOutSideHashSets[index].Count, Allocator.TempJob); + getCollisionArrayJob.checkGroup = useOutSideHashSets[index].AsReadOnly(); + job.handle = getCollisionArrayJob.Schedule(); + _allHandles.Add(job.handle); + _collisionGroupObjs[index] = getCollisionArrayJob; + data = _collisionGroupInfos[index] = job; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ColliGroupJobData EnsureJobData(int index) + { + GetJobData( + ref _collisionGroupInfos, + ref _collisionGroupObjs, + in useOutSideHashSets, + ref _allHandles, + index, + out ColliGroupJobData data + ); + return data; + } + + // 清理方法 + public void Dispose() + { + _isCreated = 0; + _collisionGroupInfos.Dispose(); + _allHandles.Dispose(); + for (int i = 0; i < _collisionGroupObjs.Length; i++) + { + _collisionGroupObjs[i].checkGroupArray.Dispose(); + } + _collisionGroupObjs.Dispose(); + if(_destroyFlag.IsCreated) _destroyFlag.Dispose(); + //hashset是在外面控制的 + } + } + + [BurstCompile(OptimizeFor = OptimizeFor.Performance)] + public struct CollisionChecker + { + private const int batchSingleCount = 64; + #region 一对多,并且返回最小的id那个 + /// + /// 查找一对多的碰撞体,并尝试获取最小的ID,请在主线程里面调用,之后统一获取到结果之后请调用PostProcess结果来获取最终结果 + /// + /// + /// + /// + /// + /// + /// + /// + /// + [BurstCompile(OptimizeFor = OptimizeFor.Performance)] + public static void FindMinCollidingId( + out NativeArray minResults_ret, + out JobHandle waitHandle, + + ref CollisionGroupHashSetToArrayManager toArrayManager, + in int groupIndex, + in ColliderStructure targetCollider, + in NativeHashMap.ReadOnly allColliders, + in NativeArray.ReadOnly vertexBuffer, + Allocator allocator = Allocator.TempJob) + { + // 第一步:转换HashSet为数组 + toArrayManager.EnsureJobData(groupIndex); + // 第二步:准备分块处理 + int elementCount = toArrayManager.GroupedColliders[groupIndex].Count; + int batchCount = batchSingleCount;//Unity.Mathematics.math.max(1, elementCount / 32); + int batchSize = nextPow2(elementCount / batchCount); + batchCount = (elementCount+batchSize-1) / batchSize; + var minResults = new NativeArray( + batchCount, + allocator, + NativeArrayOptions.UninitializedMemory); + + var handles = new NativeList(batchCount, allocator); + + // 分块调度作业 + for (int i = 0; i < batchCount; i++) + { + int start = i * batchSize; + int end = Unity.Mathematics.math.min((start+batchSize),elementCount); + + var checkJob = new CollisionCheckJob + { + checkGroupArray = toArrayManager._collisionGroupObjs[groupIndex].checkGroupArray, + allColliders = allColliders, + vertexBuffer = vertexBuffer, + targetCollider = targetCollider, + startIndex = start, + endIndex = end, + resultIndex = i, + minResults = minResults + }; + + handles.Add(checkJob.Schedule(toArrayManager._collisionGroupInfos[groupIndex].handle)); + } + + minResults_ret = minResults; + waitHandle = JobHandle.CombineDependencies(handles.AsArray()); + handles.Dispose(); + } + /// + /// 请在主线程中调用 + /// + /// + /// + [BurstCompile(OptimizeFor = OptimizeFor.Performance)] + public static int PostProcessMinResults(ref NativeArray minResults) + { + // 第三步:收集最终结果 + int finalResult = int.MaxValue; + int len = minResults.Length; + //Debug.Log("Length: "+len); + for (int i = 0; i < len; i++) + { + //Debug.Log("WhatIsMin: "+minResults[i]); + finalResult = Unity.Mathematics.math.min(finalResult, minResults[i]); + } + minResults.Dispose(); + return finalResult; + } + #endregion + [BurstCompile(OptimizeFor = OptimizeFor.Performance)] + static int nextPow2(int n) + { + n--; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n++; + return n == 0 ? 1 : n; + } + #region 一对多,并且返回排完序后的数组 + [BurstCompile(OptimizeFor = OptimizeFor.Performance)] + public static void FindAllCollidingIds( + out NativeQueue resultsQueue, + out JobHandle waitHandle, + ref CollisionGroupHashSetToArrayManager toArrayManager, + in int groupIndex, + in ColliderStructure targetCollider, + in NativeHashMap.ReadOnly allColliders, + in NativeArray.ReadOnly vertexBuffer, + Allocator allocator = Allocator.TempJob) + { + // 确保HashSet转Array任务完成 + var groupData = toArrayManager.EnsureJobData(groupIndex); + + // 创建结果队列 + resultsQueue = new NativeQueue(allocator); + + // 准备Job参数 + var job = new SingleToManyCollisionJob + { + targetCollider = targetCollider, + CheckGroup = toArrayManager._collisionGroupObjs[groupIndex].checkGroupArray, + AllColliders = allColliders, + VertexBuffer = vertexBuffer, + Results = resultsQueue.AsParallelWriter() + }; + int totalLen = toArrayManager._collisionGroupObjs[groupIndex].checkGroup.Count; + // 调度并行任务 + waitHandle = job.ScheduleParallel( + totalLen, + batchSingleCount,//nextPow2(totalLen/32+1), + groupData.handle); + } + + [BurstCompile(OptimizeFor = OptimizeFor.Performance)] + public static void PostProcessAllResults( + out NativeArray resArray, + ref NativeQueue resultsQueue, + Allocator allocator = Allocator.Temp, + bool sort = true) + { + // 转换队列为数组 + NativeArray resultArray = resultsQueue.ToArray(allocator); + resultsQueue.Dispose(); + + // 排序(可选) + if (sort && resultArray.Length > 1) + { + resultArray.Sort(); + } + + resArray = resultArray; + } + + + #endregion + } + + [BurstCompile] + public struct ConvertCheckGroupToArrayJob : IJob + { + [ReadOnly] public NativeHashSet.ReadOnly checkGroup; + [WriteOnly] public NativeArray checkGroupArray; + + public void Execute() + { + checkGroupArray.CopyFrom(checkGroup.ToNativeArray(Allocator.Temp)); + } + } + + [BurstCompile(OptimizeFor = OptimizeFor.Performance)] + public struct CollisionCheckJob : IJob + { + [ReadOnly] public NativeArray checkGroupArray; + [ReadOnly] public NativeHashMap.ReadOnly allColliders; + [ReadOnly] public NativeArray.ReadOnly vertexBuffer; + [ReadOnly] public ColliderStructure targetCollider; + + [ReadOnly]public int startIndex; + [ReadOnly]public int endIndex; + [ReadOnly]public int resultIndex; + + [NativeDisableContainerSafetyRestriction] public NativeArray minResults; + + public void Execute() + { + int localMin = int.MaxValue; + for (int i = startIndex; i < endIndex; i++) + { + int otherId = checkGroupArray[i]; + if (!allColliders.TryGetValue(otherId, out var otherCollider)) + { + continue; + } + if (otherCollider.enabled == 0) + { + continue; + } + + if (CollideExtensions.CheckCollide( + targetCollider, + otherCollider, + vertexBuffer)) + { + localMin = Unity.Mathematics.math.min(localMin, otherId); + } + } + + minResults[resultIndex] = localMin; + } + } + [BurstCompile(OptimizeFor = OptimizeFor.Performance)] + public struct SingleToManyCollisionJob : IJobFor + { + [ReadOnly] public ColliderStructure targetCollider; + [ReadOnly] public NativeArray CheckGroup; + [ReadOnly] public NativeHashMap.ReadOnly AllColliders; + [ReadOnly] public NativeArray.ReadOnly VertexBuffer; + + [WriteOnly] + public NativeQueue.ParallelWriter Results; + + public void Execute(int index) + { + int otherID = CheckGroup[index]; + if (!AllColliders.TryGetValue(otherID, out ColliderStructure otherCollider)) + return; + if (otherCollider.enabled == 0) + { + return; + } + if (CollideExtensions.CheckCollide(targetCollider, otherCollider, VertexBuffer)) + { + Results.Enqueue(otherID); + } + } + } } \ No newline at end of file diff --git a/Assets/ColliderObj.cs b/Assets/ColliderObj.cs index 722aa15..2e6d744 100644 --- a/Assets/ColliderObj.cs +++ b/Assets/ColliderObj.cs @@ -4,9 +4,11 @@ using System.Text; using TrueSync; using Unity.Collections; +using Unity.Jobs; using UnityEngine; using UnityEngine.Pool; using ZeroAs.DOTS.Colliders; +using ZeroAs.DOTS.Colliders.Jobs; namespace Core.Algorithm { @@ -36,16 +38,35 @@ public interface IMasteredCollider [Serializable] public abstract class ColliderBase : ICollideShape { + + public int UniqueID + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => collider.uniqueID; + } + public bool Registered { get; set; } = false; public ColliderStructure collider; public ref ColliderStructure Collider => ref collider; //protected CollisionGroup __colli__ = CollisionGroup.Default; public int tag = -1;//用来识别特定的tag - public CollisionGroup colliGroup { + public CollisionGroup colliGroup + { get => collider.collisionGroup; - set => collider.collisionGroup = value;//记得sync + set + { + #if UNITY_EDITOR + if (Registered) + { + throw new InvalidOperationException("不支持在注册给了管理器之后再改变Group"); + } + #endif + collider.collisionGroup = value; + } + //记得sync } + public bool enabled { get => collider.enabled!=0; @@ -539,7 +560,6 @@ void MoveDeltaPos(TSVector2 pos) }*/ public override void Destroy() { - CollisionManager.instance.nativeCollisionManager.DeleteCollider(collider); if(movedVertexs.IsCreated) movedVertexs.Dispose(); } @@ -961,7 +981,7 @@ public static CollisionManager instance public void Dispose() { - foreach (var colliderBase in colliders) + foreach (var colliderBase in colliders.Values) { if (colliderBase is IDisposable c) { @@ -969,13 +989,20 @@ public void Dispose() } } nativeCollisionManager.Dispose(); + if (converterManager.IsCreated) + { + converterManager.Dispose(); + } } - public int groupCnt = Enum.GetValues(typeof(CollisionGroup)).Length; + public static readonly int groupCnt = Enum.GetValues(typeof(CollisionGroup)).Length; public LinkedHashSet[] groupedColliders;//这个到时候要改成LinkedHashSet之类的东西。。。 - public HashSet colliders = new HashSet(); + public Dictionary colliders = new(); public LinkedDictionary> listeners = new LinkedDictionary>(); public LinkedDictionary> receivers = new LinkedDictionary>(); - + /// + /// 每帧末尾记得调用Dispose + /// + public CollisionGroupHashSetToArrayManager converterManager; public HashSet tmpDrawingHasCheckedObjectsInCurFrame = new HashSet();//用来debug有哪些物体当前帧被检查碰撞 //readonly bool multiCollisionOptimize = false;//先关掉多碰撞优化,测试功能 private Material _shapeMaterial;//测试 @@ -1098,7 +1125,7 @@ public CollisionManager AddShape(ColliderBase collider) { int grp = (int)collider.colliGroup; groupedColliders[grp].Add(collider); } - colliders.Add(collider); + colliders.Add(collider.UniqueID,collider); if (collider.collider.colliderType == ColliderType.Polygon) { nativeCollisionManager.RegisterCollider(ref collider.collider,collider.collider.vertexCount); @@ -1121,8 +1148,11 @@ public void RemoveShape(ColliderBase collider) { int grp = (int)collider.colliGroup; groupedColliders[grp].Remove(collider); } - nativeCollisionManager.DeleteCollider(collider.collider); - colliders.Remove(collider); + if (!nativeCollisionManager.Disposed) + { + nativeCollisionManager.DeleteCollider(collider.collider); + } + colliders.Remove(collider.UniqueID); //调用销毁清理函数 collider.Destroy(); collider.Registered = false; @@ -1130,34 +1160,21 @@ public void RemoveShape(ColliderBase collider) { public void SetCenter(in TSVector2 Pos,ColliderBase shape) { shape.SetCenter(Pos); - /*if (multiCollisionOptimize) - { - quadTreeOptmize.InsertCollider(shape); - }*/ + } - /*public void SwitchMultiColli(bool swit) { - if (multiCollisionOptimize == swit) { return; } - if (swit) - { - foreach(var i in colliders) - { - quadTreeOptmize.InsertCollider(i); - } - foreach (var groupHashSet in groupedColliders) { - groupHashSet.Clear(); - } - } - else + + private bool readyToBatchCheckCollision => converterManager.Available; + + public void ReloadJobCollisionChecker() { - quadTreeOptmize.ClearAllCollider(); - foreach(var i in colliders) + if (converterManager.IsCreated) { - AddShape(i); + converterManager.Dispose(); } + converterManager = new CollisionGroupHashSetToArrayManager(nativeCollisionManager.groupedColliders.AsReadOnly()); } - multiCollisionOptimize = swit; - }*/ + public ColliderBase CheckCollision(ColliderBase obj,CollisionGroup group) { if (!obj.enabled) { @@ -1203,36 +1220,187 @@ public void TraverseAllListener() { { tmpDrawingHasCheckedObjectsInCurFrame.Clear(); } - foreach(var kvPair in listeners) + + #region 不适用多线程 + if (!readyToBatchCheckCollision) { - var val = kvPair.Value; - foreach (var obj in val) + foreach(var kvPair in listeners) { - if (!obj.collider.enabled) { continue; }//如果自身不允许碰撞就不碰 - foreach (var i in obj.checkGroups) + var val = kvPair.Value; + foreach (var obj in val) { - //多碰撞不支持接收器 - if (obj.multiColli) + if (!obj.collider.enabled) { continue; }//如果自身不允许碰撞就不碰 + foreach (var i in obj.checkGroups) { - List collis = ListPool.Get(); - CheckCollision(obj.collider, i, ref collis); - foreach(var retObj in collis) + //多碰撞不支持接收器 + if (obj.multiColli) { + List collis = ListPool.Get(); + CheckCollision(obj.collider, i, ref collis); + foreach(var retObj in collis) + { + callActionComponent(retObj, obj); + } + ListPool.Release(collis); + }else{ + var retObj = CheckCollision(obj.collider, i); callActionComponent(retObj, obj); + //如果对方有接收器 + if (retObj != null && receivers.ContainsKey(retObj) && receivers[retObj].ContainsKey(obj.collider.colliGroup)) + { + callActionComponent(obj.collider, receivers[retObj][obj.collider.colliGroup]); + } + } + } + } + } + } + #endregion + #region 适用多线程 + else + { + var actionList = ListPool<__action_checkColli__>.Get(); + foreach (var listenerSet in listeners.Values) + { + actionList.AddRange(listenerSet); + } + int actionListCount = actionList.Count; + var jobHandles = new NativeList(actionListCount, Allocator.Temp); + var singleResults = new NativeArray>(actionListCount, Allocator.Temp); + var multiResults = new NativeArray>(actionListCount, Allocator.Temp); + var nativeColliders = nativeCollisionManager.colliders.AsReadOnly(); + var vertexBuffer = nativeCollisionManager.vertices.AsReadOnly(); + for (int i = 0; i < actionListCount; i++) + { + var action = actionList[i]; + if (!action.collider.enabled) + { + continue; + } +#if UNITY_EDITOR + if (!nativeColliders.TryGetValue(action.collider.UniqueID, out var targetCollider)) + { + throw new NullReferenceException("无法在本地数组里面找到collider"); + } +#endif + //使用指定的collider,但是一定要保证在数组里面 + targetCollider = action.collider.GetRealCollider(); + + // 对每个检测组进行处理 + foreach (var group in action.checkGroups) + { + int groupIndex = (int)group; + + if (action.multiColli) + { + // 多碰撞检测 + CollisionChecker.FindAllCollidingIds( + out var queueResult, + out var waitHandle, + ref converterManager, + groupIndex, + targetCollider, + nativeColliders, + vertexBuffer + ); + + multiResults[i] = queueResult; + + jobHandles.Add(waitHandle); + } + else + { + // 单碰撞检测 + CollisionChecker.FindMinCollidingId( + out var minResults, + out var waitHandle, + ref converterManager, + groupIndex, + targetCollider, + nativeColliders, + vertexBuffer + ); + singleResults[i] = minResults; + jobHandles.Add(waitHandle); + } + } + } + JobHandle.ScheduleBatchedJobs(); + JobHandle.CompleteAll(jobHandles.AsArray()); + jobHandles.Dispose(); + for (int i = 0; i < actionList.Count; i++) + { + var action = actionList[i]; + tmpDrawingHasCheckedObjectsInCurFrame.Add(action.collider); + + if (action.multiColli) + { + var tmpRes = multiResults[i]; + // 处理多碰撞结果 + if (tmpRes.Count>0) + { + //这里是排完序的,不用在意它不统一 + CollisionChecker.PostProcessAllResults( + out var res, + ref tmpRes); + foreach (var colliderId in res) + { + if (colliders.TryGetValue(colliderId, out var collided)) + { + callActionComponent(collided, action); + // 处理接收器回调 + //多碰撞无接收器 + /*if (receivers.TryGetValue(collided, out var receiverGroups) && + receiverGroups.TryGetValue(action.collider.colliGroup, out var receiverAction)) + { + callActionComponent(action.collider, receiverAction); + }*/ + } } - ListPool.Release(collis); - }else{ - var retObj = CheckCollision(obj.collider, i); - callActionComponent(retObj, obj); - //如果对方有接收器 - if (retObj != null && receivers.ContainsKey(retObj) && receivers[retObj].ContainsKey(obj.collider.colliGroup)) + } + + /*if (multiResults[i].IsCreated) + { + multiResults[i].Dispose(); + }*/ + } + else + { + var tmpRes = singleResults[i]; + int result = CollisionChecker.PostProcessMinResults(ref tmpRes); + // 处理单碰撞 + if(result!=int.MaxValue){//如果是最大就代表没有碰上任何物体 + if (colliders.TryGetValue(result, out var collided)) { - callActionComponent(obj.collider, receivers[retObj][obj.collider.colliGroup]); + callActionComponent(collided, action); + // 处理接收器回调 + if (receivers.TryGetValue(collided, out var receiverGroups) && + receiverGroups.TryGetValue(action.collider.colliGroup, out var receiverAction)) + { + callActionComponent(action.collider, receiverAction); + } } } + else + { + callActionComponent(null, action); + } + + /*if (singleResults[i].IsCreated) + { + singleResults[i].Dispose(); + }*/ } } + + + // 清理原生内存 + singleResults.Dispose(); + multiResults.Dispose(); + ListPool<__action_checkColli__>.Release(actionList); } + #endregion + } void callActionComponent(ColliderBase beCollidedObj,__action_checkColli__ action) { if (beCollidedObj != null) @@ -1277,7 +1445,7 @@ public void DebugDisplayShape(Matrix4x4 matrixTransform) { } else*/ { - foreach (var collider in colliders) + foreach (var collider in colliders.Values) { if (!collider.enabled || tmpDrawingHasCheckedObjectsInCurFrame.Contains(collider)) { continue; } Color color = Color.HSVToRGB((float)collider.colliGroup / groupCnt, 1, 1); @@ -1296,16 +1464,16 @@ public void DebugDisplayShape(Matrix4x4 matrixTransform) { GL.PopMatrix(); } } - + public enum CollisionGroup { - Default, - Hero, - HeroBullet, - Bullet, - Enemy, - EnemyCollideBullet, - Item + Default = 0, + Hero = 1, + HeroBullet = 2, + Bullet = 3, + Enemy = 4, + EnemyCollideBullet = 5, + Item = 6 } /* def GJK(s1,s2) diff --git a/Assets/ColliderStructure.cs b/Assets/ColliderStructure.cs index f493d6d..32fe087 100644 --- a/Assets/ColliderStructure.cs +++ b/Assets/ColliderStructure.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Core.Algorithm; +using JetBrains.Annotations; using TrueSync; using Unity.Burst; using Unity.Collections; @@ -451,7 +452,12 @@ public static bool CheckCollide(in ColliderStructure shape1, in ColliderStructur } } [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] - public class ColliderNativeHelper:IDisposable{ + public class ColliderNativeHelper:IDisposable + { + private bool disposed = false; + + public bool Disposed => disposed; + public static NativeArray.ReadOnly instancedBuffer { get @@ -461,9 +467,30 @@ public static NativeArray.ReadOnly instancedBuffer } public NativeHashMap colliders = new NativeHashMap(2048,Allocator.Persistent); + public NativeArray> groupedColliders; public NativeList vertices = new NativeList(Allocator.Persistent); + void InitGroupedStructs() + { + groupedColliders = new NativeArray>(CollisionManager.groupCnt,Allocator.Persistent); + for (int i = 0; i < CollisionManager.groupCnt; i++) { + groupedColliders[i] = new NativeHashSet(64,Allocator.Persistent); + } + } + + public ColliderNativeHelper() + { + InitGroupedStructs(); + } + //public SegmentManager removedIndexs = new SegmentManager(Allocator.Persistent); + /// + /// 注册Collider到数组里面,如果要调用这个静态函数记得配合RegisterCollisionGroup,必须同时使用 + /// + /// + /// + /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] static void RegisterCollider( @@ -479,6 +506,13 @@ static void RegisterCollider( //不需要清理内存,因为马上就会被设置 vertices.Resize(colli.vertexStartIndex+vertexCount,NativeArrayOptions.UninitializedMemory); } + /// + /// 注册Collider到数组里面,如果要调用这个静态函数记得配合RegisterCollisionGroup,必须同时使用 + /// + /// + /// + /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] static void RegisterCollider( @@ -489,14 +523,30 @@ ref ColliderStructure colli colliders.Add(colli.uniqueID,colli); } [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + static void RegisterCollisionGroup(ref NativeArray> collisionGroups, + in ColliderStructure colli) + { + collisionGroups[(int)colli.collisionGroup].Add(colli.uniqueID); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] + static void DeleteCollisionGroup(ref NativeArray> collisionGroups, + in ColliderStructure colli) + { + collisionGroups[(int)colli.collisionGroup].Remove(colli.uniqueID); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RegisterCollider(ref ColliderStructure colli,in int vertexCount) { RegisterCollider(colliders,vertices,ref colli,vertexCount); + RegisterCollisionGroup(ref groupedColliders,colli); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RegisterCollider(ref ColliderStructure colli) { RegisterCollider(colliders,vertices,ref colli); + RegisterCollisionGroup(ref groupedColliders,colli); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] @@ -507,7 +557,7 @@ static void ModifyCollider( { //获取实际上的colli var realColli = colliders[colli.uniqueID]; - NativeArray.Copy(modify,0,vertices,realColli.vertexStartIndex,realColli.vertexCount); + NativeArray.Copy(modify,0,vertices.AsArray(),realColli.vertexStartIndex,realColli.vertexCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ModifyCollider(in ColliderStructure colli, in NativeArray modify) @@ -530,6 +580,11 @@ public void SyncCollider(ref ColliderStructure colli) { SyncCollider(ref colliders,ref colli); } + /// + /// 从数组里面删除Collider,如果要调用这个静态函数记得配合DeleteCollisionGroup,必须同时使用 + /// + /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] static void DeleteCollider(ref NativeHashMap colliders,in ColliderStructure colli) @@ -544,6 +599,7 @@ static void DeleteCollider(ref NativeHashMap colliders,in public void DeleteCollider(in ColliderStructure colli) { DeleteCollider(ref colliders,colli); + DeleteCollisionGroup(ref groupedColliders,colli); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)] @@ -624,6 +680,7 @@ public void CompactVertexBuffers() public void Dispose() { + disposed = true; if(vertices.IsCreated) vertices.Dispose(); //removedIndexs.Dispose(); @@ -632,6 +689,17 @@ public void Dispose() colliders.Dispose(); } + if (groupedColliders.IsCreated) + { + foreach (var collider in groupedColliders) + { + if (collider.IsCreated) + { + collider.Dispose(); + } + } + groupedColliders.Dispose(); + } } /*[MethodImpl(MethodImplOptions.AggressiveInlining)] [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] diff --git a/Assets/ColliderTester.cs b/Assets/ColliderTester.cs index a321bf5..77a725b 100644 --- a/Assets/ColliderTester.cs +++ b/Assets/ColliderTester.cs @@ -82,17 +82,26 @@ void CreateCollider() controller.AddListener(false, (obj) => { meshRenderer.material.color=Color.red; - Debug.Log("collide enter"); - },CollisionManager.voidFunction,(obj) => + Debug.Log("collide enter "+obj.collider.uniqueID); + },(obj) => + { + //meshRenderer.material.color=Color.red; + Debug.Log(obj.collider.uniqueID); + },(obj) => { meshRenderer.material.color=Color.green; - Debug.Log("collide exit"); + Debug.Log("collide exit "); },CollisionGroup.Bullet); } } void Update() { + /*if (moveMode == MoveMode.Keyboard) + { + meshRenderer.material.color=Color.green; + }*/ + if (Input.GetKey(KeyCode.K)) { currentRotation+=rotationSpeed*Time.deltaTime*Mathf.Deg2Rad; diff --git a/Assets/JobsTesting.cs b/Assets/JobsTesting.cs index 4a6fbfa..7cc8950 100644 --- a/Assets/JobsTesting.cs +++ b/Assets/JobsTesting.cs @@ -44,7 +44,7 @@ private void Start() for (int i = 0; i < 500000; i++) { var o = new someObjects(); - o.center = math.UnitVector(360*((FP)UnityEngine.Random.value))*(FP)UnityEngine.Random.value*100; + o.center = Mathz.UnitVector(360*((FP)UnityEngine.Random.value))*(FP)UnityEngine.Random.value*100; objs.Add(o); } } diff --git a/Assets/math.cs b/Assets/Mathz.cs similarity index 99% rename from Assets/math.cs rename to Assets/Mathz.cs index c258be6..4c7d777 100644 --- a/Assets/math.cs +++ b/Assets/Mathz.cs @@ -214,7 +214,7 @@ public void Reset(Vector3? InitPosition=null) k = 0; } } -public static class math +public static class Mathz { public static readonly FP sqrt2 = FP.Sqrt(2); public static bool checkOut(TSVector2 border, TSVector pos, TSVector2 size) diff --git a/Assets/math.cs.meta b/Assets/Mathz.cs.meta similarity index 100% rename from Assets/math.cs.meta rename to Assets/Mathz.cs.meta diff --git a/Assets/RandomClones.cs b/Assets/RandomClones.cs new file mode 100644 index 0000000..1582522 --- /dev/null +++ b/Assets/RandomClones.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +public class RandomClones : MonoBehaviour +{ + private int times = 0; + public GameObject obj; + // Start is called once before the first execution of Update after the MonoBehaviour is created + void Start() + { + + } + + // Update is called once per frame + void Update() + { + if (times < 2000) + { + if (Random.value < 0.08f) + { + GameObject obj2 = Instantiate(obj, transform.position, Quaternion.identity); + obj2.transform.position = new Vector3(Random.Range(-15,15), Random.Range(-15,15), 0); + times++; + } + } + } +} diff --git a/Assets/RandomClones.cs.meta b/Assets/RandomClones.cs.meta new file mode 100644 index 0000000..d3e517c --- /dev/null +++ b/Assets/RandomClones.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 8f6a57f3b157f8f47bbcf035a9c05219 \ No newline at end of file diff --git a/Assets/Scenes/New Scene.unity b/Assets/Scenes/New Scene.unity index f159803..fcc146e 100644 --- a/Assets/Scenes/New Scene.unity +++ b/Assets/Scenes/New Scene.unity @@ -229,6 +229,51 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!1 &650477074 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 650477076} + - component: {fileID: 650477075} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!114 &650477075 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 650477074} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8f6a57f3b157f8f47bbcf035a9c05219, type: 3} + m_Name: + m_EditorClassIdentifier: + obj: {fileID: 1685858033} +--- !u!4 &650477076 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 650477074} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &842675857 GameObject: m_ObjectHideFlags: 0 @@ -349,9 +394,9 @@ MonoBehaviour: _serializedValue: 8589934592 ovalAxis: x: - _serializedValue: 8589934592 + _serializedValue: 15032385536 y: - _serializedValue: 4294967296 + _serializedValue: 8589934592 doubleCircleOffset: x: _serializedValue: 4294967296 @@ -691,7 +736,7 @@ Transform: m_GameObject: {fileID: 1633608431} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -6, y: 3, z: 0} + m_LocalPosition: {x: -4, y: 3, z: 0} m_LocalScale: {x: 1, y: 1, z: 4} m_ConstrainProportionsScale: 0 m_Children: [] @@ -960,3 +1005,4 @@ SceneRoots: - {fileID: 1641945851} - {fileID: 1633608435} - {fileID: 842675860} + - {fileID: 650477076} diff --git a/Packages/manifest.json b/Packages/manifest.json index 9444e62..e856177 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -3,7 +3,7 @@ "com.unity.ai.navigation": "2.0.6", "com.unity.collab-proxy": "2.7.1", "com.unity.feature.2d": "2.0.1", - "com.unity.ide.rider": "3.0.31", + "com.unity.ide.rider": "3.0.36", "com.unity.ide.visualstudio": "2.0.22", "com.unity.inputsystem": "1.14.0", "com.unity.multiplayer.center": "1.0.0", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index c834979..7ba4d1c 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -152,7 +152,7 @@ } }, "com.unity.ide.rider": { - "version": "3.0.31", + "version": "3.0.36", "depth": 0, "source": "registry", "dependencies": { From 32e48e61185095b9051de9f43f83c5fd4e835a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B3=A0=E6=BC=AA?= <32807696+AngelShadow2017@users.noreply.github.com> Date: Mon, 14 Apr 2025 16:51:21 +0800 Subject: [PATCH 8/9] Count --- Assets/ColliUpdate.cs | 2 +- Assets/ColliderObj.cs | 15 ++++++++------- Assets/ColliderTester.cs | 2 +- Assets/RandomClones.cs | 2 +- Assets/Scenes/New Scene.unity | 2 +- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Assets/ColliUpdate.cs b/Assets/ColliUpdate.cs index fe74f85..ca059f7 100644 --- a/Assets/ColliUpdate.cs +++ b/Assets/ColliUpdate.cs @@ -14,7 +14,7 @@ void Awake() private void Update() { - //CollisionManager.instance.ReloadJobCollisionChecker(); + CollisionManager.instance.ReloadJobCollisionChecker(); CollisionManager.instance.TraverseAllListener(); if ( CollisionManager.instance.converterManager.IsCreated) diff --git a/Assets/ColliderObj.cs b/Assets/ColliderObj.cs index 2e6d744..4e5287d 100644 --- a/Assets/ColliderObj.cs +++ b/Assets/ColliderObj.cs @@ -1265,7 +1265,7 @@ public void TraverseAllListener() { actionList.AddRange(listenerSet); } int actionListCount = actionList.Count; - var jobHandles = new NativeList(actionListCount, Allocator.Temp); + var jobHandles = new NativeArray(actionListCount, Allocator.Temp); var singleResults = new NativeArray>(actionListCount, Allocator.Temp); var multiResults = new NativeArray>(actionListCount, Allocator.Temp); var nativeColliders = nativeCollisionManager.colliders.AsReadOnly(); @@ -1306,7 +1306,7 @@ public void TraverseAllListener() { multiResults[i] = queueResult; - jobHandles.Add(waitHandle); + jobHandles[i] = (waitHandle); } else { @@ -1321,18 +1321,18 @@ public void TraverseAllListener() { vertexBuffer ); singleResults[i] = minResults; - jobHandles.Add(waitHandle); + jobHandles[i] = (waitHandle); } } } JobHandle.ScheduleBatchedJobs(); - JobHandle.CompleteAll(jobHandles.AsArray()); - jobHandles.Dispose(); - for (int i = 0; i < actionList.Count; i++) + + JobHandle.CompleteAll(jobHandles); + for (int i = 0; i < actionListCount; i++) { var action = actionList[i]; tmpDrawingHasCheckedObjectsInCurFrame.Add(action.collider); - + //jobHandles[i].Complete(); if (action.multiColli) { var tmpRes = multiResults[i]; @@ -1397,6 +1397,7 @@ public void TraverseAllListener() { // 清理原生内存 singleResults.Dispose(); multiResults.Dispose(); + jobHandles.Dispose(); ListPool<__action_checkColli__>.Release(actionList); } #endregion diff --git a/Assets/ColliderTester.cs b/Assets/ColliderTester.cs index 77a725b..74d154c 100644 --- a/Assets/ColliderTester.cs +++ b/Assets/ColliderTester.cs @@ -86,7 +86,7 @@ void CreateCollider() },(obj) => { //meshRenderer.material.color=Color.red; - Debug.Log(obj.collider.uniqueID); + //Debug.Log(obj.collider.uniqueID); },(obj) => { meshRenderer.material.color=Color.green; diff --git a/Assets/RandomClones.cs b/Assets/RandomClones.cs index 1582522..ded42ef 100644 --- a/Assets/RandomClones.cs +++ b/Assets/RandomClones.cs @@ -15,7 +15,7 @@ void Update() { if (times < 2000) { - if (Random.value < 0.08f) + if (Random.value < 0.1f) { GameObject obj2 = Instantiate(obj, transform.position, Quaternion.identity); obj2.transform.position = new Vector3(Random.Range(-15,15), Random.Range(-15,15), 0); diff --git a/Assets/Scenes/New Scene.unity b/Assets/Scenes/New Scene.unity index fcc146e..783abb2 100644 --- a/Assets/Scenes/New Scene.unity +++ b/Assets/Scenes/New Scene.unity @@ -245,7 +245,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!114 &650477075 MonoBehaviour: m_ObjectHideFlags: 0 From aa8d54d8f05c0ad6837366b389b0c54d6742876d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B3=A0=E6=BC=AA?= <32807696+AngelShadow2017@users.noreply.github.com> Date: Tue, 15 Apr 2025 16:37:15 +0800 Subject: [PATCH 9/9] fix bugs --- Assets/ColliUpdate.cs | 13 +- Assets/ColliderNativeJobs.cs | 99 +++++++----- Assets/ColliderObj.cs | 252 ++++++++++++++++++++--------- Assets/ColliderStructure.cs | 18 ++- Packages/manifest.json | 2 +- Packages/packages-lock.json | 2 +- ProjectSettings/ProjectVersion.txt | 4 +- 7 files changed, 269 insertions(+), 121 deletions(-) diff --git a/Assets/ColliUpdate.cs b/Assets/ColliUpdate.cs index ca059f7..3ccf793 100644 --- a/Assets/ColliUpdate.cs +++ b/Assets/ColliUpdate.cs @@ -12,21 +12,26 @@ void Awake() CollisionManager.instance = new CollisionManager(); } - private void Update() + private void Update2() { CollisionManager.instance.ReloadJobCollisionChecker(); CollisionManager.instance.TraverseAllListener(); - if ( + /*if ( CollisionManager.instance.converterManager.IsCreated) { CollisionManager.instance.converterManager.Dispose(); - } + }*/ + } + private void Update() + { + Update2(); + Update2(); } private void LateUpdate() { - CollisionManager.instance.nativeCollisionManager.CompactVertexBuffers(); + //CollisionManager.instance.nativeCollisionManager.CompactVertexBuffers(); } private void OnPostRender() diff --git a/Assets/ColliderNativeJobs.cs b/Assets/ColliderNativeJobs.cs index 4531c43..be382b7 100644 --- a/Assets/ColliderNativeJobs.cs +++ b/Assets/ColliderNativeJobs.cs @@ -7,6 +7,7 @@ using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using Unity.Jobs; +using Unity.Mathematics; using UnityEngine; using ZeroAs.DOTS.Colliders; @@ -33,7 +34,7 @@ public bool IsCreated get { #if UNITY_EDITOR - if (_destroyFlag.IsCreated!=convertIsCreateBool) + if (convertIsCreateBool&&_destroyFlag.IsCreated!=convertIsCreateBool) { throw new InvalidOperationException("忘记释放CollisionGroupHashSetToArrayManager内存"); } @@ -126,15 +127,27 @@ out ColliGroupJobData data // 清理方法 public void Dispose() { + if (_isCreated == 0) + { + return; + } _isCreated = 0; _collisionGroupInfos.Dispose(); - _allHandles.Dispose(); - for (int i = 0; i < _collisionGroupObjs.Length; i++) + if (_collisionGroupObjs.IsCreated) { - _collisionGroupObjs[i].checkGroupArray.Dispose(); + JobHandle.CompleteAll(_allHandles.AsArray()); + for (int i = 0; i < _collisionGroupObjs.Length; i++) + { + _collisionGroupObjs[i].checkGroupArray.Dispose(); + } + _collisionGroupObjs.Dispose(); } - _collisionGroupObjs.Dispose(); - if(_destroyFlag.IsCreated) _destroyFlag.Dispose(); + _allHandles.Dispose(); + //!!!Temp类型的分配不需要手动销毁 + /*if (_destroyFlag.IsCreated) + { + _destroyFlag.Dispose(); + }*/ //hashset是在外面控制的 } } @@ -157,7 +170,7 @@ public struct CollisionChecker /// [BurstCompile(OptimizeFor = OptimizeFor.Performance)] public static void FindMinCollidingId( - out NativeArray minResults_ret, + out NativeReference minResult_ret, out JobHandle waitHandle, ref CollisionGroupHashSetToArrayManager toArrayManager, @@ -176,10 +189,10 @@ public static void FindMinCollidingId( batchCount = (elementCount+batchSize-1) / batchSize; var minResults = new NativeArray( batchCount, - allocator, + Allocator.TempJob, NativeArrayOptions.UninitializedMemory); - var handles = new NativeList(batchCount, allocator); + var handles = new NativeList(batchCount, Allocator.Temp); // 分块调度作业 for (int i = 0; i < batchCount; i++) @@ -201,9 +214,10 @@ public static void FindMinCollidingId( handles.Add(checkJob.Schedule(toArrayManager._collisionGroupInfos[groupIndex].handle)); } - - minResults_ret = minResults; - waitHandle = JobHandle.CombineDependencies(handles.AsArray()); + var combine = new CombineMinJob(); + combine.ele = minResults; + minResult_ret = combine.min = new NativeReference(allocator); + waitHandle=combine.Schedule(JobHandle.CombineDependencies(handles.AsArray())); handles.Dispose(); } /// @@ -211,7 +225,7 @@ public static void FindMinCollidingId( /// /// /// - [BurstCompile(OptimizeFor = OptimizeFor.Performance)] + /*[BurstCompile(OptimizeFor = OptimizeFor.Performance)] public static int PostProcessMinResults(ref NativeArray minResults) { // 第三步:收集最终结果 @@ -225,7 +239,7 @@ public static int PostProcessMinResults(ref NativeArray minResults) } minResults.Dispose(); return finalResult; - } + }*/ #endregion [BurstCompile(OptimizeFor = OptimizeFor.Performance)] static int nextPow2(int n) @@ -242,7 +256,7 @@ static int nextPow2(int n) #region 一对多,并且返回排完序后的数组 [BurstCompile(OptimizeFor = OptimizeFor.Performance)] public static void FindAllCollidingIds( - out NativeQueue resultsQueue, + out NativeList resultArray, out JobHandle waitHandle, ref CollisionGroupHashSetToArrayManager toArrayManager, in int groupIndex, @@ -255,7 +269,7 @@ public static void FindAllCollidingIds( var groupData = toArrayManager.EnsureJobData(groupIndex); // 创建结果队列 - resultsQueue = new NativeQueue(allocator); + var resultsQueue = new NativeQueue(Allocator.TempJob); // 准备Job参数 var job = new SingleToManyCollisionJob @@ -268,36 +282,49 @@ public static void FindAllCollidingIds( }; int totalLen = toArrayManager._collisionGroupObjs[groupIndex].checkGroup.Count; // 调度并行任务 - waitHandle = job.ScheduleParallel( + var dep = job.ScheduleParallel( totalLen, batchSingleCount,//nextPow2(totalLen/32+1), groupData.handle); + var sortJob = new ConvertQueueToArrayThenSort(); + sortJob.ele = resultsQueue; + resultArray= sortJob.res = new NativeList(allocator); + var sortJobHandle = sortJob.Schedule(dep); + waitHandle = sortJobHandle; + //等待waitHandle完成后销毁 + resultsQueue.Dispose(waitHandle); } + - [BurstCompile(OptimizeFor = OptimizeFor.Performance)] - public static void PostProcessAllResults( - out NativeArray resArray, - ref NativeQueue resultsQueue, - Allocator allocator = Allocator.Temp, - bool sort = true) + #endregion + } + [BurstCompile(OptimizeFor = OptimizeFor.Performance)] + struct ConvertQueueToArrayThenSort : IJob + { + [ReadOnly] public NativeQueue ele; + public NativeList res; + public void Execute() { - // 转换队列为数组 - NativeArray resultArray = resultsQueue.ToArray(allocator); - resultsQueue.Dispose(); - - // 排序(可选) - if (sort && resultArray.Length > 1) + res.AddRange(ele.ToArray(Allocator.Temp)); + res.Sort(); + } + } + [BurstCompile(OptimizeFor = OptimizeFor.Performance)] + struct CombineMinJob : IJob + { + [DeallocateOnJobCompletion, ReadOnly] public NativeArray ele; + [WriteOnly]public NativeReference min; + public void Execute() + { + var res = int.MaxValue; + int len = ele.Length; + for (int i = 0; i < len; i++) { - resultArray.Sort(); + res = math.min(res, ele[i]); } - - resArray = resultArray; + min.Value = res; } - - - #endregion } - [BurstCompile] public struct ConvertCheckGroupToArrayJob : IJob { diff --git a/Assets/ColliderObj.cs b/Assets/ColliderObj.cs index 4e5287d..59f0488 100644 --- a/Assets/ColliderObj.cs +++ b/Assets/ColliderObj.cs @@ -38,7 +38,27 @@ public interface IMasteredCollider [Serializable] public abstract class ColliderBase : ICollideShape { - +#if UNITY_EDITOR + protected bool _dirty = false; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetDirty(bool dir) + { + _dirty = dir; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CheckDirty() + { + if (_dirty) + { + throw new MemberAccessException("碰撞体为脏,不能访问,请保存当前状态。"); + } + } +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetDirty(bool dir){} + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CheckDirty(){} +#endif public int UniqueID { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -46,7 +66,7 @@ public int UniqueID } public bool Registered { get; set; } = false; - public ColliderStructure collider; + internal ColliderStructure collider; public ref ColliderStructure Collider => ref collider; //protected CollisionGroup __colli__ = CollisionGroup.Default; @@ -72,8 +92,8 @@ public bool enabled get => collider.enabled!=0; set { + SetDirty(true); collider.enabled = value ? (byte)1 : (byte)0; - SaveState(); } } @@ -216,6 +236,7 @@ protected void CheckEssentialValues() /// public virtual void SaveState() { + SetDirty(false); CheckEssentialValues(); CollisionManager.instance.nativeCollisionManager.SyncCollider(ref collider); } @@ -247,10 +268,18 @@ public CircleCollider(FP R,TSVector2 center,CollisionGroup group = CollisionGrou collider.radius = R; collider.center = center; collider.collisionGroup = group; + SetDirty(true); } - public override void SetRotation(FP rotRad) { }//没错,圆形没有旋转 - public override void SetCenter(in TSVector2 center) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetRadius(in FP r) { + collider.radius = r; + SetDirty(true); + } + public sealed override void SetRotation(FP rotRad) { }//没错,圆形没有旋转 + public sealed override void SetCenter(in TSVector2 center) + { + SetDirty(true); Collider.center = center; } public override TSVector2 GetCenter() @@ -336,6 +365,7 @@ public OvalCollider(TSVector2 axis, TSVector2 center,in FP rotation, CollisionGr collider.center = center; SetAxis(axis); collider.collisionGroup = group; + SetDirty(true); } public void SetAxis(TSVector2 axis) { collider.Axis = axis; @@ -348,13 +378,16 @@ public void SetAxis(TSVector2 axis) { { collider.b2Dividea2 = collider.SqrAxis.y / collider.SqrAxis.x; } + SetDirty(true); } public override void SetRotation(FP rotRad) { collider.rot = rotRad; + SetDirty(true); }//没错,圆形没有旋转 public override void SetCenter(in TSVector2 center) { collider.center = center; + SetDirty(true); } public override TSVector2 GetCenter() { @@ -465,12 +498,13 @@ public PolygonCollider(TSVector2[] vertex, TSVector2 center, FP rotation, Collis collider.collisionGroup = group; collider.vertexCount = vertex.Length; movedVertexs = new NativeArray(vertex.Length,Allocator.Persistent,NativeArrayOptions.UninitializedMemory); //边数是不能变的 - RotateVertexs(false); + RotateVertexs(); + SetDirty(true); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public sealed override ColliderStructure GetRealCollider() { - return CollisionManager.instance.nativeCollisionManager.colliders[collider.uniqueID]; + return CollisionManager.instance.nativeCollisionManager.GetColliderStructureSafe(this); } public sealed override void SaveState() @@ -481,6 +515,7 @@ public sealed override void SaveState() public override void SetRotation(FP rotRad) { + SetDirty(true); collider.rot = rotRad; RotateVertexs(); }//没错,圆形没有旋转 @@ -488,12 +523,13 @@ public override void SetCenter(in TSVector2 center) { MoveDeltaPos(center-collider.center); collider.center = center; + SetDirty(true); } public override TSVector2 GetCenter() { return collider.center; } - protected void RotateVertexs(bool saveState=true) + protected void RotateVertexs() { TSVector4 tSVector4 = new TSVector4(FP.MaxValue, FP.MinValue, FP.MinValue, FP.MaxValue); for (int i = movedVertexs.Length - 1; i >= 0; --i) @@ -517,10 +553,7 @@ protected void RotateVertexs(bool saveState=true) } } _boundingBox_ = tSVector4; - if (saveState) - { - SaveState(); - } + SetDirty(true); } void MoveDeltaPos(TSVector2 pos) { @@ -529,11 +562,11 @@ void MoveDeltaPos(TSVector2 pos) movedVertexs[i] += pos; } //标注顶点缓冲区的移动 - SaveState(); _boundingBox_.x += pos.x; _boundingBox_.y += pos.y; _boundingBox_.z += pos.x; _boundingBox_.w += pos.y; + SetDirty(true); } /*public override TSVector2 GetFurthestPoint(in TSVector2 _direction) { @@ -584,7 +617,8 @@ public BoxCollider(TSVector2 widthHeight,TSVector2 center,FP rotation, Collision collider.center = center; collider.vertexCount = vertexs.Length; collider.collisionGroup = group; - RotateVertexs(false); + RotateVertexs(); + SetDirty(true); } public override void DebugDisplayColliderShape(Color color) { @@ -631,7 +665,8 @@ public DiamondCollider(TSVector2 widthHeight, TSVector2 center, FP rotation, Col collider.center = center; collider.vertexCount = vertexs.Length; collider.collisionGroup = group; - RotateVertexs(false); + RotateVertexs(); + SetDirty(true); } } @@ -646,32 +681,54 @@ public DoubleCircleCollider(FP R, TSVector2 center1,TSVector2 center2, Collision collider.radius = R; collider.collisionGroup = group; SetCircleCenters(center1,center2); + SetDirty(true); + } + + public void SetRadius(in FP r) + { + collider.radius = r; + SetDirty(true); } public override void SetRotation(FP rotRad) { }//没错,圆形没有旋转 - public override void SetCenter(in TSVector2 center) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public sealed override void SetCenter(in TSVector2 center) { TSVector2 delta = center - collider.center; collider.circleCenter1 += delta; collider.circleCenter2 += delta; collider.center = center; + SetDirty(true); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetCircleCenters(in TSVector2 center1,in TSVector2 center2) { collider.circleCenter1 = center1; collider.circleCenter2 = center2; collider.center = (center1 + center2) * 0.5; + SetDirty(true); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetCircleCenter2(in TSVector2 center2) { collider.circleCenter2 = center2; collider.center = (collider.circleCenter1 + center2) * 0.5; + SetDirty(true); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetCircleCenter1(in TSVector2 center1) { collider.circleCenter1 = center1; collider.center = (collider.circleCenter2 + center1) * 0.5; + SetDirty(true); } - public override TSVector2 GetCenter() + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TSVector2 GetCircleCenter1(){return collider.circleCenter1;} + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TSVector2 GetCircleCenter2() { return collider.circleCenter2; } + + public TSVector2 centerCircle1 => collider.circleCenter1; + public TSVector2 centerCircle2 => collider.circleCenter2; + public sealed override TSVector2 GetCenter() { return collider.center; } @@ -1135,7 +1192,6 @@ public CollisionManager AddShape(ColliderBase collider) { nativeCollisionManager.RegisterCollider(ref collider.collider); } collider.Registered = true; - collider.SaveState(); return this; } public void RemoveShape(ColliderBase collider) { @@ -1215,7 +1271,14 @@ public void CheckCollision(ColliderBase obj, CollisionGroup group, ref List(actionListCount, Allocator.Temp); - var singleResults = new NativeArray>(actionListCount, Allocator.Temp); - var multiResults = new NativeArray>(actionListCount, Allocator.Temp); + var alreadySavedGroup = new NativeArray(groupCnt,Allocator.Temp); + var jobHandles = new NativeList(actionListCount, Allocator.TempJob); + var singleResults = new NativeList< + GroupedResultReceiver< + NativeReference + > + >(actionListCount, Allocator.TempJob);//每帧?差不多会有n个或者以上 + var multiResults = new NativeList< + GroupedResultReceiver< + NativeList + > + >(actionListCount, Allocator.TempJob); var nativeColliders = nativeCollisionManager.colliders.AsReadOnly(); var vertexBuffer = nativeCollisionManager.vertices.AsReadOnly(); + //这里不能一边创建job一遍同步,不然会出现问题 + for (int i = 0 ;i>() + { + ActionTarget = i, + Container = queueResult + }); - jobHandles[i] = (waitHandle); + jobHandles.Add(waitHandle); } else { // 单碰撞检测 CollisionChecker.FindMinCollidingId( - out var minResults, + out var minResult, out var waitHandle, ref converterManager, groupIndex, @@ -1320,85 +1423,84 @@ public void TraverseAllListener() { nativeColliders, vertexBuffer ); - singleResults[i] = minResults; - jobHandles[i] = (waitHandle); + singleResults.Add(new GroupedResultReceiver>() + { + ActionTarget = i, + Container = minResult + }); + jobHandles.Add(waitHandle); } } } + alreadySavedGroup.Dispose(); JobHandle.ScheduleBatchedJobs(); - JobHandle.CompleteAll(jobHandles); - for (int i = 0; i < actionListCount; i++) + JobHandle.CompleteAll(jobHandles.AsArray()); + //处理单碰撞 { - var action = actionList[i]; - tmpDrawingHasCheckedObjectsInCurFrame.Add(action.collider); - //jobHandles[i].Complete(); - if (action.multiColli) + int sigLength = singleResults.Length; + for (int i = 0; i < sigLength; i++) { - var tmpRes = multiResults[i]; - // 处理多碰撞结果 - if (tmpRes.Count>0) + var targetAction = singleResults[i].ActionTarget; + var singleResult = singleResults[i].Container; + if (singleResult.IsCreated) { - //这里是排完序的,不用在意它不统一 - CollisionChecker.PostProcessAllResults( - out var res, - ref tmpRes); - foreach (var colliderId in res) + int result = singleResult.Value; + // 处理单碰撞 + if (result != int.MaxValue) { - if (colliders.TryGetValue(colliderId, out var collided)) + //如果是最大就代表没有碰上任何物体 + if (colliders.TryGetValue(result, out var collided)) { - callActionComponent(collided, action); + var act = actionList[targetAction]; + callActionComponent(collided, act); // 处理接收器回调 - //多碰撞无接收器 - /*if (receivers.TryGetValue(collided, out var receiverGroups) && - receiverGroups.TryGetValue(action.collider.colliGroup, out var receiverAction)) + if (receivers.TryGetValue(collided, out var receiverGroups) && + receiverGroups.TryGetValue(act.collider.colliGroup, out var receiverAction)) { - callActionComponent(action.collider, receiverAction); - }*/ + callActionComponent(act.collider, receiverAction); + } } } + else + { + callActionComponent(null, actionList[targetAction]); + } } - - /*if (multiResults[i].IsCreated) - { - multiResults[i].Dispose(); - }*/ + singleResults[i].Dispose(); } - else + } + //处理多碰撞 + { + int sigLength = multiResults.Length; + for (int i = 0; i < sigLength; i++) { - var tmpRes = singleResults[i]; - int result = CollisionChecker.PostProcessMinResults(ref tmpRes); - // 处理单碰撞 - if(result!=int.MaxValue){//如果是最大就代表没有碰上任何物体 - if (colliders.TryGetValue(result, out var collided)) + var targetAction = multiResults[i].ActionTarget; + var arr = multiResults[i].Container; + if (arr.IsCreated) + { + foreach (var colliderId in arr) { - callActionComponent(collided, action); - // 处理接收器回调 - if (receivers.TryGetValue(collided, out var receiverGroups) && - receiverGroups.TryGetValue(action.collider.colliGroup, out var receiverAction)) + if (colliders.TryGetValue(colliderId, out var collided)) { - callActionComponent(action.collider, receiverAction); + callActionComponent(collided, actionList[targetAction]); + //多碰撞无接收器 } } } - else - { - callActionComponent(null, action); - } - - /*if (singleResults[i].IsCreated) - { - singleResults[i].Dispose(); - }*/ + multiResults[i].Dispose(); } } - // 清理原生内存 singleResults.Dispose(); multiResults.Dispose(); jobHandles.Dispose(); ListPool<__action_checkColli__>.Release(actionList); + if (converterManager.IsCreated) + { + converterManager.Dispose(); + } } #endregion diff --git a/Assets/ColliderStructure.cs b/Assets/ColliderStructure.cs index 32fe087..c77bdbb 100644 --- a/Assets/ColliderStructure.cs +++ b/Assets/ColliderStructure.cs @@ -8,6 +8,7 @@ using Unity.Burst; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; +using UnityEngine; using UnityEngine.UIElements; namespace ZeroAs.DOTS.Colliders @@ -470,6 +471,13 @@ public static NativeArray.ReadOnly instancedBuffer public NativeArray> groupedColliders; public NativeList vertices = new NativeList(Allocator.Persistent); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ColliderStructure GetColliderStructureSafe(in ColliderBase collider) + { + collider.CheckDirty(); + colliders.TryGetValue(collider.collider.uniqueID,out var res); + return res; + } void InitGroupedStructs() { groupedColliders = new NativeArray>(CollisionManager.groupCnt,Allocator.Persistent); @@ -918,8 +926,14 @@ public void Dispose() } } [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)] - public struct CollisionManagerBurst + public struct GroupedResultReceiver:IDisposable where T:unmanaged,IDisposable { - + public T Container; + public int ActionTarget; + [BurstCompile(DisableDirectCall = true, OptimizeFor = OptimizeFor.Performance)] + public void Dispose() + { + Container.Dispose(); + } } } \ No newline at end of file diff --git a/Packages/manifest.json b/Packages/manifest.json index e856177..6ca1371 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -4,7 +4,7 @@ "com.unity.collab-proxy": "2.7.1", "com.unity.feature.2d": "2.0.1", "com.unity.ide.rider": "3.0.36", - "com.unity.ide.visualstudio": "2.0.22", + "com.unity.ide.visualstudio": "2.0.23", "com.unity.inputsystem": "1.14.0", "com.unity.multiplayer.center": "1.0.0", "com.unity.test-framework": "1.5.1", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 7ba4d1c..de36767 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -161,7 +161,7 @@ "url": "https://packages.unity.com" }, "com.unity.ide.visualstudio": { - "version": "2.0.22", + "version": "2.0.23", "depth": 0, "source": "registry", "dependencies": { diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index 2795afa..8678d93 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 6000.0.45f1 -m_EditorVersionWithRevision: 6000.0.45f1 (d91bd3d4e081) +m_EditorVersion: 6000.0.46f1 +m_EditorVersionWithRevision: 6000.0.46f1 (fb93bc360d3a)