该项目的目的是同时测试和演示来自 Unity DOTS 技术堆栈的多个新包。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

252 行
9.3 KiB

using System;
using System.Runtime.InteropServices;
using Unity.Entities;
using Unity.Jobs;
using Unity.Physics;
using Unity.Physics.Systems;
// TODO (mogensh) Improve this when we have C#8
[StructLayout(LayoutKind.Sequential)]
public struct CollisionHistoryBuffer
{
public const int size = 16;
private CollisionWorld CollisionWorld00;
private CollisionWorld CollisionWorld01;
private CollisionWorld CollisionWorld02;
private CollisionWorld CollisionWorld03;
private CollisionWorld CollisionWorld04;
private CollisionWorld CollisionWorld05;
private CollisionWorld CollisionWorld06;
private CollisionWorld CollisionWorld07;
private CollisionWorld CollisionWorld08;
private CollisionWorld CollisionWorld09;
private CollisionWorld CollisionWorld10;
private CollisionWorld CollisionWorld11;
private CollisionWorld CollisionWorld12;
private CollisionWorld CollisionWorld13;
private CollisionWorld CollisionWorld14;
private CollisionWorld CollisionWorld15;
public void GetCollisionWorldFromTick(int tick, out CollisionWorld collWorld)
{
var index = tick % size;
GetCollisionWorldFromIndex(index, out collWorld);
}
public void DisposeIndex(int index)
{
switch (index)
{
case 0 : CollisionWorld00.Dispose(); return;
case 1 : CollisionWorld01.Dispose(); return;
case 2 : CollisionWorld02.Dispose(); return;
case 3 : CollisionWorld03.Dispose(); return;
case 4 : CollisionWorld04.Dispose(); return;
case 5 : CollisionWorld05.Dispose(); return;
case 6 : CollisionWorld06.Dispose(); return;
case 7 : CollisionWorld07.Dispose(); return;
case 8 : CollisionWorld08.Dispose(); return;
case 9 : CollisionWorld09.Dispose(); return;
case 10 : CollisionWorld10.Dispose(); return;
case 11 : CollisionWorld11.Dispose(); return;
case 12 : CollisionWorld12.Dispose(); return;
case 13 : CollisionWorld13.Dispose(); return;
case 14 : CollisionWorld14.Dispose(); return;
case 15 : CollisionWorld15.Dispose(); return;
default:
throw new IndexOutOfRangeException();
}
}
void GetCollisionWorldFromIndex(int index, out CollisionWorld collWorld)
{
switch (index)
{
case 0 : collWorld = CollisionWorld00; break;
case 1 : collWorld = CollisionWorld01;break;
case 2 : collWorld = CollisionWorld02;break;
case 3 : collWorld = CollisionWorld03;break;
case 4 : collWorld = CollisionWorld04;break;
case 5 : collWorld = CollisionWorld05;break;
case 6 : collWorld = CollisionWorld06;break;
case 7 : collWorld = CollisionWorld07;break;
case 8 : collWorld = CollisionWorld08;break;
case 9 : collWorld = CollisionWorld09;break;
case 10 : collWorld = CollisionWorld10;break;
case 11 : collWorld = CollisionWorld11;break;
case 12 : collWorld = CollisionWorld12;break;
case 13 : collWorld = CollisionWorld13;break;
case 14 : collWorld = CollisionWorld14;break;
case 15 : collWorld = CollisionWorld15;break;
default:
throw new IndexOutOfRangeException();
}
}
public void CloneCollisionWorld(int index, in CollisionWorld collWorld)
{
switch (index)
{
case 0 : CollisionWorld00 = (CollisionWorld)collWorld.Clone(); break;
case 1 : CollisionWorld01 = (CollisionWorld)collWorld.Clone();break;
case 2 : CollisionWorld02 = (CollisionWorld)collWorld.Clone();break;
case 3 : CollisionWorld03 = (CollisionWorld)collWorld.Clone();break;
case 4 : CollisionWorld04 = (CollisionWorld)collWorld.Clone();break;
case 5 : CollisionWorld05 = (CollisionWorld)collWorld.Clone();break;
case 6 : CollisionWorld06 = (CollisionWorld)collWorld.Clone();break;
case 7 : CollisionWorld07 = (CollisionWorld)collWorld.Clone();break;
case 8 : CollisionWorld08 = (CollisionWorld)collWorld.Clone();break;
case 9 : CollisionWorld09 = (CollisionWorld)collWorld.Clone();break;
case 10 : CollisionWorld10 = (CollisionWorld)collWorld.Clone();break;
case 11 : CollisionWorld11 = (CollisionWorld)collWorld.Clone();break;
case 12 : CollisionWorld12 = (CollisionWorld)collWorld.Clone();break;
case 13 : CollisionWorld13 = (CollisionWorld)collWorld.Clone();break;
case 14 : CollisionWorld14 = (CollisionWorld)collWorld.Clone();break;
case 15 : CollisionWorld15 = (CollisionWorld)collWorld.Clone();break;
default:
throw new IndexOutOfRangeException();
}
}
}
//public class CollisionHistory
//{
// const int m_bufferCapacity = 16;
//
// private CollisionWorld[] m_CollisionWorlds = new CollisionWorld[m_bufferCapacity];
// private bool[] m_Stored = new bool[m_bufferCapacity];
//
// public CollisionHistory()
// {
// for (int i = 0; i < m_bufferCapacity; i++)
// m_CollisionWorlds[i] = new CollisionWorld(0);
// }
//
// public void Dispose()
// {
// // TODO (mogensh) wait for all jobs that might be querying this collisionworld
// for (int i = 0; i < m_bufferCapacity; i++)
// m_CollisionWorlds[i].Dispose();
// }
//
// public bool GetCollisionWorld(int tick, out CollisionWorld world)
// {
// if (tick < 0)
// {
// GameDebug.LogError("Invalid tick. tick:" + tick);
// world = new CollisionWorld(0);
// return false;
// }
//
//
// var index = tick % m_bufferCapacity;
//// GameDebug.Assert(index >= 0 && index < m_CollisionWorlds.Length, "Invalid index:{0}. Length:{1} tick:{2}", index, m_CollisionWorlds.Length, tick);
//
// if (!m_Stored[index])
// {
// // GameDebug.LogError("No data stored for index:" + index + " tick:" + tick);
// world = new CollisionWorld(0);
// return false;
// }
// // TODO (mogensh) add check for world not stored yet
//// GameDebug.Assert(m_CollisionWorlds[index].Bodies != null,"CollisionWorld has not been stored for tick:" + tick + " index:" + index);
//
// world = m_CollisionWorlds[index];
// return true;
// }
//
// public void Store(int tick, ref CollisionWorld sourceCollWorld)
// {
// if (tick <= m_LastStoredTick)
// return;
//
// // Store world for each tick that has not been stored yet (framerate might be lower than tickrate)
// var startStoreTick = m_LastStoredTick == -1 ? m_LastStoredTick + 1 : tick;
// for (int storeTick = startStoreTick; storeTick <= tick; storeTick++)
// {
// var index = storeTick % m_bufferCapacity;
//
// m_CollisionWorlds[index].Dispose();
//
// m_CollisionWorlds[index] = (CollisionWorld)sourceCollWorld.Clone();
// m_Stored[index] = true;
// }
//
// m_LastStoredTick = tick;
// }
//
// int m_LastStoredTick = -1;
//}
[UpdateInGroup(typeof(SimulationSystemGroup))]
[UpdateAfter(typeof(BuildPhysicsWorld))]
[AlwaysUpdateSystem]
[AlwaysSynchronizeSystem]
public class PhysicsWorldHistory : JobComponentSystem
{
private bool m_initialized;
private int m_lastStoredTick;
public CollisionHistoryBuffer CollisionHistory
{
get { return m_CollisionHistory; }
}
CollisionHistoryBuffer m_CollisionHistory;
protected override void OnDestroy()
{
base.OnDestroy();
if (m_initialized)
{
for(int i=0;i<CollisionHistoryBuffer.size;i++)
m_CollisionHistory.DisposeIndex(i);
}
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var timeQuery = GetEntityQuery(ComponentType.ReadOnly<GlobalGameTime>());
if (timeQuery.CalculateEntityCount() == 0)
return default;
var globalTime = timeQuery.GetSingleton<GlobalGameTime>();
var tick = globalTime.gameTime.tick;
var buildPhysicsWorld = World.GetExistingSystem<BuildPhysicsWorld>();
buildPhysicsWorld.FinalJobHandle.Complete();
if (!m_initialized)
{
for (int i = 0; i < CollisionHistoryBuffer.size; i++)
{
m_CollisionHistory.CloneCollisionWorld(i, in buildPhysicsWorld.PhysicsWorld.CollisionWorld);
}
m_lastStoredTick = tick;
m_initialized = true;
}
else
{
if (tick <= m_lastStoredTick)
return default;
// Store world for each tick that has not been stored yet (framerate might be lower than tickrate)
var startStoreTick = m_lastStoredTick != -1 ? m_lastStoredTick + 1 : tick;
// GameDebug.Log(World,null,"Store:{0}->{1}",startStoreTick,tick);
for (int storeTick = startStoreTick; storeTick <= tick; storeTick++)
{
var index = storeTick % CollisionHistoryBuffer.size;
m_CollisionHistory.DisposeIndex(index);
m_CollisionHistory.CloneCollisionWorld(index, in buildPhysicsWorld.PhysicsWorld.CollisionWorld);
}
m_lastStoredTick = tick;
}
return default;
}
}