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