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/ColliUpdate.cs b/Assets/ColliUpdate.cs
new file mode 100644
index 0000000..3ccf793
--- /dev/null
+++ b/Assets/ColliUpdate.cs
@@ -0,0 +1,47 @@
+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 Update2()
+ {
+ CollisionManager.instance.ReloadJobCollisionChecker();
+ CollisionManager.instance.TraverseAllListener();
+ /*if (
+ CollisionManager.instance.converterManager.IsCreated)
+ {
+
+ CollisionManager.instance.converterManager.Dispose();
+ }*/
+ }
+ private void Update()
+ {
+ Update2();
+ Update2();
+ }
+
+ private void LateUpdate()
+ {
+ //CollisionManager.instance.nativeCollisionManager.CompactVertexBuffers();
+ }
+
+ 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/ColliderNativeJobs.cs b/Assets/ColliderNativeJobs.cs
new file mode 100644
index 0000000..be382b7
--- /dev/null
+++ b/Assets/ColliderNativeJobs.cs
@@ -0,0 +1,407 @@
+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 Unity.Mathematics;
+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 (convertIsCreateBool&&_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()
+ {
+ if (_isCreated == 0)
+ {
+ return;
+ }
+ _isCreated = 0;
+ _collisionGroupInfos.Dispose();
+ if (_collisionGroupObjs.IsCreated)
+ {
+ JobHandle.CompleteAll(_allHandles.AsArray());
+ for (int i = 0; i < _collisionGroupObjs.Length; i++)
+ {
+ _collisionGroupObjs[i].checkGroupArray.Dispose();
+ }
+ _collisionGroupObjs.Dispose();
+ }
+ _allHandles.Dispose();
+ //!!!Temp类型的分配不需要手动销毁
+ /*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 NativeReference minResult_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.TempJob,
+ NativeArrayOptions.UninitializedMemory);
+
+ var handles = new NativeList(batchCount, Allocator.Temp);
+
+ // 分块调度作业
+ 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));
+ }
+ var combine = new CombineMinJob();
+ combine.ele = minResults;
+ minResult_ret = combine.min = new NativeReference(allocator);
+ waitHandle=combine.Schedule(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 NativeList resultArray,
+ 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);
+
+ // 创建结果队列
+ var resultsQueue = new NativeQueue(Allocator.TempJob);
+
+ // 准备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;
+ // 调度并行任务
+ 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);
+ }
+
+
+ #endregion
+ }
+ [BurstCompile(OptimizeFor = OptimizeFor.Performance)]
+ struct ConvertQueueToArrayThenSort : IJob
+ {
+ [ReadOnly] public NativeQueue ele;
+ public NativeList res;
+ public void Execute()
+ {
+ 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++)
+ {
+ res = math.min(res, ele[i]);
+ }
+ min.Value = res;
+ }
+ }
+ [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/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/ColliderObj.cs b/Assets/ColliderObj.cs
new file mode 100644
index 0000000..59f0488
--- /dev/null
+++ b/Assets/ColliderObj.cs
@@ -0,0 +1,1640 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+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
+{
+ public interface ICollideShape {
+ public bool Registered { get; set; }
+ 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 CollisionGroup colliGroup { get; set; }
+ public bool enabled { get; set; }
+ public void DebugDisplayColliderShape(Color color);
+
+ public void Destroy()
+ {
+ }
+ }
+ public interface IMasteredCollider
+ {
+ public T Master { get; set; }
+ }
+ [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)]
+ get => collider.uniqueID;
+ }
+
+ public bool Registered { get; set; } = false;
+ internal ColliderStructure collider;
+
+ public ref ColliderStructure Collider => ref collider;
+ //protected CollisionGroup __colli__ = CollisionGroup.Default;
+ public int tag = -1;//用来识别特定的tag
+ public CollisionGroup colliGroup
+ {
+ get => collider.collisionGroup;
+ set
+ {
+ #if UNITY_EDITOR
+ if (Registered)
+ {
+ throw new InvalidOperationException("不支持在注册给了管理器之后再改变Group");
+ }
+ #endif
+ collider.collisionGroup = value;
+ }
+ //记得sync
+ }
+
+ public bool enabled
+ {
+ get => collider.enabled!=0;
+ set
+ {
+ SetDirty(true);
+ collider.enabled = value ? (byte)1 : (byte)0;
+ }
+ }
+
+ 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)
+ {
+ CheckEssentialValues();
+ GetFurthestPointExtensions.GetFurthestPoint(out var result, collider, direction,ColliderNativeHelper.instancedBuffer);
+ 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 = 10;//最大迭代次数
+ //#第三步:找到第一个支撑点后,以第一个支撑点为起点指向原点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 bool CheckCollide(ColliderBase shape2) {
+ return CheckCollide(this, shape2);
+ }*/
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ 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()
+ {
+ SetDirty(false);
+ CheckEssentialValues();
+ CollisionManager.instance.nativeCollisionManager.SyncCollider(ref collider);
+ }
+
+ public bool CheckCollide(ColliderBase shape2)
+ {
+ CheckEssentialValues();
+ return CollideExtensions.CheckCollide(this.GetRealCollider(), shape2.GetRealCollider(),ColliderNativeHelper.instancedBuffer);
+ }
+
+ public virtual void DebugDisplayColliderShape(Color color) { }
+
+ public virtual void Destroy()
+ {
+ }
+ }
+ [Serializable]
+ public abstract class ColliderBase : ColliderBase
+ {
+ public T Master;
+ }
+ [Serializable]
+ public class CircleCollider : ColliderBase
+ {
+ public CircleCollider(FP R,TSVector2 center,CollisionGroup group = CollisionGroup.Default)
+ {
+ collider = ColliderStructure.CreateInstance();
+ collider.colliderType = ColliderType.Circle;
+ collider.radius = R;
+ collider.center = center;
+ collider.collisionGroup = group;
+ SetDirty(true);
+ }
+ [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()
+ {
+ 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)*10);
+ 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, CollisionGroup group = 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, CollisionGroup group = CollisionGroup.Default)
+ {
+ collider = ColliderStructure.CreateInstance();
+ collider.colliderType = ColliderType.Oval;
+ collider.rot = rotation;
+ collider.center = center;
+ SetAxis(axis);
+ collider.collisionGroup = group;
+ SetDirty(true);
+ }
+ 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;
+ }
+ 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()
+ {
+ 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, CollisionGroup group = CollisionGroup.Default) : base(axis, center,rotation, group)
+ {
+ this._master_ = master;
+ }
+
+ }
+ [Serializable]
+ public class PolygonCollider : ColliderBase,IDisposable
+ {
+ 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, 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); //边数是不能变的
+ RotateVertexs();
+ SetDirty(true);
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public sealed override ColliderStructure GetRealCollider()
+ {
+ return CollisionManager.instance.nativeCollisionManager.GetColliderStructureSafe(this);
+ }
+
+ public sealed override void SaveState()
+ {
+ base.SaveState();
+ CollisionManager.instance.nativeCollisionManager.ModifyCollider(collider,movedVertexs);
+ }
+
+ public override void SetRotation(FP rotRad)
+ {
+ SetDirty(true);
+ collider.rot = rotRad;
+ RotateVertexs();
+ }//没错,圆形没有旋转
+ 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()
+ {
+ 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(collider.rot) + collider.center;
+ 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;
+ SetDirty(true);
+ }
+ 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;
+ SetDirty(true);
+ }
+ /*public override TSVector2 GetFurthestPoint(in TSVector2 _direction)
+ {
+ 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)
+ {
+ if((len= TSVector2.Dot(direction, movedVertexs[i])) > maxLen)
+ {
+ maxLen = len;
+ pos = movedVertexs[i];
+ }
+ }
+ if (result != pos)
+ {
+ var arr = ColliderNativeHelper.instancedBuffer.ToArray();
+ StringBuilder sb = new StringBuilder();
+ sb.AppendJoin(", ", arr);
+ Debug.Log(result+" "+pos+" "+sb);
+ }
+ return pos;
+ }*/
+ public override void Destroy()
+ {
+ if(movedVertexs.IsCreated)
+ movedVertexs.Dispose();
+ }
+
+ public override TSVector4 GetBoundingBox()
+ {
+ return _boundingBox_;
+ }
+ }
+ [Serializable]
+ public class BoxCollider : PolygonCollider
+ {
+ 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);
+ vertexs = new TSVector2[4] {-a,-b, a, b}; //边数是不能变的
+ movedVertexs = new NativeArray(4,Allocator.Persistent,NativeArrayOptions.UninitializedMemory); //边数是不能变的
+ collider = ColliderStructure.CreateInstance();
+ collider.colliderType = ColliderType.Polygon;
+ collider.rot = rotation;
+ collider.center = center;
+ collider.vertexCount = vertexs.Length;
+ collider.collisionGroup = group;
+ RotateVertexs();
+ SetDirty(true);
+ }
+ 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, CollisionGroup group = CollisionGroup.Default) : base(widthHeight, center, rotation, group)
+ {
+ this._master_ = master;
+ }
+
+ }
+ [Serializable]
+ public class DiamondCollider : PolygonCollider
+ {
+ 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);
+ vertexs = new TSVector2[4] { -b, c, b, -c }; //边数是不能变的
+ movedVertexs = new NativeArray(4,Allocator.Persistent,NativeArrayOptions.UninitializedMemory); //边数是不能变的
+ collider = ColliderStructure.CreateInstance();
+ collider.colliderType = ColliderType.Polygon;
+ collider.rot = rotation;
+ collider.center = center;
+ collider.vertexCount = vertexs.Length;
+ collider.collisionGroup = group;
+ RotateVertexs();
+ SetDirty(true);
+ }
+
+ }
+ [Serializable]
+//两个相同的圆中间连线
+ public class DoubleCircleCollider : ColliderBase
+ {
+ 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);
+ SetDirty(true);
+ }
+
+ public void SetRadius(in FP r)
+ {
+ collider.radius = r;
+ SetDirty(true);
+ }
+ public override void SetRotation(FP rotRad) { }//没错,圆形没有旋转
+ [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);
+ }
+ [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;
+ }
+ /*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 (collider.circleCenter1.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 bool CircleCollideWithCircle(CircleCollider shape2)
+ {
+ return CollideExtensions.CircleCollideWithDoubleCircle(this.collider, shape2.collider);
+ }
+
+ /*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(50, 80, ((float)collider.radius) / 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 = collider.circleCenter1.ToVector();
+ Vector3 cent2 = new Vector3(Mathf.Cos(angle) * (float)collider.radius, Mathf.Sin(angle) * (float)collider.radius, 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 = collider.circleCenter2.ToVector();
+ Vector3 cent2 = new Vector3(Mathf.Cos(angle) * (float)collider.radius, Mathf.Sin(angle) * (float)collider.radius, 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, CollisionGroup group = 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 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 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 CollisionGroup[] groups) {
+ return AddListener(null,collide,null,groups);
+ }
+ public CollisionController AddListener(Action collide, bool multiColli=false, params 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 CollisionManager:IDisposable {
+ public static void voidFunction(ColliderBase c) { }
+ private static CollisionManager _instance;
+
+ public static CollisionManager instance
+ {
+ get => _instance;
+ set
+ {
+ if (_instance != null&&_instance!=value)
+ {
+ _instance.Dispose();
+ }
+ _instance = value;
+ }
+ }
+
+ public void Dispose()
+ {
+ foreach (var colliderBase in colliders.Values)
+ {
+ if (colliderBase is IDisposable c)
+ {
+ c.Dispose();
+ }
+ }
+ nativeCollisionManager.Dispose();
+ if (converterManager.IsCreated)
+ {
+ converterManager.Dispose();
+ }
+ }
+ public static readonly int groupCnt = Enum.GetValues(typeof(CollisionGroup)).Length;
+ public LinkedHashSet[] groupedColliders;//这个到时候要改成LinkedHashSet之类的东西。。。
+ 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;//测试
+ public ColliderNativeHelper nativeCollisionManager = new ColliderNativeHelper();
+ 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;
+ }
+
+ //方便过后删除掉
+ //添加碰撞监听器
+ //有多碰撞需求再改吧……反正就改个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.UniqueID,collider);
+ if (collider.collider.colliderType == ColliderType.Polygon)
+ {
+ nativeCollisionManager.RegisterCollider(ref collider.collider,collider.collider.vertexCount);
+ }
+ else
+ {
+ nativeCollisionManager.RegisterCollider(ref collider.collider);
+ }
+ collider.Registered = true;
+ return this;
+ }
+ public void RemoveShape(ColliderBase collider) {
+ /*if (multiCollisionOptimize)
+ {
+ quadTreeOptmize.RemoveCollider(collider);
+ }
+ else*/
+ {
+ int grp = (int)collider.colliGroup;
+ groupedColliders[grp].Remove(collider);
+ }
+ if (!nativeCollisionManager.Disposed)
+ {
+ nativeCollisionManager.DeleteCollider(collider.collider);
+ }
+ colliders.Remove(collider.UniqueID);
+ //调用销毁清理函数
+ collider.Destroy();
+ collider.Registered = false;
+ }
+ public void SetCenter(in TSVector2 Pos,ColliderBase shape)
+ {
+ shape.SetCenter(Pos);
+
+ }
+
+
+ private bool readyToBatchCheckCollision => converterManager.Available;
+
+ public void ReloadJobCollisionChecker()
+ {
+ if (converterManager.IsCreated)
+ {
+ converterManager.Dispose();
+ }
+ converterManager = new CollisionGroupHashSetToArrayManager(nativeCollisionManager.groupedColliders.AsReadOnly());
+ }
+
+ 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);
+ }
+ }
+ }
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ void SaveAllStateInOneColliGroup(int group)
+ {
+ foreach (var i in groupedColliders[group])
+ {
+ i.SaveState();
+ }
+ }
+ public void TraverseAllListener() {
+ {
+ tmpDrawingHasCheckedObjectsInCurFrame.Clear();
+ }
+
+ #region 不适用多线程
+ if (!readyToBatchCheckCollision)
+ {
+ var alreadySavedGroups = new bool[groupCnt];
+ foreach(var kvPair in listeners)
+ {
+ var val = kvPair.Value;
+ foreach (var obj in val)
+ {
+ if (!obj.collider.enabled) { continue; }//如果自身不允许碰撞就不碰
+ obj.collider.SaveState();
+ foreach (var i in obj.checkGroups)
+ {
+ if (alreadySavedGroups[(int)i])
+ {
+ alreadySavedGroups[(int)i] = true;
+ SaveAllStateInOneColliGroup((int)i);
+ }
+ //多碰撞不支持接收器
+ 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 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.Add(waitHandle);
+ }
+ else
+ {
+ // 单碰撞检测
+ CollisionChecker.FindMinCollidingId(
+ out var minResult,
+ out var waitHandle,
+ ref converterManager,
+ groupIndex,
+ targetCollider,
+ nativeColliders,
+ vertexBuffer
+ );
+ singleResults.Add(new GroupedResultReceiver>()
+ {
+ ActionTarget = i,
+ Container = minResult
+ });
+ jobHandles.Add(waitHandle);
+ }
+ }
+ }
+ alreadySavedGroup.Dispose();
+ JobHandle.ScheduleBatchedJobs();
+
+ JobHandle.CompleteAll(jobHandles.AsArray());
+ //处理单碰撞
+ {
+ int sigLength = singleResults.Length;
+ for (int i = 0; i < sigLength; i++)
+ {
+ var targetAction = singleResults[i].ActionTarget;
+ var singleResult = singleResults[i].Container;
+ if (singleResult.IsCreated)
+ {
+ int result = singleResult.Value;
+ // 处理单碰撞
+ if (result != int.MaxValue)
+ {
+ //如果是最大就代表没有碰上任何物体
+ if (colliders.TryGetValue(result, out var collided))
+ {
+ var act = actionList[targetAction];
+ callActionComponent(collided, act);
+ // 处理接收器回调
+ if (receivers.TryGetValue(collided, out var receiverGroups) &&
+ receiverGroups.TryGetValue(act.collider.colliGroup, out var receiverAction))
+ {
+ callActionComponent(act.collider, receiverAction);
+ }
+ }
+ }
+ else
+ {
+ callActionComponent(null, actionList[targetAction]);
+ }
+ }
+ singleResults[i].Dispose();
+ }
+ }
+ //处理多碰撞
+ {
+ int sigLength = multiResults.Length;
+ for (int i = 0; i < sigLength; i++)
+ {
+ var targetAction = multiResults[i].ActionTarget;
+ var arr = multiResults[i].Container;
+ if (arr.IsCreated)
+ {
+ foreach (var colliderId in arr)
+ {
+ if (colliders.TryGetValue(colliderId, out var collided))
+ {
+ callActionComponent(collided, actionList[targetAction]);
+ //多碰撞无接收器
+ }
+ }
+ }
+ multiResults[i].Dispose();
+ }
+ }
+
+ // 清理原生内存
+ singleResults.Dispose();
+ multiResults.Dispose();
+ jobHandles.Dispose();
+ ListPool<__action_checkColli__>.Release(actionList);
+ if (converterManager.IsCreated)
+ {
+ converterManager.Dispose();
+ }
+ }
+ #endregion
+
+ }
+ 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.Values)
+ {
+ 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();
+ }
+ }
+
+ public enum CollisionGroup
+ {
+ Default = 0,
+ Hero = 1,
+ HeroBullet = 2,
+ Bullet = 3,
+ Enemy = 4,
+ EnemyCollideBullet = 5,
+ Item = 6
+ }
+ /*
+ 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..c77bdbb
--- /dev/null
+++ b/Assets/ColliderStructure.cs
@@ -0,0 +1,939 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Core.Algorithm;
+using JetBrains.Annotations;
+using TrueSync;
+using Unity.Burst;
+using Unity.Collections;
+using Unity.Collections.LowLevel.Unsafe;
+using UnityEngine;
+using UnityEngine.UIElements;
+
+namespace ZeroAs.DOTS.Colliders
+{
+ public enum ColliderType
+ {
+ Circle,
+ Oval,
+ Polygon,
+ DoubleCircle,
+ }
+ [BurstCompile(OptimizeFor = OptimizeFor.Performance)]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct ColliderStructure:IEquatable
+ {
+ //从 1 开始,代表uniqueID如果是0就有问题了,因为这代表是从new创建出来的,不支持从new创建
+ private static int _globalIDCounter = 1;
+ public byte enabled;
+ public ColliderType colliderType;
+ public CollisionGroup collisionGroup;
+ #region 多边形
+ ///
+ /// 目前进行过修改的vertexStartIndex没同步到主线程上!!!
+ ///
+ internal int vertexStartIndex;
+ ///
+ /// 注意,vertexCount不可变
+ ///
+ 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)]
+ 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
+
+ public TSVector2 center;
+ public static ColliderStructure CreateInstance()
+ {
+ var t = new ColliderStructure
+ {
+ uniqueID = _globalIDCounter++,
+ collisionGroup = CollisionGroup.Default,
+ 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;
+ }
+ }
+ [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)]
+ public struct GetFurthestPointExtensions
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [BurstCompile(DisableDirectCall = false,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 = 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 = false,OptimizeFor = OptimizeFor.Performance)]
+ public static void Negate(ref TSVector2 val)
+ {
+ Negate(ref val.x);
+ Negate(ref val.y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [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 = 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)
+ {
+ //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 = 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_ = length;
+ for(int ia = len_-1; ia >= 0; --ia)
+ {
+ int i = offset+ia;
+ if((len= TSVector2.Dot(direction, movedVertexs[i])) > maxLen)
+ {
+ maxLen = len;
+ pos = movedVertexs[i];
+ }
+ }
+ result= pos;
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [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*
+ 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,in NativeArray.ReadOnly buffer)
+ {
+ 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, buffer,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 = 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,buffer);
+ //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 = false,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 = 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;
+ GetFurthestPointExtensions.Negate(ref cY);
+ result = new TSVector2(cY, c.x) * sign;
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [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])
+ #第一步:选择一个初始方向,这个初始方向可以是随机选择的,但通常来说是两个形状中心之间的向量,即:
+
+ */
+ TSVector2 tmpVec;
+ TSVector2 direction = (shape2.center - shape1.center).normalized;
+ //#第二步:找到支撑点,即第一个支撑点(即闵可夫斯基差的边上的点之一……)
+ NativeArray Simplex = new NativeArray(3,Allocator.Temp);//单纯形数组,最多只能是3个
+ GetFurthestPointExtensions.SupportFunc(out tmpVec,shape1, shape2, direction,buffer);
+ Simplex[0] = tmpVec;
+ int simplexLastInd = 1;
+ int interateTimeMax = 10;//最大迭代次数
+ //#第三步:找到第一个支撑点后,以第一个支撑点为起点指向原点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,buffer);
+ //因为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 = 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 = false,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);
+ }
+ }
+
+ [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 ColliderNativeHelper:IDisposable
+ {
+ private bool disposed = false;
+
+ public bool Disposed => disposed;
+
+ public static NativeArray.ReadOnly instancedBuffer
+ {
+ get
+ {
+ return CollisionManager.instance.nativeCollisionManager.vertices.AsReadOnly();
+ }
+ }
+
+ public NativeHashMap colliders = new NativeHashMap(2048,Allocator.Persistent);
+ 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);
+ 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(
+ 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);
+ }
+ ///
+ /// 注册Collider到数组里面,如果要调用这个静态函数记得配合RegisterCollisionGroup,必须同时使用
+ ///
+ ///
+ ///
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)]
+ static void RegisterCollider(
+ in NativeHashMap colliders,in NativeList vertices,
+ 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)]
+ 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.AsArray(),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 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);
+ }
+ ///
+ /// 从数组里面删除Collider,如果要调用这个静态函数记得配合DeleteCollisionGroup,必须同时使用
+ ///
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)]
+ static void DeleteCollider(ref NativeHashMap colliders,in ColliderStructure colli)
+ {
+ //var realColli = colliders[colli.uniqueID];
+ //removedIndexs.Add(realColli.vertexStartIndex,realColli.vertexStartIndex+realColli.vertexCount-1);
+ if(colliders.IsCreated)
+ colliders.Remove(colli.uniqueID);
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)]
+ public void DeleteCollider(in ColliderStructure colli)
+ {
+ DeleteCollider(ref colliders,colli);
+ DeleteCollisionGroup(ref groupedColliders,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 void CompactVertexBuffers(
+ ref NativeHashMap colliders,
+ ref NativeList vertices
+ )
+ {
+ if (!vertices.IsCreated)
+ {
+ throw new NullReferenceException("vertices数组未创建");
+ }
+ NativeList newList = new NativeList(vertices.Length,Allocator.Persistent);
+ newList.ResizeUninitialized(vertices.Length);
+ //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;
+ 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;
+ newStartIndex += val.vertexCount;
+ }
+ vertices.Dispose();
+ vertices = newList;
+ }
+ ///
+ /// 移除vertexbuffer的洞洞,注意这是个比较消耗性能的操作,并且要在主线程中同步所有的结构体的顶点位置?(提供同步方法,如果需要的话可以同步,貌似目前不需要,只是会throw出错而已)
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [BurstCompile(DisableDirectCall = false,OptimizeFor = OptimizeFor.Performance)]
+ public void CompactVertexBuffers()
+ {
+ CompactVertexBuffers(ref colliders,ref vertices);
+ }
+
+ public void Dispose()
+ {
+ disposed = true;
+ if(vertices.IsCreated)
+ vertices.Dispose();
+ //removedIndexs.Dispose();
+ if (colliders.IsCreated)
+ {
+ 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)]
+ 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);
+ ColliderNativeHelper.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);
+ ColliderNativeHelper.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();
+ }
+ }
+ [BurstCompile(DisableDirectCall = true,OptimizeFor = OptimizeFor.Performance)]
+ 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/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/ColliderTester.cs b/Assets/ColliderTester.cs
new file mode 100644
index 0000000..74d154c
--- /dev/null
+++ b/Assets/ColliderTester.cs
@@ -0,0 +1,194 @@
+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");
+ }
+ if (moveMode == MoveMode.Keyboard)
+ {
+ collider.colliGroup = CollisionGroup.Default;
+ }
+ else
+ {
+ collider.colliGroup = CollisionGroup.Bullet;
+ }
+ controller = new CollisionController(collider);
+ collider.enabled = true;
+ if (moveMode == MoveMode.Keyboard)
+ {
+ controller.AddListener(false, (obj) =>
+ {
+ meshRenderer.material.color=Color.red;
+ 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 ");
+ },CollisionGroup.Bullet);
+ }
+ }
+
+ void Update()
+ {
+ /*if (moveMode == MoveMode.Keyboard)
+ {
+ meshRenderer.material.color=Color.green;
+ }*/
+
+ 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/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..7cc8950 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 = Mathz.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/Mathz.cs b/Assets/Mathz.cs
new file mode 100644
index 0000000..4c7d777
--- /dev/null
+++ b/Assets/Mathz.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 Mathz
+{
+ 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/Mathz.cs.meta b/Assets/Mathz.cs.meta
new file mode 100644
index 0000000..f1f32e5
--- /dev/null
+++ b/Assets/Mathz.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 096c4a70d4e6a474784178f5dfa52f70
\ 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/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/RandomClones.cs b/Assets/RandomClones.cs
new file mode 100644
index 0000000..ded42ef
--- /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.1f)
+ {
+ 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 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..783abb2
--- /dev/null
+++ b/Assets/Scenes/New Scene.unity
@@ -0,0 +1,1008 @@
+%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 &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: 1
+--- !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
+ 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: 1
+ radius:
+ _serializedValue: 4294967296
+ boxSize:
+ x:
+ _serializedValue: 8589934592
+ y:
+ _serializedValue: 8589934592
+ ovalAxis:
+ x:
+ _serializedValue: 15032385536
+ y:
+ _serializedValue: 8589934592
+ 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 &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: -4, 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
+ 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: 21474836480
+ 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: 1641945851}
+ - {fileID: 1633608435}
+ - {fileID: 842675860}
+ - {fileID: 650477076}
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 1c63aa8..1187d56 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
@@ -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
@@ -177,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
@@ -250,12 +294,12 @@ 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!1 &410087039
GameObject:
m_ObjectHideFlags: 0
@@ -336,6 +380,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
@@ -398,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:
@@ -423,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
@@ -430,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/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/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/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/tmpExtensions.cs b/Assets/tmpExtensions.cs
new file mode 100644
index 0000000..1602f1f
--- /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.Sin(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/Packages/manifest.json b/Packages/manifest.json
index 0c4acda..6ca1371 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.ide.rider": "3.0.31",
- "com.unity.ide.visualstudio": "2.0.22",
- "com.unity.inputsystem": "1.13.1",
+ "com.unity.feature.2d": "2.0.1",
+ "com.unity.ide.rider": "3.0.36",
+ "com.unity.ide.visualstudio": "2.0.23",
+ "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..de36767 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,8 +136,23 @@
"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",
+ "version": "3.0.36",
"depth": 0,
"source": "registry",
"dependencies": {
@@ -54,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": {
@@ -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/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/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..8678d93 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.46f1
+m_EditorVersionWithRevision: 6000.0.46f1 (fb93bc360d3a)
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