ecs framework

master
abenmonkey 2 years ago
parent 6d59d7f23f
commit 3a1e97df6f
  1. 7
      Assets/Scripts/EntityData.cs
  2. 11
      Assets/Scripts/EntityData.cs.meta
  3. 9
      Assets/Scripts/EntityType.cs
  4. 11
      Assets/Scripts/EntityType.cs.meta
  5. 19
      Assets/Scripts/TestJob.cs
  6. 11
      Assets/Scripts/TestJob.cs.meta
  7. 8
      LocalPackages/com.nimin.tinyecs/Runtime.meta
  8. 48
      LocalPackages/com.nimin.tinyecs/Runtime/Entity.cs
  9. 11
      LocalPackages/com.nimin.tinyecs/Runtime/Entity.cs.meta
  10. 129
      LocalPackages/com.nimin.tinyecs/Runtime/EntityCollection.cs
  11. 11
      LocalPackages/com.nimin.tinyecs/Runtime/EntityCollection.cs.meta
  12. 79
      LocalPackages/com.nimin.tinyecs/Runtime/EntityGenerator.cs
  13. 11
      LocalPackages/com.nimin.tinyecs/Runtime/EntityGenerator.cs.meta
  14. 33
      LocalPackages/com.nimin.tinyecs/Runtime/TinyECS.Runtime.asmdef
  15. 7
      LocalPackages/com.nimin.tinyecs/Runtime/TinyECS.Runtime.asmdef.meta
  16. 14
      LocalPackages/com.nimin.tinyecs/package.json
  17. 7
      LocalPackages/com.nimin.tinyecs/package.json.meta
  18. 3
      Packages/manifest.json
  19. 35
      Packages/packages-lock.json
  20. 191
      ProjectSettings/ProjectSettings.asset

@ -0,0 +1,7 @@
using GameCore.TinyECS;
namespace GameCore.Test
{
using Entity = Entity<EntityType>;
}

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 72e85a26219664e7f843536ec14a06bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,9 @@
namespace GameCore.Test
{
public enum EntityType
{
Unit,
Monster,
}
}

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8fbbe7882877348f8a41a85ea6281b10
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,19 @@
using System;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
namespace GameCore.Test
{
[BurstCompile]
public struct TestJob : IJobParallelFor
{
public void Execute(int index)
{
}
}
}

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68aafcef1265449e6b6b2dd81d7173a8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4ebb82ca8005849b48d82e7b2799da17
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,48 @@
using System;
namespace GameCore.TinyECS
{
public readonly struct Entity<TEnum> : IEquatable<Entity<TEnum>> where TEnum : unmanaged
{
public readonly TEnum type;
public readonly int index;
public readonly int generation;
public Entity(TEnum type, int index, int generation)
{
this.type = type;
this.index = index;
this.generation = generation;
}
public override string ToString()
{
return $"Entity<{type}>({index},{generation})";
}
public bool Equals(Entity<TEnum> other)
{
return type.Equals(other.type) && index == other.index && generation == other.generation;
}
public override bool Equals(object obj)
{
return obj is Entity<TEnum> other && Equals(other);
}
public override int GetHashCode()
{
return HashCode.Combine(type, index, generation);
}
public static bool operator ==(Entity<TEnum> lhs, Entity<TEnum> rhs)
{
return lhs.Equals(rhs);
}
public static bool operator !=(Entity<TEnum> lhs, Entity<TEnum> rhs)
{
return !(lhs == rhs);
}
}
}

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ad57411486945444c95e8a0aec2cf8b7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,129 @@
using System;
using Unity.Collections;
using System.Diagnostics;
namespace GameCore.TinyECS
{
public struct EntityCollection<TEnum> : IDisposable where TEnum : unmanaged
{
private struct Buffer
{
public int index;
public int generation;
}
private NativeList<Buffer> entityBuffer;
private NativeList<int> entityIndexToDataIndex;
private TEnum entityType;
public EntityCollection(TEnum type, int capacity, Allocator allocator)
{
entityType = type;
entityBuffer = new (capacity, allocator);
entityIndexToDataIndex = new (capacity, allocator);
}
public void Dispose()
{
entityBuffer.Dispose();
entityIndexToDataIndex.Dispose();
}
public int Count => entityBuffer.Length;
public Entity<TEnum> this[int index]
{
get
{
var buf = entityBuffer[index];
return new(entityType, buf.index, buf.generation);
}
}
public int Add(Entity<TEnum> entity)
{
CheckEntityType(entity);
var dataIndex = entityBuffer.Length;
var oldEntityCount = entityIndexToDataIndex.Length;
if (entity.index >= oldEntityCount)
{
entityIndexToDataIndex.Resize(entity.index + 1, NativeArrayOptions.UninitializedMemory);
for (int i = oldEntityCount, e = entity.index - 1; i < e; ++i)
{
entityIndexToDataIndex[i] = -1;
}
}
entityIndexToDataIndex[entity.index] = dataIndex;
entityBuffer.Add(new Buffer{index = entity.index, generation = entity.generation });
return dataIndex;
}
public bool TryGetIndex(Entity<TEnum> entity, out int index)
{
CheckEntityType(entity);
index = 0;
if (entity.index >= entityIndexToDataIndex.Length)
{
return false;
}
index = entityIndexToDataIndex[entity.index];
if (index < 0 || index >= entityBuffer.Length)
{
return false;
}
var buf = entityBuffer[index];
return buf.index == entity.index && buf.generation == entity.generation;
}
public bool Remove(Entity<TEnum> entity, out int index, out bool removeFromBack)
{
CheckEntityType(entity);
if (!TryGetIndex(entity, out index))
{
removeFromBack = false;
return false;
}
removeFromBack = RemoveInternal(entity, index);
return true;
}
private bool RemoveInternal(Entity<TEnum> entity, int index)
{
entityIndexToDataIndex[entity.index] = -1;
var backIndex = entityBuffer.Length - 1;
if (index == backIndex)
{
entityBuffer.Resize(backIndex, NativeArrayOptions.UninitializedMemory);
return true;
}
var backBuf = entityBuffer[backIndex];
entityBuffer.RemoveAtSwapBack(index);
entityIndexToDataIndex[backBuf.index] = index;
return false;
}
[Conditional("DEBUG")]
void CheckEntityType(Entity<TEnum> entity)
{
if (!entity.type.Equals(entityType))
throw new Exception($"Wrong entity type: {entity.type}");
}
public void Clear()
{
entityBuffer.Clear();
entityIndexToDataIndex.Clear();
}
}
}

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c788a2d204aeb46b188a801ae66ab4ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,79 @@
using System;
using Unity.Collections;
using Unity.Mathematics;
namespace GameCore.TinyECS
{
public struct EntityGenerator<TEnum> : IDisposable where TEnum : unmanaged
{
private NativeList<int> indexToGeneration;
private int beginSearchIndex;
private int freeCount;
private TEnum entityType;
public EntityGenerator(TEnum type, int capacity, Allocator allocator)
{
indexToGeneration = new(capacity, allocator) { 0 };
beginSearchIndex = 1;
freeCount = 0;
entityType = type;
}
public void Dispose()
{
indexToGeneration.Dispose();
}
public Entity<TEnum> Create()
{
if (freeCount == 0)
{
var index = indexToGeneration.Length;
indexToGeneration.Add(1);
return new(entityType, index, 1);
}
var count = indexToGeneration.Length;
for (var i = beginSearchIndex; i < count; ++i)
{
var oldGeneration = indexToGeneration[i];
if (oldGeneration >= 0)
continue;
beginSearchIndex = i + 1;
freeCount--;
var generation = 1 - oldGeneration;
indexToGeneration[i] = generation;
return new(entityType, i, generation);
}
throw new Exception("Impossible");
}
public void Delete(Entity<TEnum> entity)
{
var generation = indexToGeneration[entity.index];
if (generation != entity.generation)
{
throw new Exception($"Invalid entity: {entity}");
}
indexToGeneration[entity.index] = -generation;
freeCount++;
beginSearchIndex = math.min(beginSearchIndex, entity.index);
}
public bool IsValid(Entity<TEnum> entity)
{
var generation = indexToGeneration[entity.index];
return generation == entity.generation;
}
public void Clear()
{
indexToGeneration.Resize(1, NativeArrayOptions.UninitializedMemory);
beginSearchIndex = 1;
freeCount = 0;
}
}
}

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d1bf40e20fa3e4ea69d9a9896a297fe1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,33 @@
{
"name": "TinyECS.Runtime",
"rootNamespace": "",
"references": [
"Unity.Collections",
"Unity.Mathematics"
],
"includePlatforms": [
"Android",
"Editor",
"iOS",
"LinuxStandalone64",
"Lumin",
"macOSStandalone",
"PS4",
"Stadia",
"Switch",
"tvOS",
"WSA",
"WebGL",
"WindowsStandalone32",
"WindowsStandalone64",
"XboxOne"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c2bd585c8e44341079d076e23cd9d3eb
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,14 @@
{
"name": "com.nimin.tinyecs",
"displayName": "Tiny ECS",
"version": "0.1.0",
"unity": "2021.3",
"description": "Data oriented ECS famework",
"dependencies": {
"com.unity.collections": "1.2.4",
"com.unity.burst": "1.8.1"
},
"keywords": [
"ECS", "JobSystem"
]
}

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: afdf6be686c684f4c8190a688038f1ca
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

@ -40,6 +40,7 @@
"com.unity.modules.video": "1.0.0",
"com.unity.modules.vr": "1.0.0",
"com.unity.modules.wind": "1.0.0",
"com.unity.modules.xr": "1.0.0"
"com.unity.modules.xr": "1.0.0",
"com.nimin.tinyecs": "file:../LocalPackages/com.nimin.tinyecs"
}
}

@ -1,5 +1,23 @@
{
"dependencies": {
"com.nimin.tinyecs": {
"version": "file:../LocalPackages/com.nimin.tinyecs",
"depth": 0,
"source": "local",
"dependencies": {
"com.unity.collections": "1.2.4",
"com.unity.burst": "1.8.1"
}
},
"com.unity.burst": {
"version": "1.8.1",
"depth": 1,
"source": "registry",
"dependencies": {
"com.unity.mathematics": "1.2.1"
},
"url": "https://packages.unity.cn"
},
"com.unity.collab-proxy": {
"version": "1.17.1",
"depth": 0,
@ -9,6 +27,16 @@
},
"url": "https://packages.unity.cn"
},
"com.unity.collections": {
"version": "1.2.4",
"depth": 1,
"source": "registry",
"dependencies": {
"com.unity.burst": "1.6.6",
"com.unity.test-framework": "1.1.31"
},
"url": "https://packages.unity.cn"
},
"com.unity.editorcoroutines": {
"version": "1.0.0",
"depth": 1,
@ -62,6 +90,13 @@
"dependencies": {},
"url": "https://packages.unity.cn"
},
"com.unity.mathematics": {
"version": "1.2.6",
"depth": 2,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.cn"
},
"com.unity.nuget.newtonsoft-json": {
"version": "3.0.2",
"depth": 2,

@ -280,7 +280,196 @@ PlayerSettings:
AndroidValidateAppBundleSize: 1
AndroidAppBundleSizeToValidate: 150
m_BuildTargetIcons: []
m_BuildTargetPlatformIcons: []
m_BuildTargetPlatformIcons:
- m_BuildTarget: iPhone
m_Icons:
- m_Textures: []
m_Width: 180
m_Height: 180
m_Kind: 0
m_SubKind: iPhone
- m_Textures: []
m_Width: 120
m_Height: 120
m_Kind: 0
m_SubKind: iPhone
- m_Textures: []
m_Width: 167
m_Height: 167
m_Kind: 0
m_SubKind: iPad
- m_Textures: []
m_Width: 152
m_Height: 152
m_Kind: 0
m_SubKind: iPad
- m_Textures: []
m_Width: 76
m_Height: 76
m_Kind: 0
m_SubKind: iPad
- m_Textures: []
m_Width: 120
m_Height: 120
m_Kind: 3
m_SubKind: iPhone
- m_Textures: []
m_Width: 80
m_Height: 80
m_Kind: 3
m_SubKind: iPhone
- m_Textures: []
m_Width: 80
m_Height: 80
m_Kind: 3
m_SubKind: iPad
- m_Textures: []
m_Width: 40
m_Height: 40
m_Kind: 3
m_SubKind: iPad
- m_Textures: []
m_Width: 87
m_Height: 87
m_Kind: 1
m_SubKind: iPhone
- m_Textures: []
m_Width: 58
m_Height: 58
m_Kind: 1
m_SubKind: iPhone
- m_Textures: []
m_Width: 29
m_Height: 29
m_Kind: 1
m_SubKind: iPhone
- m_Textures: []
m_Width: 58
m_Height: 58
m_Kind: 1
m_SubKind: iPad
- m_Textures: []
m_Width: 29
m_Height: 29
m_Kind: 1
m_SubKind: iPad
- m_Textures: []
m_Width: 60
m_Height: 60
m_Kind: 2
m_SubKind: iPhone
- m_Textures: []
m_Width: 40
m_Height: 40
m_Kind: 2
m_SubKind: iPhone
- m_Textures: []
m_Width: 40
m_Height: 40
m_Kind: 2
m_SubKind: iPad
- m_Textures: []
m_Width: 20
m_Height: 20
m_Kind: 2
m_SubKind: iPad
- m_Textures: []
m_Width: 1024
m_Height: 1024
m_Kind: 4
m_SubKind: App Store
- m_BuildTarget: Android
m_Icons:
- m_Textures: []
m_Width: 432
m_Height: 432
m_Kind: 2
m_SubKind:
- m_Textures: []
m_Width: 324
m_Height: 324
m_Kind: 2
m_SubKind:
- m_Textures: []
m_Width: 216
m_Height: 216
m_Kind: 2
m_SubKind:
- m_Textures: []
m_Width: 162
m_Height: 162
m_Kind: 2
m_SubKind:
- m_Textures: []
m_Width: 108
m_Height: 108
m_Kind: 2
m_SubKind:
- m_Textures: []
m_Width: 81
m_Height: 81
m_Kind: 2
m_SubKind:
- m_Textures: []
m_Width: 192
m_Height: 192
m_Kind: 1
m_SubKind:
- m_Textures: []
m_Width: 144
m_Height: 144
m_Kind: 1
m_SubKind:
- m_Textures: []
m_Width: 96
m_Height: 96
m_Kind: 1
m_SubKind:
- m_Textures: []
m_Width: 72
m_Height: 72
m_Kind: 1
m_SubKind:
- m_Textures: []
m_Width: 48
m_Height: 48
m_Kind: 1
m_SubKind:
- m_Textures: []
m_Width: 36
m_Height: 36
m_Kind: 1
m_SubKind:
- m_Textures: []
m_Width: 192
m_Height: 192
m_Kind: 0
m_SubKind:
- m_Textures: []
m_Width: 144
m_Height: 144
m_Kind: 0
m_SubKind:
- m_Textures: []
m_Width: 96
m_Height: 96
m_Kind: 0
m_SubKind:
- m_Textures: []
m_Width: 72
m_Height: 72
m_Kind: 0
m_SubKind:
- m_Textures: []
m_Width: 48
m_Height: 48
m_Kind: 0
m_SubKind:
- m_Textures: []
m_Width: 36
m_Height: 36
m_Kind: 0
m_SubKind:
m_BuildTargetBatching:
- m_BuildTarget: Standalone
m_StaticBatching: 1

Loading…
Cancel
Save