浏览代码

Merge branch 'dots-physics' into merge-branch

# Conflicts:
#	Assets/Objects/boats/Prefabs/_Boat.prefab
#	Assets/Scripts/Boat/AIcontroller.cs
#	Assets/Scripts/Boat/Engine.cs
#	Assets/Scripts/GameSystem/RaceManager.cs
#	Assets/Scripts/GameSystem/WaypointGroup.cs
#	Packages/com.verasl.water-system/Scripts/BuoyantObject.cs
#	Packages/com.verasl.water-system/Scripts/Water.cs
#	Packages/manifest.json
/demo-work-customrenderer
Mike Geig 5 年前
当前提交
ff35ecaa
共有 955 个文件被更改,包括 6356 次插入387 次删除
  1. 748
      Assets/Objects/boats/Prefabs/_Boat.prefab
  2. 9
      Assets/Scripts/Boat/BoatController.cs
  3. 4
      Assets/Scripts/Boat/HumanController.cs
  4. 17
      Packages/com.verasl.water-system/Scripts/BuoyantObject.cs
  5. 43
      Packages/com.verasl.water-system/Scripts/Water.cs
  6. 8
      Assets/EntityCache.meta
  7. 8
      Assets/Unity Physics Items.meta
  8. 8
      Assets/EntityCache/Resources.meta
  9. 7
      Assets/Unity Physics Items/Physics Scene.unity.meta
  10. 8
      Assets/Unity Physics Items/Components.meta
  11. 8
      Assets/Unity Physics Items/Prefabs.meta
  12. 8
      Assets/Unity Physics Items/Systems.meta
  13. 11
      Assets/Unity Physics Items/BuoyantObject_DOTS.cs.meta
  14. 115
      Assets/Unity Physics Items/AIController_DOTS.cs
  15. 11
      Assets/Unity Physics Items/AIController_DOTS.cs.meta
  16. 15
      Assets/Unity Physics Items/BoatBodyComponent.cs
  17. 375
      Assets/Unity Physics Items/BuoyantObject_DOTS.cs
  18. 11
      Assets/Unity Physics Items/Components/BoatDataComponents.cs.meta
  19. 33
      Assets/Unity Physics Items/Components/BoatDataComponents.cs
  20. 1001
      Assets/Unity Physics Items/Physics Scene.unity
  21. 7
      Assets/Unity Physics Items/Prefabs/BoatEntity.prefab.meta
  22. 88
      Assets/Unity Physics Items/Prefabs/Physics Settings.prefab
  23. 7
      Assets/Unity Physics Items/Prefabs/Physics Settings.prefab.meta
  24. 8
      Assets/Unity Physics Items/Prefabs/Slippery.asset.meta
  25. 42
      Assets/Unity Physics Items/Prefabs/Slippery.asset
  26. 146
      Assets/Unity Physics Items/Prefabs/AIBoatEntity Variant.prefab
  27. 7
      Assets/Unity Physics Items/Prefabs/AIBoatEntity Variant.prefab.meta
  28. 1001
      Assets/Unity Physics Items/Prefabs/BoatEntity.prefab
  29. 11
      Assets/Unity Physics Items/Systems/ApplyBuoyancyForceSystem.cs.meta
  30. 11
      Assets/Unity Physics Items/Systems/DriveSystem.cs.meta
  31. 11
      Assets/Unity Physics Items/Systems/GertsnerSystem.cs.meta
  32. 11
      Assets/Unity Physics Items/Systems/PhysicsConversionSystem.cs.meta
  33. 127
      Assets/Unity Physics Items/Systems/GertsnerSystem.cs
  34. 21
      Assets/Unity Physics Items/Systems/PhysicsConversionSystem.cs
  35. 96
      Assets/Unity Physics Items/Systems/ApplyBuoyancyForceSystem.cs
  36. 68
      Assets/Unity Physics Items/Systems/DriveSystem.cs
  37. 54
      Assets/Unity Physics Items/Systems/InputSystem.cs
  38. 11
      Assets/Unity Physics Items/Systems/InputSystem.cs.meta
  39. 11
      Assets/Unity Physics Items/BoatBodyComponent.cs.meta
  40. 176
      Packages/com.unity.entities@0.0.12-preview.33/CHANGELOG.md
  41. 7
      Packages/com.unity.entities@0.0.12-preview.33/CHANGELOG.md.meta
  42. 28
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/TableOfContents.md
  43. 22
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/chunk_iteration.md
  44. 219
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/chunk_iteration_job.md
  45. 26
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/component_data.md
  46. 223
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/component_group.md
  47. 15
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/component_system.md
  48. 382
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/custom_job_types.md
  49. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/doo_design.md
  50. 94
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/dynamic_buffers.md
  51. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_anatomy.md
  52. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_building_projects.md
  53. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_burst.md
  54. 37
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_components.md
  55. 117
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_core.md
  56. 8
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_data_structures.md
  57. 56
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_debugging.md
  58. 54
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_entities.md
  59. 8
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_gameplay.md
  60. 101
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_in_detail.md
  61. 25
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_job_extensions.md
  62. 44
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_job_overview.md
  63. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_profiling.md
  64. 16
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_project_status.md
  65. 6
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_systems.md
  66. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_testing.md
  67. 164
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_write_groups.md
  68. 12
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/entities.md
  69. 41
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/entity_command_buffer.md
  70. 113
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/entity_iteration_foreach.md
  71. 147
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/entity_iteration_job.md
  72. 53
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/entity_manager.md
  73. 11
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/exclusive_entity_transaction.md
  74. 8
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/execution_order.md
  75. 37
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/filter.yml
  76. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_ai.md
  77. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_animation.md
  78. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_assets.md
  79. 8
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_audio.md
  80. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_ecs_interop.md
  81. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_input.md
  82. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_multiplayer.md
  83. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_physics.md
  84. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_prefabs.md
  85. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_rendering.md
  86. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_scenes.md
  87. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_text_handling.md
  88. 7
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_ui.md
  89. 4
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/images/pixel.png
  90. 40
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/images/sec1-1.png
  91. 50
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/images/sec1-2.png
  92. 79
      Packages/com.unity.entities@0.0.12-preview.33/Documentation~/images/sec2-1.png

748
Assets/Objects/boats/Prefabs/_Boat.prefab
文件差异内容过多而无法显示
查看文件

9
Assets/Scripts/Boat/BoatController.cs


public Color PrimaryColor; // Boat primary colour
public Color TrimColor; // Boat secondary colour
public Renderer boatRenderer; // The renderer for the boat mesh
public Engine engine;
public CinemachineVirtualCamera cam;
void OnValidate()

// Use this for initialization
void Start()
void Awake()
gameObject.AddComponent<HumanController>().engine = engine; // Adds a human controller if human
gameObject.AddComponent<HumanController>(); // Adds a human controller if human
gameObject.AddComponent<AIcontroller>().engine = engine; // Adds an AI controller if AI
gameObject.AddComponent<AIcontroller>(); // Adds an AI controller if AI
}
}

4
Assets/Scripts/Boat/HumanController.cs


controls.BoatControls.Steering.performed += context => steering = context.ReadValue<float>();
controls.BoatControls.Steering.canceled += context => steering = 0f;
}
engine = GetComponent<Engine>(); // get the engine script
}
private void OnEnable()
{

17
Packages/com.verasl.water-system/Scripts/BuoyantObject.cs


if(_buoyancyType == BuoyancyType.PhysicalVoxel)
{
//Debug.Log("new pass: " + gameObject.name);
UpdateDrag(submergedAmount);
// UpdateDrag(submergedAmount);
}
else if(_buoyancyType == BuoyancyType.Physical)
{

private void BuoyancyForce(Vector3 position, float waterHeight, ref float submergedAmount, ref DebugDrawing _debug)
{
var wp = transform.TransformPoint(position);
float waterLevel = waterHeight;
float waterLevel = waterHeight;
Vector3 force = Vector3.zero;
float k = Mathf.Clamp01((waterLevel - (wp.y - voxelResolution)) / (voxelResolution * 2f));
float k = Mathf.Clamp01((waterLevel - (wp.y - voxelResolution)) / (voxelResolution * 2f));
submergedAmount += k / voxels.Length;//(math.clamp(waterLevel - (wp.y - voxelResolution), 0f, voxelResolution * 2f) / (voxelResolution * 2f)) / voxels.Count;
submergedAmount += k / voxels.Length;//(math.clamp(waterLevel - (wp.y - voxelResolution), 0f, voxelResolution * 2f) / (voxelResolution * 2f)) / voxels.Count;
var force = localDampingForce + Mathf.Sqrt(k) * localArchimedesForce;//\
force = localDampingForce + Mathf.Sqrt(k) * localArchimedesForce;//\
}
}
//Debug.Log(string.Format("Position: {0:f1} -- Force: {1:f2} -- Height: {2:f2}\nVelocty: {3:f2} -- Damp: {4:f2} -- Mass: {5:f1} -- K: {6:f2}", wp, force, waterLevel, velocity, localDampingForce, RB.mass, localArchimedesForce));
}
}
private void UpdateDrag(float submergedAmount)
{

43
Packages/com.verasl.water-system/Scripts/Water.cs


using UnityEngine.Profiling;
using UnityEngine.Rendering;
using UnityEngine.Rendering.LWRP;
using UnityEngine.Rendering.Universal;
using Lightmapping = UnityEngine.Experimental.GlobalIllumination.Lightmapping;
namespace WaterSystem
{

return _Instance;
}
}
// Script references
private MainCameraAlign camAlign;
private PlanarReflections planarReflections;
private bool useComputeBuffer;
public bool computeOverride;

useComputeBuffer = false;
Init();
RenderPipelineManager.beginCameraRendering += BeginCameraRendering;
if(resources == null)
{
resources = Resources.Load("WaterResources") as WaterResources;
}
}
private void OnDisable() {

float roll = cam.transform.localEulerAngles.z;
Shader.SetGlobalFloat("_CameraRoll", roll);
Shader.SetGlobalMatrix("_InvViewProjection", (GL.GetGPUProjectionMatrix(cam.projectionMatrix, false) * cam.worldToCameraMatrix).inverse);
foreach (var mesh in resources.defaultWaterMeshes)
{
Graphics.DrawMesh(mesh, transform.localToWorldMatrix, resources.defaultSeaMaterial, gameObject.layer, cam);
}
}
private void SafeDestroy(Object o)

{
Shader.SetGlobalTexture("_WaterDepthMap", _bakedDepthTex);
}
if (!gameObject.TryGetComponent(out camAlign))
{
camAlign = gameObject.AddComponent<MainCameraAlign>();
camAlign.hideFlags = HideFlags.HideAndDontSave | HideFlags.HideInInspector;
}
if (!gameObject.TryGetComponent(out planarReflections))
{
planarReflections = gameObject.AddComponent<PlanarReflections>();
planarReflections.hideFlags = HideFlags.HideAndDontSave | HideFlags.HideInInspector;
}
planarReflections.m_settings = settingsData.planarSettings;
planarReflections.enabled = settingsData.refType == ReflectionType.PlanarReflection;
if(resources == null)
{
resources = Resources.Load("WaterResources") as WaterResources;
}
//CaptureDepthMap();
private void LateUpdate() {
if(Application.isPlaying)
GerstnerWavesJobs.UpdateHeights();
void Update()
{
waterTime = Time.time;
Shader.SetGlobalFloat("_GlobalTime", waterTime);
GerstnerWavesJobs.UpdateHeights();
}
public void FragWaveNormals(bool toggle)

8
Assets/EntityCache.meta


fileFormatVersion: 2
guid: e50cf0f4dde230944a81a4bb1a939a90
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Unity Physics Items.meta


fileFormatVersion: 2
guid: b67fc1f9c9fc5be47b5a34feb592f451
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/EntityCache/Resources.meta


fileFormatVersion: 2
guid: f81c7c23b2629154aa90990298a95e36
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

7
Assets/Unity Physics Items/Physics Scene.unity.meta


fileFormatVersion: 2
guid: 15526d9c33e0e1a4a976cb75b81a90bb
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Unity Physics Items/Components.meta


fileFormatVersion: 2
guid: abe8179f462907947a719dde0391f6dc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Unity Physics Items/Prefabs.meta


fileFormatVersion: 2
guid: a9875aaa1f03515488c4e37f55db9618
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Unity Physics Items/Systems.meta


fileFormatVersion: 2
guid: 71f78570d6fb8c74a92c6e06b82f20e6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

11
Assets/Unity Physics Items/BuoyantObject_DOTS.cs.meta


fileFormatVersion: 2
guid: 0fe52c158d195e64a99e4eaa38bb3df7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

115
Assets/Unity Physics Items/AIController_DOTS.cs


using BoatAttack;
using System.Collections;
using System.Collections.Generic;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.AI;
class PathData
{
public Vector3[] pathPoint;
public int curPoint;
public int curWP;
public bool foundPath;
};
public class AIController_DOTS : MonoBehaviour
{
static AIController_DOTS main;
Dictionary<Entity, PathData> paths;
private void Awake()
{
if (main != null && main != this)
{
Destroy(this);
return;
}
main = this;
paths = new Dictionary<Entity, PathData>();
}
public static void Register(Entity entity)
{
if (main.paths.ContainsKey(entity))
return;
PathData data = new PathData();
main.paths.Add(entity, data);
}
public static void GetInputs(Entity entity, float3 pos, quaternion rot, out float throttle, out float steering)
{
main.GetInputsInternal(entity, pos, rot, out throttle, out steering);
}
void GetInputsInternal(Entity entity, float3 pos, quaternion rot, out float throttle, out float steering)
{
throttle = steering = 0;
//Do we have data?
PathData data;
if (!paths.TryGetValue(entity, out data))
return;
if (data.pathPoint == null)
{
WaypointGroup.Waypoint wp = WaypointGroup.Instance.GetClosestWaypoint(pos);
CalculatePath(WaypointGroup.Instance.GetNextWaypoint(wp), data, pos);
}
else if (data.pathPoint.Length > data.curPoint && data.foundPath)
{
if ((Vector3.Distance(pos, data.pathPoint[data.curPoint])) < 8) // If we are close to the current point on the path get the next
{
data.curPoint++; // Move on to next point
if (data.curPoint >= data.pathPoint.Length)
CalculatePath(WaypointGroup.Instance.GetWaypoint(data.curWP), data, pos);
}
}
if (data.pathPoint != null && data.pathPoint.Length > data.curPoint)
{
//Get angle to the destination and the side
Vector3 normDir = data.pathPoint[data.curPoint] - (Vector3)pos;
normDir = normDir.normalized;
var forward = math.forward(rot);
float dot = Vector3.Dot(normDir, forward);
//float angle = Mathf.Acos (dot) * Mathf.Rad2Deg;
float targetSide = Vector3.Cross(forward, normDir).y;//positive on right side, negative on left side
steering = Mathf.Clamp(targetSide, -1.0f, 1.0f);
throttle = dot > 0 ? 1f : 0.25f;
}
}
void CalculatePath(WaypointGroup.Waypoint wp, PathData data, float3 pos)
{
var offset = (UnityEngine.Random.value * 2f - 1f) * wp.WPwidth * Vector3.left;
var curWPPos = wp.point + wp.rotation * offset;
data.curWP++;
if (data.curWP >= WaypointGroup.Instance.WPs.Count)
data.curWP = 0;
var navPath = new NavMeshPath(); // New nav path
NavMesh.CalculatePath(pos, curWPPos, 255, navPath);
if (navPath.status == NavMeshPathStatus.PathComplete) // if the path is good(complete) use it
{
data.pathPoint = navPath.corners;
data.curPoint = 1;
data.foundPath = true;
}
else if (navPath == null || navPath.status == NavMeshPathStatus.PathInvalid) // if the path is bad, we havent found a path
{
data.foundPath = false;
}
}
}

11
Assets/Unity Physics Items/AIController_DOTS.cs.meta


fileFormatVersion: 2
guid: d535e331fdb3f734cb363f09fa881545
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

15
Assets/Unity Physics Items/BoatBodyComponent.cs


using System.Collections;
using System.Collections.Generic;
using Unity.Entities;
using Unity.Transforms;
using UnityEngine;
public class BoatBodyComponent : MonoBehaviour//, IConvertGameObjectToEntity
{
//Called by parent BuoyantObject_DOTS
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
dstManager.AddComponent(entity, typeof(CopyTransformToGameObject));
}
}

375
Assets/Unity Physics Items/BuoyantObject_DOTS.cs


using System;
using System.Collections.Generic;
using UnityEngine;
using Unity.Mathematics;
using Unity.Entities;
using BoatAttack.Boat;
using System.Collections;
//using Unity.Physics;
namespace WaterSystem
{
public class BuoyantObject_DOTS : MonoBehaviour//, IConvertGameObjectToEntity
{
public BuoyancyType _buoyancyType; // type of buoyancy to calculate
public float density; // density of the object, this is calculated off it's volume and mass
public float volume; // volume of the object, this is calculated via it's colliders
public float voxelResolution = 0.51f; // voxel resolution, represents the half size of a voxel when creating the voxel representation
private Bounds voxelBounds; // bounds of the voxels
public Vector3 centerOfMass = Vector3.zero; // Center Of Mass offset
private const float DAMPFER = 0.005f;
private const float WATER_DENSITY = 1000;
private float baseDrag; // reference to original drag
private float baseAngularDrag; // reference to original angular drag
private int _guid; // GUID for the height system
private Vector3 localArchimedesForce;
[SerializeField]
private Vector3[] voxels; // voxel position
private float3[] samplePoints; // sample points for height calc
private float3[] heights; // water height array(only size of 1 when simple or non-physical)
private float3[] normals; // water normal array(only used when non-physical and size of 1 also when simple)
[SerializeField]
Collider[] colliders; // colliders attatched ot this object
Rigidbody RB;
private DebugDrawing[] debugInfo; // For drawing force gizmos
public float percentSubmerged = 0f;
[ContextMenu("Initialize")]
void Init()
{
voxels = null;
if (_buoyancyType == BuoyancyType.NonPhysicalVoxel || _buoyancyType == BuoyancyType.PhysicalVoxel) // If voxel based we need colliders and voxels
{
SetupColliders();
SliceIntoVoxels();
samplePoints = new float3[voxels.Length];
}
if (_buoyancyType == BuoyancyType.Physical || _buoyancyType == BuoyancyType.PhysicalVoxel) // If physical, then we need a rigidbody
{
// The object must have a RidigBody
RB = GetComponent<Rigidbody>();
if (RB == null)
{
RB = gameObject.AddComponent<Rigidbody>();
Debug.LogError(string.Format("Buoyancy:Object \"{0}\" had no Rigidbody. Rigidbody has been added.", name));
}
RB.centerOfMass = centerOfMass + voxelBounds.center;
baseDrag = RB.drag;
baseAngularDrag = RB.angularDrag;
samplePoints = new float3[voxels.Length];
}
if (_buoyancyType == BuoyancyType.NonPhysical || _buoyancyType == BuoyancyType.Physical)
{
voxels = new Vector3[1];
voxels[0] = centerOfMass;
samplePoints = new float3[1];
}
float archimedesForceMagnitude = WATER_DENSITY * -Physics.gravity.y * volume;
localArchimedesForce = new Vector3(0, archimedesForceMagnitude, 0) / samplePoints.Length;
}
private void Start()
{
_guid = gameObject.GetInstanceID();
Init();
if (_buoyancyType == BuoyancyType.NonPhysical || _buoyancyType == BuoyancyType.Physical)
{
debugInfo = new DebugDrawing[1];
heights = new float3[1];// new NativeSlice<float3>();
normals = new float3[1];//new NativeSlice<float3>();
}
else
{
debugInfo = new DebugDrawing[voxels.Length];
heights = new float3[voxels.Length]; //new NativeSlice<float3>();
}
}
void SetupColliders()
{
// The object must have a Collider
colliders = GetComponentsInChildren<Collider>(false);
if (colliders.Length == 0)
{
colliders = new Collider[1];
colliders[0] = gameObject.AddComponent<BoxCollider>();
Debug.LogError(string.Format("Buoyancy:Object \"{0}\" had no coll. BoxCollider has been added.", name));
}
}
void Update()
{
for (var i = 0; i < samplePoints.Length; i++)
{
samplePoints[i] = transform.TransformPoint(voxels[i]);
}
if (_buoyancyType == BuoyancyType.PhysicalVoxel || _buoyancyType == BuoyancyType.Physical) // if acurate the are more points so only heights are needed
{
GerstnerWavesJobs.UpdateSamplePoints(samplePoints, _guid, false);
GerstnerWavesJobs.GetData(_guid, ref heights);
}
else
{
GerstnerWavesJobs.UpdateSamplePoints(samplePoints, _guid, true);
GerstnerWavesJobs.GetSimpleData(_guid, ref heights, ref normals);
if (_buoyancyType == BuoyancyType.NonPhysical)
{
Vector3 vec = transform.position;
vec.y = heights[0].y;
transform.position = vec;
transform.up = Vector3.Slerp(transform.up, normals[0], Time.deltaTime);
}
else if (_buoyancyType == BuoyancyType.NonPhysicalVoxel)
{
// do the voxel non-physical
}
}
}
private void FixedUpdate()
{
float submergedAmount = 0f;
if (_buoyancyType == BuoyancyType.PhysicalVoxel)
{
Physics.autoSyncTransforms = false;
for (var i = 0; i < voxels.Length; i++) BuoyancyForce(voxels[i], heights[i].y, ref submergedAmount, ref debugInfo[i]);
Physics.SyncTransforms();
Physics.autoSyncTransforms = true;
UpdateDrag(submergedAmount);
}
else if (_buoyancyType == BuoyancyType.Physical)
{
BuoyancyForce(Vector3.zero, heights[0].y, ref submergedAmount, ref debugInfo[0]);
UpdateDrag(submergedAmount);
}
}
private void BuoyancyForce(Vector3 position, float waterHeight, ref float submergedAmount, ref DebugDrawing _debug)
{
var wp = transform.TransformPoint(position);
float waterLevel = waterHeight;
_debug.position = wp;
_debug.waterHeight = waterLevel;
_debug.force = Vector3.zero;
if (wp.y - voxelResolution < waterLevel)
{
float k = Mathf.Clamp01(waterLevel - (wp.y - voxelResolution)) / (voxelResolution * 2f);
submergedAmount += k / voxels.Length;//(math.clamp(waterLevel - (wp.y - voxelResolution), 0f, voxelResolution * 2f) / (voxelResolution * 2f)) / voxels.Count;
var velocity = RB.GetPointVelocity(wp);
velocity.y *= 2f;
var localDampingForce = DAMPFER * RB.mass * -velocity;
var force = localDampingForce + Mathf.Sqrt(k) * localArchimedesForce;//\
RB.AddForceAtPosition(force, wp);
_debug.force = force; // For drawing force gizmos
}
}
private void UpdateDrag(float submergedAmount)
{
percentSubmerged = Mathf.Lerp(percentSubmerged, submergedAmount, 0.25f);
RB.drag = baseDrag + (baseDrag * (percentSubmerged * 10f));
RB.angularDrag = baseAngularDrag + (percentSubmerged * 0.5f);
}
private void SliceIntoVoxels()
{
Quaternion rot = transform.rotation;
Vector3 pos = transform.position;
Vector3 size = transform.localScale;
transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
transform.localScale = Vector3.one;
voxels = null;
var points = new List<Vector3>();
var rawBounds = VoxelBounds();
voxelBounds = rawBounds;
voxelBounds.size = RoundVector(rawBounds.size, voxelResolution);
for (float ix = -voxelBounds.extents.x; ix < voxelBounds.extents.x; ix += voxelResolution)
{
for (float iy = -voxelBounds.extents.y; iy < voxelBounds.extents.y; iy += voxelResolution)
{
for (float iz = -voxelBounds.extents.z; iz < voxelBounds.extents.z; iz += voxelResolution)
{
float x = (voxelResolution * 0.5f) + ix;
float y = (voxelResolution * 0.5f) + iy;
float z = (voxelResolution * 0.5f) + iz;
var p = new Vector3(x, y, z) + voxelBounds.center;
bool inside = false;
for (var i = 0; i < colliders.Length; i++)
{
if (PointIsInsideCollider(colliders[i], p))
{
inside = true;
}
}
if (inside)
points.Add(p);
}
}
}
voxels = points.ToArray();
transform.SetPositionAndRotation(pos, rot);
transform.localScale = size;
var voxelVolume = Mathf.Pow(voxelResolution, 3f) * voxels.Length;
var rawVolume = rawBounds.size.x * rawBounds.size.y * rawBounds.size.z;
volume = Mathf.Min(rawVolume, voxelVolume); //actual close to 34.637f
density = gameObject.GetComponent<Rigidbody>().mass / volume;
}
private Bounds VoxelBounds()
{
Bounds bounds = new Bounds();
foreach (Collider nextCollider in colliders)
{
bounds.Encapsulate(nextCollider.bounds);
}
return bounds;
}
static Vector3 RoundVector(Vector3 vec, float rounding)
{
return new Vector3(Mathf.Ceil(vec.x / rounding) * rounding, Mathf.Ceil(vec.y / rounding) * rounding, Mathf.Ceil(vec.z / rounding) * rounding);
}
private bool PointIsInsideCollider(Collider c, Vector3 p)
{
Vector3 cp = Physics.ClosestPoint(p, c, Vector3.zero, UnityEngine.Quaternion.identity);
return Vector3.Distance(cp, p) < 0.01f ? true : false;
}
private void OnDrawGizmosSelected()
{
const float gizmoSize = 0.05f;
var matrix = Matrix4x4.TRS(transform.position, transform.rotation, transform.lossyScale);
Gizmos.matrix = matrix;
if (voxels != null)
{
Gizmos.color = Color.yellow;
foreach (var p in voxels)
{
Gizmos.DrawCube(p, new Vector3(gizmoSize, gizmoSize, gizmoSize));
}
}
if (voxelResolution >= 0.1f)
{
Gizmos.DrawWireCube(voxelBounds.center, voxelBounds.size);
Vector3 center = voxelBounds.center;
float y = center.y - voxelBounds.extents.y;
for (float x = -voxelBounds.extents.x; x < voxelBounds.extents.x; x += voxelResolution)
{
Gizmos.DrawLine(new Vector3(x, y, -voxelBounds.extents.z + center.z), new Vector3(x, y, voxelBounds.extents.z + center.z));
}
for (float z = -voxelBounds.extents.z; z < voxelBounds.extents.z; z += voxelResolution)
{
Gizmos.DrawLine(new Vector3(-voxelBounds.extents.x, y, z + center.z), new Vector3(voxelBounds.extents.x, y, z + center.z));
}
}
else
voxelBounds = VoxelBounds();
Gizmos.color = Color.red;
Gizmos.DrawSphere(voxelBounds.center + centerOfMass, 0.2f);
Gizmos.matrix = Matrix4x4.identity; Gizmos.matrix = Matrix4x4.identity;
if (debugInfo != null)
{
foreach (DebugDrawing debug in debugInfo)
{
Gizmos.color = Color.cyan;
Gizmos.DrawCube(debug.position, new Vector3(gizmoSize, gizmoSize, gizmoSize)); // drawCenter
Vector3 water = debug.position;
water.y = debug.waterHeight;
Gizmos.DrawLine(debug.position, water); // draw the water line
Gizmos.DrawSphere(water, gizmoSize * 4f);
if (_buoyancyType == BuoyancyType.Physical || _buoyancyType == BuoyancyType.PhysicalVoxel)
{
Gizmos.color = Color.red;
Gizmos.DrawRay(debug.position, debug.force / RB.mass); // draw force
}
}
}
}
//Will be called by the PhysicsConversionSystem
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
Init();
BuoyantData data = new BuoyantData();
data.type = _buoyancyType;
data.voxelResolution = voxelResolution;
data.localArchimedesForce = localArchimedesForce;
data.percentSubmerged = 0f;
data.baseDrag = baseDrag;
data.baseAngularDrag = baseAngularDrag;
dstManager.AddComponentData(entity, data);
dstManager.AddBuffer<VoxelOffset>(entity);
dstManager.AddBuffer<VoxelHeight>(entity);
var mass = dstManager.GetComponentData<Unity.Physics.PhysicsMass>(entity);
mass.CenterOfMass = centerOfMass;
dstManager.SetComponentData(entity, mass);
DynamicBuffer<VoxelOffset> offsets = dstManager.GetBuffer<VoxelOffset>(entity);
DynamicBuffer<VoxelHeight> heights = dstManager.GetBuffer<VoxelHeight>(entity);
for (int i = 0; i < voxels.Length; i++)
{
offsets.Add(new VoxelOffset { Value = voxels[i] - centerOfMass });// transform.TransformPoint(voxels[i]) - transform.position }); // << Is this right?
heights.Add(new VoxelHeight { Value = float3.zero });
}
//Call other Convert methods
var body = GetComponentInChildren<BoatBodyComponent>();
body.Convert(conversionSystem.GetPrimaryEntity(body), dstManager, conversionSystem);
var engine = GetComponent<Engine>();
engine.Convert(conversionSystem.GetPrimaryEntity(engine), dstManager, conversionSystem);
}
struct DebugDrawing
{
public Vector3 force;
public Vector3 position;
public float waterHeight;
}
public enum BuoyancyType
{
NonPhysical,
NonPhysicalVoxel,
Physical,
PhysicalVoxel
}
}
}

11
Assets/Unity Physics Items/Components/BoatDataComponents.cs.meta


fileFormatVersion: 2
guid: 5cd1fa5899494974698ae65f8dd12273
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

33
Assets/Unity Physics Items/Components/BoatDataComponents.cs


using Unity.Entities;
using Unity.Mathematics;
using static WaterSystem.BuoyantObject_DOTS;
public struct BuoyantData : IComponentData
{
public BuoyancyType type;
public float voxelResolution;
public float3 normal;
public float3 localArchimedesForce;
public float percentSubmerged;
public float baseDrag;
public float baseAngularDrag;
}
public struct VoxelOffset : IBufferElementData
{
public float3 Value;
}
public struct VoxelHeight : IBufferElementData
{
public float3 Value;
}
public struct DrivingData : IComponentData
{
public bool isHuman;
public float torque;
public float horsePower;
public float3 engineOffset;
public float throttle;
public float steering;
}

1001
Assets/Unity Physics Items/Physics Scene.unity
文件差异内容过多而无法显示
查看文件

7
Assets/Unity Physics Items/Prefabs/BoatEntity.prefab.meta


fileFormatVersion: 2
guid: 0a308b87c1579fb4c9ea256406209ca5
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

88
Assets/Unity Physics Items/Prefabs/Physics Settings.prefab


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &6698997538611213016
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4018593011617785703}
- component: {fileID: 1925807081182823211}
- component: {fileID: 6001476266129338508}
- component: {fileID: 4712718218339362870}
m_Layer: 0
m_Name: Physics Settings
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4018593011617785703
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6698997538611213016}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -81.26014, y: -1.9031935, z: -21.097088}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1925807081182823211
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6698997538611213016}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4d30974bf68d61043b1572197db94cdc, type: 3}
m_Name:
m_EditorClassIdentifier:
SimulationType: 1
Gravity:
x: -0
y: -9.81
z: -0
SolverIterationCount: 4
ThreadCountHint: 8
--- !u!114 &6001476266129338508
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6698997538611213016}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ea7d7495833204790ba1d3a8755397f8, type: 3}
m_Name:
m_EditorClassIdentifier:
ConversionMode: 0
--- !u!114 &4712718218339362870
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6698997538611213016}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bb54ea4f67dc17342bcd49954c53502d, type: 3}
m_Name:
m_EditorClassIdentifier:
DrawColliders: 1
DrawColliderEdges: 0
DrawColliderAabbs: 0
DrawBroadphase: 0
DrawMassProperties: 1
DrawContacts: 0
DrawCollisionEvents: 0
DrawTriggerEvents: 0
DrawJoints: 0

7
Assets/Unity Physics Items/Prefabs/Physics Settings.prefab.meta


fileFormatVersion: 2
guid: ebb958ca9e119be438b62f3cce1981fc
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Unity Physics Items/Prefabs/Slippery.asset.meta


fileFormatVersion: 2
guid: 15aa0e33a6fa41749b19f36537af1280
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

42
Assets/Unity Physics Items/Prefabs/Slippery.asset


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
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: 79f877434772c463192af154345455c9, type: 3}
m_Name: Slippery
m_EditorClassIdentifier:
m_Value:
m_SupportsTemplate: 0
m_Template: {fileID: 0}
m_IsTrigger:
m_Override: 1
m_Value: 0
m_Friction:
m_Override: 1
m_Value:
Value: 0
CombineMode: 0
m_Restitution:
m_Override: 1
m_Value:
Value: 0
CombineMode: 0
m_BelongsTo:
m_Override: 1
m_Value: 0101010101010101010101010101010101010101010101010101010101010101
m_CollidesWith:
m_Override: 1
m_Value: 0101010101010101010101010101010101010101010101010101010101010101
m_RaisesCollisionEvents:
m_Override: 1
m_Value: 0
m_CustomTags:
m_Override: 1
m_Value: 0000000000000000

146
Assets/Unity Physics Items/Prefabs/AIBoatEntity Variant.prefab


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &2478739796189504339
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 3457973740146875416, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_Name
value: BoatEntity
objectReference: {fileID: 0}
- target: {fileID: 3457973740146875416, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3457973740146875417, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalPosition.x
value: -78.9
objectReference: {fileID: 0}
- target: {fileID: 3457973740146875417, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3457973740146875417, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalPosition.z
value: -20
objectReference: {fileID: 0}
- target: {fileID: 3457973740146875417, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 3457973740146875417, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalRotation.y
value: 0.95782626
objectReference: {fileID: 0}
- target: {fileID: 3457973740146875417, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 3457973740146875417, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalRotation.w
value: 0.28734788
objectReference: {fileID: 0}
- target: {fileID: 3457973740146875417, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_RootOrder
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3457973740146875417, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3457973740146875417, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3457973740146875417, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6727757724182940452, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: PrimaryColor.r
value: 0.7434182
objectReference: {fileID: 0}
- target: {fileID: 6727757724182940452, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: PrimaryColor.g
value: 0.7434182
objectReference: {fileID: 0}
- target: {fileID: 6727757724182940452, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: PrimaryColor.b
value: 0.7434182
objectReference: {fileID: 0}
- target: {fileID: 6727757724182940452, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: TrimColor.r
value: 0.025658185
objectReference: {fileID: 0}
- target: {fileID: 6727757724182940452, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: TrimColor.g
value: 0.15348418
objectReference: {fileID: 0}
- target: {fileID: 6727757724182940452, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: TrimColor.b
value: 0.25658178
objectReference: {fileID: 0}
- target: {fileID: 6727757724182940452, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: Human
value: 0
objectReference: {fileID: 0}
- target: {fileID: 320792261470743900, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 558137786967539335, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalRotation.x
value: 0.09853761
objectReference: {fileID: 0}
- target: {fileID: 558137786967539335, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalRotation.y
value: -0.0000002682209
objectReference: {fileID: 0}
- target: {fileID: 558137786967539335, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalRotation.z
value: -0.00000011175871
objectReference: {fileID: 0}
- target: {fileID: 558137786967539335, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalPosition.z
value: -5
objectReference: {fileID: 0}
- target: {fileID: 558137786967539335, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalPosition.x
value: 0.0000026226044
objectReference: {fileID: 0}
- target: {fileID: 558137786967539335, guid: 0a308b87c1579fb4c9ea256406209ca5,
type: 3}
propertyPath: m_LocalRotation.w
value: 0.99513334
objectReference: {fileID: 0}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 0a308b87c1579fb4c9ea256406209ca5, type: 3}

7
Assets/Unity Physics Items/Prefabs/AIBoatEntity Variant.prefab.meta


fileFormatVersion: 2
guid: c48ad8112d3b604478deaa848d47c861
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

1001
Assets/Unity Physics Items/Prefabs/BoatEntity.prefab
文件差异内容过多而无法显示
查看文件

11
Assets/Unity Physics Items/Systems/ApplyBuoyancyForceSystem.cs.meta


fileFormatVersion: 2
guid: 6387e875988aca64a81560a89e9386ee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Assets/Unity Physics Items/Systems/DriveSystem.cs.meta


fileFormatVersion: 2
guid: 0bb75e9b16d3ccf46b42eb1f80cc44b2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Assets/Unity Physics Items/Systems/GertsnerSystem.cs.meta


fileFormatVersion: 2
guid: 54405482a57114844800f64f212d201a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Assets/Unity Physics Items/Systems/PhysicsConversionSystem.cs.meta


fileFormatVersion: 2
guid: 4237fdf5d806beb4388f07fdbdbafe70
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

127
Assets/Unity Physics Items/Systems/GertsnerSystem.cs


using System.Collections;
using System.Collections.Generic;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics.Authoring;
using Unity.Transforms;
using UnityEngine;
using WaterSystem;
using WaterSystem.Data;
public class GertsnerSystem : JobComponentSystem
{
private int _waveCount;
private NativeArray<Wave> waveData;
protected override void OnCreate()
{
_waveCount = Water.Instance._waves.Length;
waveData = new NativeArray<Wave>(_waveCount, Allocator.Persistent);
for (var i = 0; i < waveData.Length; i++)
{
waveData[i] = Water.Instance._waves[i];
}
base.OnCreate();
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var job = new HeightJob {
waveData = waveData,
time = Time.deltaTime,
offsetBuffer = GetBufferFromEntity<VoxelOffset>(false),
heightBuffer = GetBufferFromEntity<VoxelHeight>(false)
};
return job.Schedule(this, inputDeps);
}
[BurstCompile]
public struct HeightJob : IJobForEachWithEntity<Translation, BuoyantData>
{
[ReadOnly]
public NativeArray<Wave> waveData; // wave data stroed in vec4's like the shader version but packed into one
[ReadOnly]
public float time;
[ReadOnly]
public BufferFromEntity<VoxelOffset> offsetBuffer;
[NativeDisableParallelForRestriction]
public BufferFromEntity<VoxelHeight> heightBuffer;
// The code actually running on the job
public void Execute(Entity entity, int i, [ReadOnly] ref Translation translation, ref BuoyantData data)
{
DynamicBuffer<VoxelOffset> offsets = offsetBuffer[entity];
DynamicBuffer<VoxelHeight> heights = heightBuffer[entity];
for (int vi = 0; vi < offsets.Length; vi++)
{
float3 voxelPos = translation.Value + offsets[vi].Value;
var waveCountMulti = 1f / waveData.Length;
float3 wavePos = new float3(0f, 0f, 0f);
float3 waveNorm = new float3(0f, 0f, 0f);
for (var wave = 0; wave < waveData.Length; wave++) // for each wave
{
// Wave data vars
var pos = new float2(voxelPos.x, voxelPos.z);
var amplitude = waveData[wave].amplitude;
var direction = waveData[wave].direction;
var wavelength = waveData[wave].wavelength;
var omniPos = waveData[wave].origin;
////////////////////////////////wave value calculations//////////////////////////
var w = 6.28318f / wavelength; // 2pi over wavelength(hardcoded)
var wSpeed = math.sqrt(9.8f * w); // frequency of the wave based off wavelength
var peak = 0.8f; // peak value, 1 is the sharpest peaks
var qi = peak / (amplitude * w * waveData.Length);
var windDir = new float2(0f, 0f);
var dir = 0f;
direction = math.radians(direction); // convert the incoming degrees to radians
var windDirInput = new float2(math.sin(direction), math.cos(direction)) * (1 - waveData[wave].onmiDir); // calculate wind direction - TODO - currently radians
var windOmniInput = (pos - omniPos) * waveData[wave].onmiDir;
windDir += windDirInput;
windDir += windOmniInput;
windDir = math.normalize(windDir);
dir = math.dot(windDir, pos - (omniPos * waveData[wave].onmiDir)); // calculate a gradient along the wind direction
////////////////////////////position output calculations/////////////////////////
var calc = dir * w + -time * wSpeed; // the wave calculation
var cosCalc = math.cos(calc); // cosine version(used for horizontal undulation)
var sinCalc = math.sin(calc); // sin version(used for vertical undulation)
// calculate the offsets for the current point
wavePos.x += qi * amplitude * windDir.x * cosCalc;
wavePos.z += qi * amplitude * windDir.y * cosCalc;
wavePos.y += ((sinCalc * amplitude)) * waveCountMulti; // the height is divided by the number of waves
if (offsets.Length == 1)
{
////////////////////////////normal output calculations/////////////////////////
float wa = w * amplitude;
// normal vector
float3 norm = new float3(-(windDir.xy * wa * cosCalc),
1 - (qi * wa * sinCalc));
waveNorm += (norm * waveCountMulti) * amplitude;
}
}
heights[vi] = new VoxelHeight{Value = wavePos};
if (offsets.Length == 1)
data.normal = math.normalize(waveNorm.xzy);
}
}
}
}

21
Assets/Unity Physics Items/Systems/PhysicsConversionSystem.cs


using Unity.Entities;
using UnityEngine;
using WaterSystem;
namespace Unity.Physics.Authoring
{
// IConvertGameObjectToEntity pipeline is called before the Physics Body & Shape Conversion Systems
// This means that there would be no Physics components created when Convert was called.
// Instead Convert is called from this specific ConversionSystem for any component that may need
// to read or write the various Physics components at conversion time.
[UpdateAfter(typeof(PhysicsBodyConversionSystem))]
[UpdateAfter(typeof(LegacyRigidbodyConversionSystem))]
public class PhysicsConversionSystem : GameObjectConversionSystem
{
// Update is called once per frame
protected override void OnUpdate()
{
Entities.ForEach((BuoyantObject_DOTS behaviour) => { behaviour.Convert(GetPrimaryEntity(behaviour), DstEntityManager, this); });
}
}
}

96
Assets/Unity Physics Items/Systems/ApplyBuoyancyForceSystem.cs


using System.Collections;
using System.Collections.Generic;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
using static WaterSystem.BuoyantObject_DOTS;
using Unity.Physics.Extensions;
using Unity.Physics.Systems;
using Unity.Physics;
[UpdateAfter(typeof(GertsnerSystem)), UpdateBefore(typeof(BuildPhysicsWorld))]
public class ApplyBuoyancyForceSystem : JobComponentSystem
{
float lastTime = 0;
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
//Debug.Log(string.Format("DeltaTime: {0}, Time.time {1}, Calc Delta: {2}", Time.deltaTime, Time.time, Time.time - lastTime));
//lastTime = Time.time;
var job = new ForceJob()
{
dt = Time.deltaTime,
offsetBuffer = GetBufferFromEntity<VoxelOffset>(false),
heightBuffer = GetBufferFromEntity<VoxelHeight>(false)
};
return job.Schedule(this, inputDeps);
}
//[BurstCompile]
public struct ForceJob : IJobForEachWithEntity<Translation, Rotation, PhysicsVelocity, PhysicsMass, PhysicsDamping, BuoyantData>
{
public float dt;
[ReadOnly]
public BufferFromEntity<VoxelOffset> offsetBuffer;
[ReadOnly]
public BufferFromEntity<VoxelHeight> heightBuffer;
public void Execute(Entity entity, int index, ref Translation pos, ref Rotation rot, ref PhysicsVelocity vel, ref PhysicsMass mass, ref PhysicsDamping damping, ref BuoyantData data)
{
DynamicBuffer<VoxelOffset> offsets = offsetBuffer[entity];
DynamicBuffer<VoxelHeight> heights = heightBuffer[entity];
float submergedAmount = 0f;
//Debug.Log("new pass: " + entity.ToString());
float avgHeight = 0;
int total = 0;
var entityTransform = new RigidTransform(rot.Value, pos.Value);
//Apply buoyant force
for (var i = 0; i < offsets.Length; i++)
{
var wp = math.transform(entityTransform, offsets[i].Value);
float waterLevel = heights[i].Value.y;
if (wp.y - data.voxelResolution < waterLevel)
{
//float depth = waterLevel - wp.y + (data.voxelResolution * 2f);
float subFactor = Mathf.Clamp01((waterLevel - (wp.y - data.voxelResolution)) / (data.voxelResolution * 2f));//depth / data.voxelResolution);
submergedAmount += subFactor / offsets.Length;//(math.clamp(waterLevel - (wp.y - voxelResolution), 0f, voxelResolution * 2f) / (voxelResolution * 2f)) / voxels.Count;
//var force2 = data.localArchimedesForce * subFactor;
var velocity = ComponentExtensions.GetLinearVelocity(vel, mass, pos, rot, wp);
velocity.y *= 2f;
var localDampingForce = .005f * math.rcp(mass.InverseMass) * -velocity;
var force = localDampingForce + math.sqrt(subFactor) * data.localArchimedesForce;//\
ComponentExtensions.ApplyImpulse(ref vel, mass, pos, rot, force * dt, wp);
//entity.ApplyImpulse(force, wp);//RB.AddForceAtPosition(force, wp);
avgHeight += force.y;
total++;
//Debug.Log(string.Format("ECS: Position: {0:f1} -- Force: {1:f2} -- Height: {2:f2}\nVelocty: {3:f2} -- Damp: {4:f2} -- Mass: {5:f1} -- K: {6:f2}", wp, force, waterLevel, velocity, localDampingForce, math.rcp(mass.InverseMass), dt));
}
}
//Update drag
// Debug.Log("Average height: " + avgHeight / total);
//submergedAmount /= offsets.Length;
//damping.Linear = Mathf.Lerp(data.baseDrag, 1f, submergedAmount);
//damping.Angular = Mathf.Lerp(data.baseAngularDrag, 1f, submergedAmount);
data.percentSubmerged = Mathf.Lerp(data.percentSubmerged, submergedAmount, 0.25f);
damping.Linear = data.baseDrag + (data.baseDrag * (data.percentSubmerged * 10f));
damping.Angular = data.baseAngularDrag + (data.percentSubmerged * 0.5f);
}
}
}

68
Assets/Unity Physics Items/Systems/DriveSystem.cs


using System.Collections;
using System.Collections.Generic;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics;
using Unity.Physics.Extensions;
using Unity.Transforms;
using UnityEngine;
[UpdateAfter(typeof(ApplyBuoyancyForceSystem))]
public class DriveSystem : JobComponentSystem
{
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var job = new DriveWithInputJob()
{
dt = Time.deltaTime,
};
return job.Schedule(this, inputDeps);
}
[BurstCompile]
public struct DriveWithInputJob : IJobForEachWithEntity<Translation, Rotation, PhysicsVelocity, PhysicsMass, DrivingData>
{
public float dt;
public void Execute(Entity entity, int index, [ReadOnly] ref Translation pos, [ReadOnly] ref Rotation rot, ref PhysicsVelocity vel, [ReadOnly] ref PhysicsMass mass, ref DrivingData data)
{
float velMag = math.dot(vel.Linear, vel.Linear);
var wp = pos.Value + data.engineOffset;
//if (wp.y <= -0.1f) // if the engine is deeper than 0.1
//{
//accel
data.throttle = Mathf.Clamp(data.throttle, 0f, 1f); // clamp for reasonable values
float3 forward = math.forward(rot.Value);
forward.y = 0f;
forward = math.normalize(forward);
var force = (forward * data.throttle * data.horsePower) / mass.InverseMass; //divide by iMass to counteract mass in impulse method
var torque = (data.throttle * new float3(-1, 0, 0)) / mass.InverseInertia;
float3 up = math.mul(rot.Value, math.up());
ComponentExtensions.ApplyLinearImpulse(ref vel, mass, force * dt);
ComponentExtensions.ApplyLinearImpulse(ref vel, mass, up * 20000f * dt);
//ComponentExtensions.ApplyAngularImpulse(ref vel, mass, torque * dt);
//RB.AddForce(forward * modifier * horsePower, ForceMode.Acceleration); // add force forward based on input and horsepower
//RB.AddRelativeTorque(-Vector3.right * modifier, ForceMode.Acceleration);
//Turning
data.steering = Mathf.Clamp(data.steering, -1f, 1f); // clamp for reasonable values
var sTorque = new float3(0f, data.torque, -data.torque * .5f) * data.steering / mass.InverseInertia;
ComponentExtensions.ApplyAngularImpulse(ref vel, mass, sTorque * dt);
//Debug.Log(string.Format("Force: {0}, Torque: {1} Throttle: {2}", force, sTorque, throttle));
//RB.AddRelativeTorque(new Vector3(0f, torque, -torque * 0.5f) * modifier, ForceMode.Acceleration); // add torque based on input and torque amount
//}
}
}
}

54
Assets/Unity Physics Items/Systems/InputSystem.cs


using BoatAttack;
using System.Collections;
using System.Collections.Generic;
using Unity.Entities;
using Unity.Transforms;
using UnityEngine;
[UpdateBefore(typeof(DriveSystem))]
public class InputSystem : ComponentSystem
{
InputControls controls;
float throttle;
float steering;
float startTime;
protected override void OnCreate()
{
startTime = Time.time + WaypointGroup.raceDelay;
controls = new InputControls();
controls.BoatControls.Trottle.performed += context => throttle = context.ReadValue<float>();
controls.BoatControls.Trottle.canceled += context => throttle = 0f;
controls.BoatControls.Steering.performed += context => steering = context.ReadValue<float>();
controls.BoatControls.Steering.canceled += context => steering = 0f;
controls.BoatControls.Enable();
base.OnCreate();
}
protected override void OnUpdate()
{
//not time to start
if (Time.time < startTime)
return;
Entities.ForEach((Entity entity, ref Translation pos, ref Rotation rot, ref DrivingData data ) =>
{
if (data.isHuman)
{
data.throttle = throttle;
data.steering = steering;
}
else
{
AIController_DOTS.GetInputs(entity, pos.Value, rot.Value, out data.throttle, out data.steering);
}
});
}
}

11
Assets/Unity Physics Items/Systems/InputSystem.cs.meta


fileFormatVersion: 2
guid: b8a5f3eb75380dc4b8e643111843c4e9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Assets/Unity Physics Items/BoatBodyComponent.cs.meta


fileFormatVersion: 2
guid: 80b5230fc040dc24a87a4b4792d30957
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

176
Packages/com.unity.entities@0.0.12-preview.33/CHANGELOG.md


# Change log
## [0.0.12-preview.33] - 2019-05-24
### New Features
* `[DisableAutoCreation]` can now apply to entire assemblies, which will cause all systems contained within to be excluded from automatic system creation. Useful for test assemblies.
* Added `ComponentSystemGroup.RemoveSystemFromUpdateList()`
* `EntityCommandBuffer` has commands for adding/removing components, deleting entities and adding shared components based on an EntityQuery and its filter. Not available in the `Concurrent` version
### Changes
* Generic component data types must now be registered in advance. Use [RegisterGenericComponentType] attribute to register each concrete use. e.g. `[assembly: RegisterGenericComponentType(typeof(TypeManagerTests.GenericComponent<int>))]`
* Attempting to call `Playback()` more than once on the same EntityCommandBuffer will now throw an error.
* Improved error checking for `[UpdateInGroup]`, `[UpdateBefore]`, and `[UpdateAfter]` attributes
* TypeManager no longer imposes alignment requirements on components containing pointers. Instead, it now throws an exception if you try to serialize a blittable component containing an unmanaged pointer, which suggests different alternatives.
### Fixes
* Fixed regression where accessing and destroying a blob asset in a burst job caused an exception
* Fixed bug where entities with manually specified `CompositeScale` were not updated by `TRSLocalToWorldSystem`.
* Error message when passing in invalid parameters to CreateSystem() is improved.
* Fixed bug where an exception due to aggressive pointer restrictions could leave the `TypeManager` in an invalid state
* SceneBoundingVolume is now generated seperately for each subsection
* SceneBoundingVolume no longer throws exceptions in conversion flow
* Fixed regression where calling AddComponent(NativeArray<Entity> entities, ComponentType componentType) could cause a crash.
## [0.0.12-preview.32] - 2019-05-16
### New Features
* Added BlobBuilder which is a new API to build Blob Assets that does not require preallocating one contiguous block of memory. The BlobAllocator is now marked obsolete.
* Added versions of `IJobForEach` that support `DynamicBuffer`s
* Due to C# language constraints, these overloads needed different names. The format for these overloads follows the following structure:
* All job names begin with either `IJobForEach` or `IJobForEachEntity`
* All jobs names are then followed by an underscore `_` and a combination of letter corresponding to the parameter types of the job
* `B` - `IBufferElementData`
* `C` - `IComponentData`
* `E` - `Entity` (`IJobForEachWithEntity` only)
* All suffixes for `WithEntity` jobs begin with `E`
* All data types in a suffix are in alphabetical order
* Here is the complete list of overloads:
* `IJobForEach_C`, `IJobForEach_CC`, `IJobForEach_CCC`, `IJobForEach_CCCC`, `IJobForEach_CCCCC`, `IJobForEach_CCCCCC`
* `IJobForEach_B`, `IJobForEach_BB`, `IJobForEach_BBB`, `IJobForEach_BBBB`, `IJobForEach_BBBBB`, `IJobForEach_BBBBBB`
* `IJobForEach_BC`, `IJobForEach_BCC`, `IJobForEach_BCCC`, `IJobForEach_BCCCC`, `IJobForEach_BCCCCC`, `IJobForEach_BBC`, `IJobForEach_BBCC`, `IJobForEach_BBCCC`, `IJobForEach_BBCCCC`, `IJobForEach_BBBC`, `IJobForEach_BBBCC`, `IJobForEach_BBBCCC`, `IJobForEach_BBBCCC`, `IJobForEach_BBBBC`, `IJobForEach_BBBBCC`, `IJobForEach_BBBBBC`
* `IJobForEachWithEntity_EB`, `IJobForEachWithEntity_EBB`, `IJobForEachWithEntity_EBBB`, `IJobForEachWithEntity_EBBBB`, `IJobForEachWithEntity_EBBBBB`, `IJobForEachWithEntity_EBBBBBB`
* `IJobForEachWithEntity_EC`, `IJobForEachWithEntity_ECC`, `IJobForEachWithEntity_ECCC`, `IJobForEachWithEntity_ECCCC`, `IJobForEachWithEntity_ECCCCC`, `IJobForEachWithEntity_ECCCCCC`
* `IJobForEachWithEntity_BC`, `IJobForEachWithEntity_BCC`, `IJobForEachWithEntity_BCCC`, `IJobForEachWithEntity_BCCCC`, `IJobForEachWithEntity_BCCCCC`, `IJobForEachWithEntity_BBC`, `IJobForEachWithEntity_BBCC`, `IJobForEachWithEntity_BBCCC`, `IJobForEachWithEntity_BBCCCC`, `IJobForEachWithEntity_BBBC`, `IJobForEachWithEntity_BBBCC`, `IJobForEachWithEntity_BBBCCC`, `IJobForEachWithEntity_BBBCCC`, `IJobForEachWithEntity_BBBBC`, `IJobForEachWithEntity_BBBBCC`, `IJobForEachWithEntity_BBBBBC`
* Note that you can still use `IJobForEach` and `IJobForEachWithEntity` as before if you're using only `IComponentData`.
* EntityManager.SetEnabled API automatically enables & disables an entity or set of entities. If LinkedEntityGroup is present the whole group is enabled / disabled. Inactive game objects automatically get a LinkedEntityGroup added so that EntityManager.SetEnabled works as expected out of the box.
* Add `WithAnyReadOnly` and `WithAllReadyOnly` methods to EntityQueryBuilder to specify queries that filter on components with access type ReadOnly.
* No longer throw when the same type is in a WithAll and ForEach delegate param for ForEach queries.
* `DynamicBuffer` CopyFrom method now supports another DynamicBuffer as a parameter.
* Fixed cases that would not be handled correctly by the api updater.
### Upgrade guide
* Usages of BlobAllocator will need to be changed to use BlobBuilder instead. The API is similar but Allocate now returns the data that can be populated:
```csharp
ref var root = ref builder.ConstructRoot<MyData>();
var floatArray = builder.Allocate(3, ref root.floatArray);
floatArray[0] = 0; // root.floatArray[0] can not be used and will throw on access
```
* ISharedComponentData with managed fields must implement IEquatable and GetHashCode
* IComponentData and ISharedComponentData implementing IEquatable must also override GetHashCode
### Fixes
* Comparisons of managed objects (e.g. in shared components) now work as expected
* Prefabs referencing other prefabs are now supported in game object entity conversion process
* Fixed a regression where ComponentDataProxy was not working correctly on Prefabs due to a ordering issue.
* Exposed GameObjectConversionDeclarePrefabsGroup for declaring prefab references. (Must happen before any conversion systems run)
* Inactive game objects are automatically converted to be Disabled entities
* Disabled components are ignored during conversion process. Behaviour.Enabled has no direct mapping in ECS. It is recommended to Disable whole entities instead
* Warnings are now issues when asking for a GetPrimaryEntity that is not a game object that is part of the converted group. HasPrimaryEntity can be used to check if the game object is part of the converted group in case that is necessary.
* Fixed a race condition in `EntityCommandBuffer.AddBuffer()` and `EntityCommandBuffer.SetBuffer()`
## [0.0.12-preview.31] - 2019-05-01
### New Features
### Upgrade guide
* Serialized entities file format version has changed, Sub Scenes entity caches will require rebuilding.
### Changes
* Adding components to entities that already have them is now properly ignored in the cases where no data would be overwritten. That means the inspectable state does not change and thus determinism can still be guaranteed.
* Restored backwards compatibility for `ForEach` API directly on `ComponentSystem` to ease people upgrading to the latest Unity.Entities package on top of Megacity.
* Rebuilding the entity cache files for sub scenes will now properly request checkout from source control if required.
### Fixes
* `IJobForEach` will only create new entity queries when scheduled, and won't rely on injection anymore. This avoids the creation of useless queries when explicit ones are used to schedule those jobs. Those useless queries could cause systems to keep updating even though the actual queries were empty.
* APIs changed in the previous version now have better obsolete stubs and upgrade paths. All obsolete APIs requiring manual code changes will now soft warn and continue to work, instead of erroring at compile time. These respective APIs will be removed in a future release after that date.
* LODGroup conversion now handles renderers being present in a LOD Group in multipe LOD levels correctly
* Fixed potential memory leak when disposing an EntityCommandBuffer after certain types of playback errors
* Fixed an issue where chunk utilization histograms weren't properly clipped in EntityDebugger
* Fixed an issue where tag components were incorrectly shown as subtractive in EntityDebugger
* ComponentSystem.ShouldRunSystem() exception message now more accurately reports the most likely reason for the error when the system does not exist.
### Known Issues
* It might happen that shared component data with managed references is not compared for equality correctly with certain profiles.
## [0.0.12-preview.30] - 2019-04-05
### New Features
Script templates have been added to help you create new component types and systems, similar to Unity's built-in template for new MonoBehaviours. Use them via the Assets/Create/ECS menu.
### Upgrade guide
Some APIs have been deprecated in this release:
[API Deprecation FAQ](https://forum.unity.com/threads/api-deprecation-faq-0-0-23.636994/)
** Removed obsolete ComponentSystem.ForEach
** Removed obsolete [Inject]
** Removed obsolete ComponentDataArray
** Removed obsolete SharedComponentDataArray
** Removed obsolete BufferArray
** Removed obsolete EntityArray
** Removed obsolete ComponentGroupArray
####ScriptBehaviourManager removal
* The ScriptBehaviourManager class has been removed.
* ComponentSystem and JobComponentSystem remain as system base classes (with a common ComponentSystemBase class)
* ComponentSystems have overridable methods OnCreateManager and OnDestroyManager. These have been renamed to OnCreate and OnDestroy.
* This is NOT handled by the obsolete API updater and will need to be done manually.
* The old OnCreateManager/OnDestroyManager will continue to work temporarily, but will print a warning if a system contains them.
* World APIs have been updated as follows:
* CreateManager, GetOrCreateManager, GetExistingManager, DestroyManager, BehaviourManagers have been renamed to CreateSystem, GetOrCreateSystem, GetExistingSystem, DestroySystem, Systems.
* These should be handled by the obsolete API updater.
* EntityManager is no longer accessed via GetExistingManager. There is now a property directly on World: World.EntityManager.
* This is NOT handled by the obsolete API updater and will need to be done manually.
* Searching and replacing Manager<EntityManager> should locate the right spots. For example, world.GetExistingManager<EntityManager>() should become just world.EntityManager.
#### IJobProcessComponentData renamed to IJobForeach
This rename unfortunately cannot be handled by the obsolete API updater.
A global search and replace of IJobProcessComponentData to IJobForEach should be sufficient.
#### ComponentGroup renamed to EntityQuery
ComponentGroup has been renamed to EntityQuery to better represent what it does.
All APIs that refer to ComponentGroup have been changed to refer to EntityQuery in their name, e.g. CreateEntityQuery, GetEntityQuery, etc.
#### EntityArchetypeQuery renamed to EntityQueryDesc
EntityArchetypeQuery has been renamed to EntityQueryDesc
### Changes
* Minimum required Unity version is now 2019.1.0b9
* Adding components to entities that already have them is now properly ignored in the cases where no data would be overwritten.
* UNITY_CSHARP_TINY is now NET_DOTS to match our other NET_* defines
### Fixes
* Fixed exception in inspector when Script is missing
* The presence of chunk components could lead to corruption of the entity remapping during deserialization of SubScene sections.
* Fix for an issue causing filtering with IJobForEachWithEntity to try to access entities outside of the range of the group it was scheduled with.
<!-- Template for version sections
## [0.0.0-preview.0]
### New Features
### Upgrade guide
### Changes
### Fixes
-->

7
Packages/com.unity.entities@0.0.12-preview.33/CHANGELOG.md.meta


fileFormatVersion: 2
guid: 77ec343c3667943c189e1bceeff600ce
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

28
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/TableOfContents.md


<!-- Generated from ../Samples/Packages/com.unity.entities/Documentation~/toc.yml do not edit. -->
* [Overview](index.md)
* Core ECS
* [Entities](ecs_entities.md)
* [Worlds](world.md)
* [Components](ecs_components.md)
* [General Purpose Components](component_data.md)
* [Shared Components](shared_component_data.md)
* [System State Components](system_state_components.md)
* [Dynamic Buffer Components](dynamic_buffers.md)
* [System](ecs_systems.md)
* [Component Systems](component_system.md)
* [Job Component Systems](job_component_system.md)
* [Entity Command Buffers](entity_command_buffer.md)
* [System Update Order](system_update_order.md)
* [Accessing Entity Data](chunk_iteration.md)
* [Using IJobForEach](entity_iteration_job.md)
* [Using IJobChunk](chunk_iteration_job.md)
* [Using ComponentSystem and ForEach](entity_iteration_foreach.md)
* [Manual iteration](manual_iteration.md)
* [Component Groups](component_group.md)
* [Component WriteGroups](ecs_write_groups.md)
* [Versions and Generations](version_numbers.md)
* [Jobs in ECS](ecs_job_overview.md)
* [ECS Job System extensions](ecs_job_extensions.md)
* Creating Gameplay
* [Transforms](transform_system.md)
* [Rendering](gp_rendering.md)

22
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/chunk_iteration.md


---
uid: ecs-iteration
---
# Accessing entity data
Iterating over your data is one of the most common tasks you will perform when implementing an ECS system. ECS systems typically process a set of entities, reading data from one or more components, performing a calculation, and then writing the result to another component.
In general, the most efficient way to iterate over your entities and components is in a parallelizable Job that processes the components in order. This takes advantage of processing power from all available cores and data locality to avoid CPU cache misses.
The ECS API provides a number of ways to accomplish iteration, each with its own performance implications and restrictions. You can iterate over ECS data in the following ways:
* [IJobForEach](entity_iteration_job.md) — the simplest efficient way to process component data entity by entity.
* [IJobForEachWithEntity](entity_iteration_job.md#with-entity) — slightly more complex than IJobForEach, giving you access to the entity handle and array index of the entity you are processing.
* [IJobChunk](chunk_iteration_job.md) — iterates over the eligible blocks of memory (called a *Chunk*) containing matching entities. Your Job Execute() function can iterate over the Elements inside each chunk using a for loop. You can use IJobChunk for more complex situations than supported by IJobForEach, while maintaining maximum efficiency.
* [ComponentSystem](entity_iteration_foreach.md) — the ComponentSystem offers the Entities.ForEach delegate functions to help iterate over your entities. However, ForEach runs on the main thread, so typically, you should only use ComponentSystem implementations for tasks that must be carried out on the main thread anyway.
* [Manual iteration](manual_iteration.md) — if the previous methods are insufficient, you can manually iterate over entities or chunks. For example, you can get a NativeArray containing entities or the chunks of the entities that you want to process and iterate over them using a Job, such as IJobParallelFor.
The [EntityQuery](component_group.md) class provides a way to construct a view of your data that contains only the specific data you need for a given algorithm or process. Many of the iteration methods in the list above use a EntityQuery, either explicitly or internally.

219
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/chunk_iteration_job.md


# Using IJobChunk
You can implement IJobChunk inside a JobComponentSystem to iterate through your data by chunk. The JobComponentSystem calls your Execute() function once for each chunk that contains the entities that you want the system to process. You can then process the data inside each chunk, entity by entity.
Iterating with IJobChunk requires more code setup than does IJobForEach, but is also more explicit and represents the most direct access to the data, as it is actually stored.
Another benefit of using iterating by chunks is that you can check whether an optional component is present in each chunk (with Archetype.Has<T>) and process all the entities in the chunk accordingly.
The steps involved in implementing an IJobChunk Job include:
1. Identify the entities that you want to process by creating a EntityQuery.
2. Defining the Job struct, including fields for ArchetypeChunkComponentType objects to identifying the types of components the Job directly accesses, specifying whether the Job reads or writes to those components.
3. Instantiating the Job struct and scheduling the Job in the system OnUpdate() function.
4. In the Execute() function, getting the NativeArray instances for the components the Job reads or writes and, finally, iterating over the current chunk to perform the desired work.
The [ECS samples repository](https://github.com/Unity-Technologies/EntityComponentSystemSamples) contains a simple HelloCube example that demonstrates how to use IJobChunk.
## Query for data with a EntityQuery
A EntityQuery defines the set of component types that an archetype must contain for the system to process its associated chunks and entities. An archetype can have additional components as well, but it must have at least those defined by the EntityQuery. You can also exclude archetypes that contain specific types of components.
For simple queries, you can use the JobComponentSystem.GetEntityQuery() function, passing in the component types:
``` c#
public class RotationSpeedSystem : JobComponentSystem
{
private EntityQuery m_Group;
protected override void OnCreate()
{
m_Group = GetEntityQuery(typeof(RotationQuaternion), ComponentType.ReadOnly<RotationSpeed>());
}
//…
}
````
For more complex situations, you can use an EntityQueryDesc. An EntityQueryDesc provides a flexible query mechanism to specify the component types:
* `All` = All component types in this array must exist in the archetype
* `Any` = At least one of the component types in this array must exist in the archetype
* `None` = None of the component types in this array can exist in the archetype
For example, the following query includes archetypes containing the RotationQuaternion and RotationSpeed components, but excludes any archetypes containing the Frozen component:
``` c#
protected override void OnCreate()
{
var query = new EntityQueryDesc
{
None = new ComponentType[]{ typeof(Frozen) },
All = new ComponentType[]{ typeof(RotationQuaternion), ComponentType.ReadOnly<RotationSpeed>() }
}
};
m_Group = GetEntityQuery(query);
}
```
The query uses `ComponentType.ReadOnly<T>` instead of the simpler `typeof` expression to designate that the system does not write to RotationSpeed.
You can also combine multiple queries by passing an array of EntityQueryDesc objects rather than a single instance. Each query is combined using a logical OR operation. The following example selects an archetypes that contain a RotationQuaternion component or a RotationSpeed component (or both):
``` c#
protected override void OnCreate()
{
var query0 = new EntityQueryDesc
{
All = new ComponentType[] {typeof(RotationQuaternion)}
};
var query1 = new EntityQueryDesc
{
All = new ComponentType[] {typeof(RotationSpeed)}
};
m_Group = GetEntityQuery(new EntityQueryDesc[] {query0, query1});
}
```
**Note:** Do not include completely optional components in the EntityQueryDesc. To handle optional components, use the `chunk.Has<T>()` method inside `IJobChunk.Execute()` to determine whether the current ArchetypeChunk has the optional component or not. Since all entities within the same chunk have the same components, you only need to check whether an optional component exists once per chunk -- not once per entity.
For efficiency and to avoid needless creation of garbage-collected reference types, you should create the EntityQueries for a system in the system’s OnCreate() function and store the result in an instance variable. (In the above examples, the `m_Group` variable is used for this purpose.)
### ## Define the IJobChunk struct
The IJobChunk struct defines fields for the data the Job needs when it runs, as well as the Job’s Execute() method.
In order to access the component arrays inside the chunks that the system passes to your Execute() method, you must create an ArchetypeChunkComponentType<T> object for each type of component that the Job reads or writes. These objects allow you to get instances of the NativeArrays providing access to the components of an entity. Include all the components referenced in the Job’s EntityQuery that the Execute method reads or writes. You can also provide ArchetypeChunkComponentType variables for optional component types that you do not include in the EntityQuery. (You must check to make sure that the current chunk has an optional component before trying to access it.)
For example, the HelloCube IJobChunk example declares a Job struct that defines ArchetypeChunkComponentType<T> variables for two components, RotationQuaternion and RotationSpeed:
``` c#
[BurstCompile]
struct RotationSpeedJob : IJobChunk
{
public float DeltaTime;
public ArchetypeChunkComponentType<RotationQuaternion> RotationType;
[ReadOnly] public ArchetypeChunkComponentType<RotationSpeed> RotationSpeedType;
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
{
//...
}
}
```
The system assigns values to these variables in the OnUpdate() function. The variables are used inside the Execute() method when the ECS framework runs the Job.
The Job also uses the Unity delta time to animate the rotation of a 3D object. The example also passes this value to the Execute method using a struct field.
### ## Writing the Execute method
The signature of the IJobChunk Execute method is:
``` c#
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
```
The `chunk` parameter is a handle to the block of memory containing the entities and components to be processed in this iteration of the Job. Since a chunk can only contain a single archetype, all the entities in a chunk have the same set of components.
Use the `chunk` parameter to get the NativeArray instances for your components:
``` c#
var chunkRotations = chunk.GetNativeArray(RotationType);
var chunkRotationSpeeds = chunk.GetNativeArray(RotationSpeedType);
```
These arrays are aligned such that an entity has the same index in all of them. You can then iterate through the component arrays with a normal for loop. Use `chunk.Count` to get the number of entities stored in the current chunk:
``` c#
for (var i = 0; i < chunk.Count; i++)
{
var rotation = chunkRotations[i];
var rotationSpeed = chunkRotationSpeeds[i];
// Rotate something about its up vector at the speed given by RotationSpeed.
chunkRotations[i] = new RotationQuaternion
{
Value = math.mul(math.normalize(rotation.Value),
quaternion.AxisAngle(math.up(), rotationSpeed.RadiansPerSecond * DeltaTime))
};
}
```
If you the `Any` filter in your EntityQueryDesc or have completely optional components that don’t appear in the query at all, you can use the `ArchetypeChunk.Has<T>` function to test whether the current chunk contains the one of those components before using it:
if (chunk.Has<OptionalComp>(OptionalCompType))
{//...}
__Note:__ If you use a concurrent entity command buffer, pass the chunkIndex argument as the `jobIndex` parameter to the command buffer functions.
## Skipping chunks with unchanged entities
If you only need to update entities when a component value has changed, you can add that component type to the change filter of the EntityQuery used to select the entities and chunks for the job. For example, if you have a system that reads two components and only needs to update a third when one of the first two has changed, you could use a EntityQuery as follows:
``` c#
EntityQuery m_Group;
protected override void OnCreate()
{
m_Group = GetEntityQuery(typeof(Output),
ComponentType.ReadOnly<InputA>(),
ComponentType.ReadOnly<InputB>());
m_Group.SetFilterChanged(new ComponentType{ typeof(InputA), typeof(InputB)});
}
```
The EntityQuery change filter supports up to two components. If you want to check more or aren't using a EntityQuery, you can make the check manually. To make this check, compare the chunk’s change version for the component to the system’s LastSystemVersion using the `ArchetypeChunk.DidChange()` function. If this function returns false, you can skip the current chunk altogether since none of the components of that type have changed since the last time the system ran.
The LastSystemVersion from the system must be passed into the Job using a struct field:
[BurstCompile]
struct UpdateJob : IJobChunk
{
public ArchetypeChunkComponentType<InputA> InputAType;
public ArchetypeChunkComponentType<InputB> InputBType;
[ReadOnly] public ArchetypeChunkComponentType<Output> OutputType;
public uint LastSystemVersion;
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
{
var inputAChanged = chunk.DidChange(InputAType, LastSystemVersion);
var inputBChanged = chunk.DidChange(InputBType, LastSystemVersion);
if (!(inputAChanged || inputBChanged))
return;
//...
}
As with all the Job struct fields, you must assign its value before scheduling the Job:
``` c#
var job = new UpdateJob()
{
LastSystemVersion = this.LastSystemVersion,
//… initialize other fields
}
```
Note that for efficiency, the change version applies to whole chunks not individual entities. If a chunk has been accessed by another Job which had the ability to write to that type of component, then the change version for that component is incremented and the `DidChange()` function returns true.
## Instantiate and schedule the Job
To run an IJobChunk Job, you must create an instance of your Job struct, setting the struct fields, and then schedule the Job. When you do this in the OnUpdate() function of a JobComponentSystem, the system schedules the Job to run every frame.
``` c#
// OnUpdate runs on the main thread.
protected override JobHandle OnUpdate(JobHandle inputDependencies)
{
var job = new RotationSpeedJob()
{
RotationType = GetArchetypeChunkComponentType<RotationQuaternion>(false),
RotationSpeedType = GetArchetypeChunkComponentType<RotationSpeed>(true),
DeltaTime = Time.deltaTime
};
return job.Schedule(m_Group, inputDependencies);
}
```
When you call the GetArchetypeChunkComponentType<T> function to set your component type variables, make sure that you set the isReadOnly to true for components that the Job reads, but doesn’t write. Setting these parameters correctly can have a significant impact on how efficiently the ECS framework can schedule your Jobs. These access mode settings must match their equivalents in both the struct definition, and the EntityQuery.
Do not cache the return value of GetArchetypeChunkComponentType<T> in a system class variable. The function must be called every time the system runs and the updated value passed to the Job.

26
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/component_data.md


---
uid: ecs-component-data
---
# ComponentData
ComponentData in Unity (also known as a component in standard ECS terms) is a struct that contains only the instance data for an [entity](entities.md). ComponentData cannot contain methods. To put this in terms of the old Unity system, this is somewhat similar to an old Component class, but one that **only contains variables**.
Unity ECS provides an interface called `IComponentData` that you can implement in your code.
## IComponentData
Traditional Unity components (including `MonoBehaviour`) are [object-oriented](https://en.wikipedia.org/wiki/Object-oriented_programming) classes which contain data and methods for behavior. `IComponentData` is a pure ECS-style component, meaning that it defines no behavior, only data. `IComponentData` is a struct rather than a class, meaning that it is copied [by value instead of by reference](https://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value?answertab=votes#tab-top) by default. You will usually need to use the following pattern to modify data:
```c#
var transform = group.transform[index]; // Read
transform.heading = playerInput.move; // Modify
transform.position += deltaTime * playerInput.move * settings.playerMoveSpeed;
group.transform[index] = transform; // Write
```
`IComponentData` structs may not contain references to managed objects. Since the all `ComponentData` lives in simple non-garbage-collected tracked [chunk memory](chunk_iteration.md).
See file: _/Packages/com.unity.entities/Unity.Entities/IComponentData.cs_.

223
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/component_group.md


---
uid: ecs-component-group
---
# Querying for data using a EntityQuery
The first step to reading or writing data is finding that data. Data in the ECS framework is stored in components, which are grouped together in memory according to the archetype of the entity to which they belong. To define a view into your ECS data that contains only the specific data you need for a given algorithm or process, you can construct a EntityQuery.
After creating a EntityQuery, you can
* Run a Job to process the entities and components selected for the view
* Get a NativeArray containing all the selected entities
* Get NativeArrays of the selected components (by component type)
The entity and component arrays returned by a EntityQuery are guaranteed to be "parallel", that is, the same index value always applies to the same entity in any array.
**Note:** that the `ComponentSystem.Entites.ForEach` delegates and IJobForEach create internal EntityQueries based on the component types and attributes you specify for these APIs.
<!-- TODO: (In an IJobForEach Job, you can override the EntityQuery to use a more complex query than the default setup supports.) -->
## Defining a query
A EntityQuery query defines the set of component types that an archetype must contain in order for its chunks and entities to be included in the view. You can also exclude archetypes that contain specific types of components.
For simple queries, you can create a EntityQuery based on an array of component types. The following example defines a EntityQuery that finds all entities with both RotationQuaternion and RotationSpeed components.
``` c#
EntityQuery m_Group = GetEntityQuery(typeof(RotationQuaternion), ComponentType.ReadOnly<RotationSpeed>());
````
The query uses `ComponentType.ReadOnly<T>` instead of the simpler `typeof` expression to designate that the system does not write to RotationSpeed. Always specify read only when possible, since there are fewer constraints on read access to data, which can help the Job scheduler execute your Jobs more efficiently.
### EntityQueryDesc
For more complex queries, you can use an EntityQueryDesc to create the EntityQuery. An EntityQueryDesc provides a flexible query mechanism to specify which archetypes to select based on the following sets of components:
* `All` = All component types in this array must exist in the archetype
* `Any` = At least one of the component types in this array must exist in the archetype
* `None` = None of the component types in this array can exist in the archetype
For example, the following query includes archetypes containing the RotationQuaternion and RotationSpeed components, but excludes any archetypes containing the Frozen component:
``` c#
var query = new EntityQueryDesc
{
None = new ComponentType[]{ typeof(Frozen) },
All = new ComponentType[]{ typeof(RotationQuaternion), ComponentType.ReadOnly<RotationSpeed>() }
}
EntityQuery m_Group = GetEntityQuery(query);
```
**Note:** Do not include completely optional components in the EntityQueryDesc. To handle optional components, use the `ArchetypeChunk.Has<T>()` method to determine whether a chunk contains the optional component or not. Since all entities within the same chunk have the same components, you only need to check whether an optional component exists once per chunk -- not once per entity.
### Query options
When you create an EntityQueryDesc, you can set its `Options` variable. The options allow for specialized queries (normally you do not need to set them):
* Default — no options set; the query behaves normally.
* IncludePrefab — includes archetypes containing the special Prefab tag component.
* IncludeDisabled — includes archetypes containing the special Disabled tag component.
* FilterWriteGroup — considers the WriteGroup of any components in the query.
When you set the FilterWriteGroup option, only entities with those components in a Write Group that are explicitly included in the query will be included in the view. Entities that have any additional components from the same WriteGroup are excluded.
For example, suppose C2 and C3 are components in the same Write Group based on C1, and you created a query using the FilterWriteGroup option that requires C1 and C3:
``` c#
public struct C1: IComponentData{}
[WriteGroup(C1)]
public struct C2: IComponentData{}
[WriteGroup(C1)]
public struct C3: IComponentData{}
// ... In a system:
var query = new EntityQueryDesc{
All = new ComponentType{typeof(C1), ComponentType.ReadOnly<C3>()},
Options = EntityQueryDescOptions.FilterWriteGroup
};
var m_group = GetEntityQuery(query);
```
This query excludes any entities with both C2 and C3 because C2 is not explicitly included in the query. While you could design this into the query using `None`, doing it through a Write Group provides an important benefit: you don't need to alter the queries used by other systems (as long as these systems also use Write Groups).
Write Groups are a mechanism that allow you to extend existing systems. For example, if C1 and C2 are defined in another system (perhaps part of a library that you don't control), you could put C3 into the same Write Group as C2 in order to change how C1 is updated. For any entities to which you add your C3 component, your system will update C1 and the original system will not. For other entities without C3, the original system will update C1 as before.
See [Write Groups](ecs_write_groups.md) for more information.
### Combining queries
You can combine multiple queries by passing an array of EntityQueryDesc objects rather than a single instance. Each query is combined using a logical OR operation. The following example selects an archetypes that contain a RotationQuaternion component or a RotationSpeed component (or both):
``` c#
var query0 = new EntityQueryDesc
{
All = new ComponentType[] {typeof(RotationQuaternion)}
};
var query1 = new EntityQueryDesc
{
All = new ComponentType[] {typeof(RotationSpeed)}
};
EntityQuery m_Group = GetEntityQuery(new EntityQueryDesc[] {query0, query1});
```
## Creating a EntityQuery
Outside a system class, you can create a EntityQuery with the `EntityManager.CreateEntityQuery()` function:
``` c#
EntityQuery m_Group = CreateEntityQuery(typeof(RotationQuaternion), ComponentType.ReadOnly<RotationSpeed>());
```
However, in a system class, you must use the `GetEntityQuery()` function:
``` c#
public class RotationSpeedSystem : JobComponentSystem
{
private EntityQuery m_Group;
protected override void OnCreate()
{
m_Group = GetEntityQuery(typeof(RotationQuaternion), ComponentType.ReadOnly<RotationSpeed>());
}
//…
}
```
When you plan to reuse the same view, you should cache the EntityQuery instance, if possible, instead of creating a new one for each use. For example, in a system, you can create the EntityQuery in the system’s `OnCreate()` function and store the result in an instance variable. The `m_Group` variable in the above example is used for this purpose.
## Defining filters
In addition to defining which components must be included or excluded from the query, you can also filter the view. You can specify the following types of filters:
* Shared component values —filter the set of entities based on specific values of a shared component.
* Change filter — Filter the set of entities based on whether the value of a specific component type has potentially changed
### Shared component filters
To use a shared component filter, first include the shared component in the EntityQuery (along with other needed components), and then call the `SetFilter()` function, passing in a struct of the same ISharedComponent type that contains the values to select. All values must match. You can add up to two different shared components to the filter.
You can change the filter at any time, but changing the filter does not change any existing arrays of entities or components that you received from the group `ToComponentDataArray()` or `ToEntityArray()` functions. You must recreate these arrays.
The following example defines a shared component named SharedGrouping and a system that only processes entities that have the Group field set to 1.
```cs
struct SharedGrouping : ISharedComponentData
{
public int Group;
}
class ImpulseSystem : ComponentSystem
{
EntityQuery m_Group;
protected override void OnCreate(int capacity)
{
m_Group = GetEntityQuery(typeof(Position), typeof(Displacement), typeof(SharedGrouping));
}
protected override void OnUpdate()
{
// Only iterate over entities that have the SharedGrouping data set to 1
m_Group.SetFilter(new SharedGrouping { Group = 1 });
var positions = m_Group.ToComponentDataArray<Position>(Allocator.Temp);
var displacememnts = m_Group.ToComponentDataArray<Displacement>(Allocator.Temp);
for (int i = 0; i != positions.Length; i++)
positions[i].Value = positions[i].Value + displacememnts[i].Value;
}
}
```
### Change filters
If you only need to update entities when a component value has changed, you can add that component to the EntityQuery filter using the `SetFilterChanged()` function. For example, the following EntityQuery only includes entities from chunks in which another system has already written to the Translation component:
``` c#
protected override void OnCreate(int capacity)
{
m_Group = GetEntityQuery(typeof(LocalToWorld), ComponentType.ReadOnly<Translation>());
m_Group.SetFilterChanged(typeof(Translation));
}
```
Note that for efficiency, the change filter applies to whole chunks not individual entities. The change filter also only checks whether a system has run that declared write access to the component, not whether it actually changed any data. In other words, if a chunk has been accessed by another Job which had the ability to write to that type of component, then the change filter includes all entities in that chunk. (This is another reason to always declare read only access to components that you do not need to modify.)
## Executing the query
A EntityQuery executes its query when you use the EntityQuery in a Job or you call one of the EntityQuery methods that returns arrays of entities, components, or chunks in the view:
* `ToEntityArray()` returns an array of the selected entities.
* `ToComponentDataArray<T>` returns an array of the components of type T for the selected entities.
* `CreateArchetypeChunkArray()` returns all the chunks containing the selected entities. (Since a query operates on archetypes, shared component values, and change filters, which are all identical for all the entities in a chunk, the set of entities stored within the returned set of chunks is exactly the same as the set of entities returned by `ToEntityArray()`.)
<!-- TODO: Discuss using the Job versions of these functions. -->
### In Jobs
In a JobComponentSystem, pass the EntityQuery object to the system's `Schedule()` method. In the following example, from the HelloCube IJobChunk sample, the `m_Group` argument is the EntityQuery object
``` c#
// OnUpdate runs on the main thread.
protected override JobHandle OnUpdate(JobHandle inputDependencies)
{
var rotationType = GetArchetypeChunkComponentType<Rotation>(false);
var rotationSpeedType = GetArchetypeChunkComponentType<RotationSpeed>(true);
var job = new RotationSpeedJob()
{
RotationType = rotationType,
RotationSpeedType = rotationSpeedType,
DeltaTime = Time.deltaTime
};
return job.Schedule(m_Group, inputDependencies);
}
```
A EntityQuery uses Jobs internally to create the required arrays. When you pass the group to the `Schedule()` method, the EntityQuery Jobs are scheduled along with the system's own Jobs and can take advantage of parallel processing.

15
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/component_system.md


---
uid: ecs-component-system
---
# ComponentSystem
A `ComponentSystem` in Unity (also known as a system in standard ECS terms) performs operations on [entities](entities.md). A `ComponentSystem` cannot contain instance data. To put this in terms of the old Unity system, this is somewhat similar to an old [Component](https://docs.unity3d.com/Manual/Components.html) class, but one that **only contains methods**. One `ComponentSystem` is responsible for updating all entities with a matching set of components (that is defined within a struct called a [EntityQuery](component_group.md)).
Unity ECS provides an abstract class called `ComponentSystem` that you can extend in your code.
See file: _/Packages/com.unity.entities/Unity.Entities/ComponentSystem.cs_.
See also: [System update order](system_update_order.md).

382
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/custom_job_types.md


---
uid: ecs-custom-job-types
---
# Custom job types
On the lowest level of the job system, jobs are scheduled by calling one of the `Schedule` functions in [JobsUtility](https://docs.unity3d.com/ScriptReference/Unity.Jobs.LowLevel.Unsafe.JobsUtility.html). The currently existing [job types](https://docs.unity3d.com/ScriptReference/Unity.Jobs.LowLevel.Unsafe.JobType.html) all use these functions, but it is also possible to create specialized job types using the same APIs.
These APIs use unsafe code and have to be crafted carefully, since they can easily introduce unwanted race conditions. If you add your own job types, we strongly recommend to aim for full test coverage.
As an example we have a custom job type `IJobParallelForBatch` (see file: _/Packages/com.unity.jobs/Unity.Jobs/IJobParallelForBatch.cs_).
It works like __IJobParallelFor__, but instead of calling a single execute function per index it calls one execute function per batch being executed. This is useful if you need to do something on more than one item at a time, but still want to do it in parallel. A common scenario for this job type is if you need to create a temporary array and you want to avoid creating each item in the array one at a time. By using IJobParallelFor you can instead create one temporary array per batch.
In the IJobParallelForBatch example, the entry point where the job is actually scheduled looks like this:
```c#
unsafe static public JobHandle ScheduleBatch<T>(this T jobData, int arrayLength, int minIndicesPerJobCount, JobHandle dependsOn = new JobHandle()) where T : struct, IJobParallelForBatch
{
var scheduleParams = new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), ParallelForBatchJobStruct<T>.Initialize(), dependsOn, ScheduleMode.Batched);
return JobsUtility.ScheduleParallelFor(ref scheduleParams, arrayLength, minIndicesPerJobCount);
}
```
The first line creates a struct containing the scheduling parameters. When creating it you need to set a pointer to the data which will be copied to the jobs. The reason this is a pointer is that the native code which uses it does not know about the type.
You also need to pass it a pointer to the __JobReflectionData__ created by calling:
```c#
JobsUtility.CreateJobReflectionData(typeof(T), JobType.ParallelFor, (ExecuteJobFunction)Execute);
```
JobReflection stores information about the struct with the data for the job, such as which __NativeContainers__ it has and how they need to be patched when scheduling a job. It lives on the native side of the engine and the managed code only has access to it though pointers without any information about what the type is. When creating JobReflectionData you need to specify the type of the struct implementing the job, the __JobType__ and the method which will be called to execute the job. The JobReflectionData does not depend on the data in the struct you schedule, only its type, so it should only be created once for all jobs implementing the same interface. There are currently only two job types, __Single__ and __ParallelFor__. Single means the job will only get a single call, ParallelFor means there will be multiple calls to process it; where each call is restricted to a subset of the range of indices to process. Which job type you choose affects which schedule function you are allowed to call.
The third parameter of __JobsUtility.JobScheduleParameters__ is the __JobHandle__ that the scheduled job should depend on.
The final parameter is the schedule mode. There are two scheduling modes to choose from, __Run__ and __Batched__. Batched means one or more jobs will be scheduled to do the processing, while Run means the processing will be done on the main thread before Schedule returns.
Once the schedule parameters are created we actually schedule the job. There are three ways to schedule jobs depending on their type:
```c#
JobHandle Schedule(ref JobScheduleParameters parameters);
JobHandle ScheduleParallelFor(ref JobScheduleParameters parameters, int arrayLength, int innerLoopBatchCount);
JobHandle ScheduleParallelForTransform(ref JobScheduleParameters parameters, IntPtr transfromAccessArray);
```
Schedule can only be used if the __ScheduleParameters__ are created with __JobType.Single__, the other two schedule functions require __JobType.ParallelFor__.
The __arrayLength__ and __innerLoopBatchCount__ parameter passed to __ScheduleParallelFor__ are used to determine how many indices the jobs should process and how many indices it should handle in the inner loop (see the section on [Execution and JobRanges](#execution-and-jobranges) for more information on the inner loop count).
__ScheduleParallelForTransform__ is similar to ScheduleParallelFor, but it also has access to a __TransformAccessArray__ that allows you to modify __Transform__ components on __GameObjects__. The number of indices and batch size is inferred from the TransformAccessArray.
## Execution and JobRanges
After scheduling the job, Unity will call the entry point you specified directly from the native side. It works in a similar way to how __Update__ is called on MonoBehaviours, but from inside a job instead. You only get one call per job and there is either one job, or one job per worker thread; in the case of ParallelFor.
The signature used for Execute is
```c#
public delegate void ExecuteJobFunction(ref T data, IntPtr additionalPtr, IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex);
```
For Single jobs, only the data is needed and you can just do your processing right away, but for ParallelFor jobs it requires some more work before you can start processing indices. We need to split up the indices into a number of sequential sub-sets that each job will process in parallel. This way we do not process the same thing twice and we are sure that everything gets covered. The memory layout will determine the order of indices.
The JobRanges contain the batches and indices a ParallelFor job is supposed to process. The indices are split into batches based on the batch size, the batches are evenly distributed between the jobs doing the execution in such a way that each job can iterate over a continuous section of memory. The ParallelFor job should call:
```c#
JobsUtility.GetWorkStealingRange(ref ranges, jobIndex, out begin, out end)
```
This continues until it returns `false`, and after calling it process all items with index between __begin__ and __end__.
The reason you get batches of items, rather than the full set of items the job should process, is that Unity will apply [work stealing](https://en.wikipedia.org/wiki/Work_stealing) if one job completes before the others. Work stealing in this context means that when one job is done it will look at the other jobs running and see if any of them still have a lot of work left. If it finds a job which is not complete it will steal some of the batches that it has not yet started; to dynamically redistribute the work.
Before a ParallelFor job starts processing items it also needs to limit the write access to NativeContainers on the range of items which the job is processing. If it does not do this several jobs can potentially write to the same index which leads to race conditions. The NativeContainers that need to be limited is passed to the job and there is a function to patch them; so they cannot access items outside the correct range. The code to do it looks like this:
```c#
#if ENABLE_UNITY_COLLECTIONS_CHECKS
JobsUtility.PatchBufferMinMaxRanges(bufferRangePatchData, UnsafeUtility.AddressOf(ref jobData), begin, end - begin);
#endif
```
# Custom NativeContainers
When writing jobs, the data communication between jobs is one of the hardest parts to get right. Just using __NativeArray__ is very limiting. Using __NativeQueue__, __NativeHashMap__ and __NativeMultiHashMap__ and their __Concurrent__ versions solves most scenarios.
For the remaining scenarios it is possible to write your own custom NativeContainers.
When writing custom containers for [thread synchronization](https://en.wikipedia.org/wiki/Synchronization_(computer_science)#Thread_or_process_synchronization) it is very important to write correct code. We strongly recommend full test coverage for any new containers you add.
As a very simple example of this we will create a __NativeCounter__ that can be incremented in a ParallelFor job through __NativeCounter.Concurrent__ and read in a later job or on the main thread.
Let's start with the basic container type:
```c#
// Mark this struct as a NativeContainer, usually this would be a generic struct for containers, but a counter does not need to be generic
// TODO - why does a counter not need to be generic? - explain the argument for this reasoning please.
[StructLayout(LayoutKind.Sequential)]
[NativeContainer]
unsafe public struct NativeCounter
{
// The actual pointer to the allocated count needs to have restrictions relaxed so jobs can be schedled with this container
[NativeDisableUnsafePtrRestriction]
int* m_Counter;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle m_Safety;
// The dispose sentinel tracks memory leaks. It is a managed type so it is cleared to null when scheduling a job
// The job cannot dispose the container, and no one else can dispose it until the job has run, so it is ok to not pass it along
// This attribute is required, without it this NativeContainer cannot be passed to a job; since that would give the job access to a managed object
[NativeSetClassTypeToNullOnSchedule]
DisposeSentinel m_DisposeSentinel;
#endif
// Keep track of where the memory for this was allocated
Allocator m_AllocatorLabel;
public NativeCounter(Allocator label)
{
// This check is redundant since we always use an int that is blittable.
// It is here as an example of how to check for type correctness for generic types.
#if ENABLE_UNITY_COLLECTIONS_CHECKS
if (!UnsafeUtility.IsBlittable<int>())
throw new ArgumentException(string.Format("{0} used in NativeQueue<{0}> must be blittable", typeof(int)));
#endif
m_AllocatorLabel = label;
// Allocate native memory for a single integer
m_Counter = (int*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf<int>(), 4, label);
// Create a dispose sentinel to track memory leaks. This also creates the AtomicSafetyHandle
#if ENABLE_UNITY_COLLECTIONS_CHECKS
DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0);
#endif
// Initialize the count to 0 to avoid uninitialized data
Count = 0;
}
public void Increment()
{
// Verify that the caller has write permission on this data.
// This is the race condition protection, without these checks the AtomicSafetyHandle is useless
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
#endif
(*m_Counter)++;
}
public int Count
{
get
{
// Verify that the caller has read permission on this data.
// This is the race condition protection, without these checks the AtomicSafetyHandle is useless
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
#endif
return *m_Counter;
}
set
{
// Verify that the caller has write permission on this data. This is the race condition protection, without these checks the AtomicSafetyHandle is useless
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
#endif
*m_Counter = value;
}
}
public bool IsCreated
{
get { return m_Counter != null; }
}
public void Dispose()
{
// Let the dispose sentinel know that the data has been freed so it does not report any memory leaks
#if ENABLE_UNITY_COLLECTIONS_CHECKS
DisposeSentinel.Dispose(m_Safety, ref m_DisposeSentinel);
#endif
UnsafeUtility.Free(m_Counter, m_AllocatorLabel);
m_Counter = null;
}
}
```
With this we have a simple NativeContainer where we can get, set, and increment the count. This container can be passed to a job, but it has the same restrictions as NativeArray, which means it cannot be passed to a ParallelFor job with write access.
The next step is to make it usable in ParallelFor. In order to avoid race conditions we want to make sure no-one else is reading it while the ParallelFor is writing to it. To achieve this we create a separate inner struct called Concurrent that can handle multiple writers, but no readers. We make sure NativeCounter.Concurrent can be assigned to from within a normal NativeCounter, since it is not possible for it to live separately outside a NativeCounter. TODO - why is that?
```c#
[NativeContainer]
// This attribute is what makes it possible to use NativeCounter.Concurrent in a ParallelFor job
[NativeContainerIsAtomicWriteOnly]
unsafe public struct Concurrent
{
// Copy of the pointer from the full NativeCounter
[NativeDisableUnsafePtrRestriction]
int* m_Counter;
// Copy of the AtomicSafetyHandle from the full NativeCounter. The dispose sentinel is not copied since this inner struct does not own the memory and is not responsible for freeing it.
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle m_Safety;
#endif
// This is what makes it possible to assign to NativeCounter.Concurrent from NativeCounter
public static implicit operator NativeCounter.Concurrent (NativeCounter cnt)
{
NativeCounter.Concurrent concurrent;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle.CheckWriteAndThrow(cnt.m_Safety);
concurrent.m_Safety = cnt.m_Safety;
AtomicSafetyHandle.UseSecondaryVersion(ref concurrent.m_Safety);
#endif
concurrent.m_Counter = cnt.m_Counter;
return concurrent;
}
public void Increment()
{
// Increment still needs to check for write permissions
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
#endif
// The actual increment is implemented with an atomic, since it can be incremented by multiple threads at the same time
Interlocked.Increment(ref *m_Counter);
}
}
```
With this setup we can schedule ParallelFor with write access to a NativeCounter through the inner Concurrent struct, like this:
```c#
struct CountZeros : IJobParallelFor
{
[ReadOnly]
public NativeArray<int> input;
public NativeCounter.Concurrent counter;
public void Execute(int i)
{
if (input[i] == 0)
{
counter.Increment();
}
}
}
```
```c#
var counter = new NativeCounter(Allocator.Temp);
var jobData = new CountZeros();
jobData.input = input;
jobData.counter = counter;
counter.Count = 0;
var handle = jobData.Schedule(input.Length, 8);
handle.Complete();
Debug.Log("The array countains " + counter.Count + " zeros");
counter.Dispose();
```
## Better cache usage
The NativeCounter from the previous section is a working implementation of a counter, but all jobs in the ParallelFor will access the same atomic to increment the value. This is not optimal as it means the same cache line is used by all threads.
The way this is generally solved in NativeContainers is to have a local cache per worker thread, which is stored on its own cache line.
The __[NativeSetThreadIndex]__ attribute can inject a worker thread index, the index is guaranteed to be unique while accessing the NativeContainer from the ParallelFor jobs.
In order to make such an optimization here we need to change a few things. The first thing we need to change is the data layout. For performance reasons we need one full cache line per worker thread, rather than a single int to avoid [false sharing](https://en.wikipedia.org/wiki/False_sharing).
We start by adding a constant for the number of ints on a cache line.
```c#
public const int IntsPerCacheLine = JobsUtility.CacheLineSize / sizeof(int);
```
Next we change the amount of memory allocated.
```c#
// One full cache line (integers per cacheline * size of integer) for each potential worker index, JobsUtility.MaxJobThreadCount
m_Counter = (int*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf<int>()*IntsPerCacheLine*JobsUtility.MaxJobThreadCount, 4, label);
```
TODO: I'm not sure which example you are referring to when you say: main, non-concurrent, version below (is this an example you used on this page or what you would do if you were not using jobified code/ECS etc. It has potential for confusion.)
When accessing the counter from the main, non-concurrent, version there can only be one writer so the increment function is fine with the new memory layout.
For `get` and `set` of the `count` we need to loop over all potential worker indices.
```c#
public int Count
{
get
{
// Verify that the caller has read permission on this data.
// This is the race condition protection, without these checks the AtomicSafetyHandle is useless
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
#endif
int count = 0;
for (int i = 0; i < JobsUtility.MaxJobThreadCount; ++i)
count += m_Counter[IntsPerCacheLine * i];
return count;
}
set
{
// Verify that the caller has write permission on this data.
// This is the race condition protection, without these checks the AtomicSafetyHandle is useless
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
#endif
// Clear all locally cached counts,
// set the first one to the required value
for (int i = 1; i < JobsUtility.MaxJobThreadCount; ++i)
m_Counter[IntsPerCacheLine * i] = 0;
*m_Counter = value;
}
}
```
The final change is the inner Concurrent struct that needs to get the worker index injected into it. Since each worker only runs one job at a time, there is no longer any need to use atomics when only accessing the local count.
```c#
[NativeContainer]
[NativeContainerIsAtomicWriteOnly]
// Let the job system know that it should inject the current worker index into this container
unsafe public struct Concurrent
{
[NativeDisableUnsafePtrRestriction]
int* m_Counter;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle m_Safety;
#endif
// The current worker thread index; it must use this exact name since it is injected
[NativeSetThreadIndex]
int m_ThreadIndex;
public static implicit operator NativeCacheCounter.Concurrent (NativeCacheCounter cnt)
{
NativeCacheCounter.Concurrent concurrent;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle.CheckWriteAndThrow(cnt.m_Safety);
concurrent.m_Safety = cnt.m_Safety;
AtomicSafetyHandle.UseSecondaryVersion(ref concurrent.m_Safety);
#endif
concurrent.m_Counter = cnt.m_Counter;
concurrent.m_ThreadIndex = 0;
return concurrent;
}
public void Increment()
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
#endif
// No need for atomics any more since we are just incrementing the local count
++m_Counter[IntsPerCacheLine*m_ThreadIndex];
}
}
```
Writing the NativeCounter this way significantly reduces the overhead of having multiple threads writing to it. It does, however, come at a price. The cost of getting the count on the main thread has increased significantly since it now needs to check all local caches and sum them up. If you are aware of this and make sure to cache the return values it is usually worth it, but you need to know the limitations of your data structures. So we strongly recommend documenting the performance characteristics.
## Tests
The NativeCounter is not complete, the only thing left is to add tests for it to make sure it is correct and that it does not break in the future. When writing tests you should try to cover as many unusual scenarios as possible. It is also a good idea to add some kind of stress test using jobs to detect race conditions, even if it is unlikely to find all of them. The NativeCounter API is very small so the number of tests required is not huge.
* Both versions of the counter examples above are available at: _/Assets/NativeCounterDemo_.
* The tests for them can be found at: _/Assets/NativeCounterDemo/Editor/NativeCounterTests.cs_.
## Available attributes
The NativeCounter uses many attributes, but there are a few more available for other types of containers. Here is a list of the available attributes you can use on the NativeContainer struct.
* [NativeContainer](https://docs.unity3d.com/2018.1/Documentation/ScriptReference/Unity.Collections.LowLevel.Unsafe.NativeContainerAttribute.html) - marks a struct as a NativeContainer.Required for all native containers.
* [NativeContainerSupportsMinMaxWriteRestriction](https://docs.unity3d.com/2018.1/Documentation/ScriptReference/Unity.Collections.LowLevel.Unsafe.NativeContainerSupportsMinMaxWriteRestrictionAttribute.html) - signals that the NativeContainer can restrict its writable ranges to be between a min and max index. This is used when passing the container to an IJobParallelFor to make sure that the job does not write to indices it is not supposed to process. In order to use this the NativeContainer must have the members int __m_Length__, int __m_MinIndex__ and int __m_MaxIndex__ in that order with no other members between them. The container must also throw an exception for writes outside the min/max range.
* [NativeContainerIsAtomicWriteOnly](https://docs.unity3d.com/2018.1/Documentation/ScriptReference/Unity.Collections.LowLevel.Unsafe.NativeContainerIsAtomicWriteOnlyAttribute.html) - signals that the NativeContainer uses atomic writes and no reads. By adding this is is possible to pass the NativeContainer to an IJobParallelFor as writable without restrictions on which indices can be written to.
* [NativeContainerSupportsDeallocateOnJobCompletion](https://docs.unity3d.com/2018.1/Documentation/ScriptReference/Unity.Collections.LowLevel.Unsafe.NativeContainerSupportsDeallocateOnJobCompletionAttribute.html) - makes the NativeContainer usable with [DeallocateOnJobCompletion](https://docs.unity3d.com/2018.1/Documentation/ScriptReference/Unity.Collections.DeallocateOnJobCompletionAttribute.html). In order to use this the NativeContainer must have a single allocation in __m_Buffer__, an allocator label in __m_AllocatorLabel__ and a dispose sentinel in __m_DisposeSentinel__.
* [NativeSetThreadIndex](https://docs.unity3d.com/2018.1/Documentation/ScriptReference/Unity.Collections.LowLevel.Unsafe.NativeSetThreadIndexAttribute.html) - Patches an int with the thread index of the job.
In addition to these attributes on the native container struct itself there are a few attributes which can be used on members of the native container.
* [NativeDisableUnsafePtrRestriction](https://docs.unity3d.com/2018.1/Documentation/ScriptReference/Unity.Collections.LowLevel.Unsafe.NativeDisableUnsafePtrRestrictionAttribute.html) - allows the NativeContainer to be passed to a job even though it contains a pointer, which is usually not allowed.
* [NativeSetClassTypeToNullOnSchedule](https://docs.unity3d.com/2018.1/Documentation/ScriptReference/Unity.Collections.LowLevel.Unsafe.NativeSetClassTypeToNullOnScheduleAttribute.html) - allows the NativeContainer to be passed to a job even though it contains a managed object. The managed object will be set to `null` on the copy passed to the job.

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/doo_design.md


---
uid: ecs-data-oriented-design
---
# Data-oriented design in Unity
> Synopsis: Discuss how to design optimal data structures and algorithms to transform them. Provide case studies for different types of data commonly found in games: transform data, hierarchical skinned meshes, audio, strings, etc...

94
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/dynamic_buffers.md


---
uid: ecs-dynamic-buffers
---
# Dynamic Buffers
A `DynamicBuffer` is a type of component data that allows a variable-sized, "stretchy"
buffer to be associated with an entity. It behaves as a component type that
carries an internal capacity of a certain number of elements, but can allocate
a heap memory block if the internal capacity is exhausted.
Memory management is fully automatic when using this approach. Memory associated with
`DynamicBuffers` is managed by the `EntityManager` so that when a `DynamicBuffer`
component is removed, any associated heap memory is automatically freed as well.
`DynamicBuffers` supersede fixed array support which has been removed.
## Declaring Buffer Element Types
To declare a `Buffer`, you declare it with the type of element that you will be
putting into the `Buffer`:
// This describes the number of buffer elements that should be reserved
// in chunk data for each instance of a buffer. In this case, 8 integers
// will be reserved (32 bytes) along with the size of the buffer header
// (currently 16 bytes on 64-bit targets)
[InternalBufferCapacity(8)]
public struct MyBufferElement : IBufferElementData
{
// These implicit conversions are optional, but can help reduce typing.
public static implicit operator int(MyBufferElement e) { return e.Value; }
public static implicit operator MyBufferElement(int e) { return new MyBufferElement { Value = e }; }
// Actual value each buffer element will store.
public int Value;
}
While it seem strange to describe the element type and not the `Buffer` itself,
this design enables two key benefits in the ECS:
1. It supports having more than one `DynamicBuffer` of type `float3`, or any
other common value type. You can add any number of `Buffers` that leverage the
same value types, as long as the elements are uniquely wrapped in a top-level
struct.
2. We can include `Buffer` element types in `EntityArchetypes`, and it generally
will behave like having a component.
## Adding Buffer Types To Entities
To add a buffer to an entity, you can use the normal methods of adding a
component type onto an entity:
### Using AddBuffer()
entityManager.AddBuffer<MyBufferElement>(entity);
### Using an archetype
Entity e = entityManager.CreateEntity(typeof(MyBufferElement));
## Accessing Buffers
There are several ways to access `DynamicBuffers`, which parallel access methods
to regular component data.
### Direct, main-thread only access
DynamicBuffer<MyBufferElement> buffer = entityManager.GetBuffer<MyBufferElement>(entity);
## Entity based access
You can also look up `Buffers` on a per-entity basis from a JobComponentSystem:
var lookup = GetBufferFromEntity<EcsIntElement>();
var buffer = lookup[myEntity];
buffer.Append(17);
buffer.RemoveAt(0);
## Reinterpreting Buffers (experimental)
`Buffers` can be reinterpreted as a type of the same size. The intention is to
allow controlled type-punning and to get rid of the wrapper element types when
they get in the way. To reinterpret, simply call `Reinterpret<T>`:
var intBuffer = entityManager.GetBuffer<EcsIntElement>().Reinterpret<int>();
The reinterpreted `Buffer` carries with it the safety handle of the original
`Buffer`, and is safe to use. They use the same underlying `BufferHeader`, so
modifications to one reinterpreted `Buffer` will be immediately reflected in
others.
Note that there are no type checks involved, so it is entirely possible to
alias a `uint` and `float` buffer.

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_anatomy.md


---
uid: ecs-anatomy
---
# Anatomy of an ECS scene
> Synopsis: Essential elements of an ECS scene in the Unity Editor. Also cover how to load and unload ECS scenes (assuming there are differences from normal -- which is certainly true with Tiny).

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_building_projects.md


---
uid: ecs-building
---
# Building your project
> Synopsis: Cover any unique aspects for building ECS projects, including any cross-platform details.

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_burst.md


---
uid: ecs-burst
---
# Using Burst
> Synopsis: Cover how, when, and why to use the Burst compiler with ECS. Everything burst -elated within ECS should go here.

37
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_components.md


---
uid: ecs-components
---
# Components
<!--
> Synopsis:componentsin detail
> What a componenti s...
> How components are managed
> General approaches for accessing components> ComponentData struct
> SharedComponentData struct
> SystemStateComponent and SystemStateSharedComponent
> BufferComponent
> ChunkComponent
> Prefab and Disabled IComponentData
> EntityQuery and filtering
-->
Components are one of the three principle elements of an Entity Component System architecture. They represent the data of your game or program. [Entities](ecs_entities.md) are essentially identifiers that index your collections of components [Systems](ecs_systems.md) provide the behavior.
Concretely, a component in ECS is a struct with one of the following "marker interfaces":
* IComponentData
* ISharedComponentData
* ISystemStateComponentData
* ISharedSystemStateComponentData
The EntityManager organizes unique combinations of components appearing on your entities into **Archetypes**. It stores the components of all entities with the same archetype together in blocks of memory called **Chunks**. The entities in a given Chunk all have the same component archetype.
Shared components are a special kind of data component that you can use to subdivide entities based on the specific values in the shared component (in addition to their archetype). When you add a shared component to an entity, the EntityManager places all entities with the same shared data values into the same Chunk. Shared components allow your systems to process like entities together. For example, the shared component `Rendering.RenderMesh`, which is part of the Hybrid.rendering package, defines several fields, including **mesh**, **material**, **receiveShadows**, etc. When rendering, it is most efficient to process all the 3D objects that all have the same value for those fields together. Because these properties are specified in a shared component the EntityManager places the matching entities together in memory so the rendering system can efficiently iterate over them.
**Note:** Over using shared components can lead to poor Chunk utilization since it involves a combinatorial expansion of the number of memory Chunks required based on archetype and every unique value of each shared component field. Avoid adding unnecessary fields to a shared component Use the [Entity Debugger](ecs_debugging.md) to view the current Chunk utilization.
If you add or remove a component from an entity, or change the value of a SharedComponent, The EntityManager moves the entity to a different Chunk, creating a new Chunk if necessary.
System state components behave like normal components or shared components with the exception that when you destroy entities, the EntityManager does not remove any system state components and does not recycle the entity ID until they are removed. This difference in behavior allows a system to cleanup its internal state or free resources when an entity is destroyed.

117
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_core.md


---
uid: ecs-concepts
---
# ECS concepts
If you are familiar with [Entity-component-system](https://en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system) (ECS) concepts, you might see the potential for naming conflicts with Unity's existing __GameObject__/__Component__ setup.
The purpose of this page is:
1. Clarify and disambiguate the concepts as used in the ECS.
2. Provide a brief introduction to each concept as an entry point to a new user.
### EntityManager
Manages memory and structural changes.
### ComponentData
Parallel streams of concrete, [blittable](https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types) data.
e.g.
| Position | HitPoints |
| ---------- | -----------|
| 64,30 | 69 |
| 58,55 | 70 |
| 95,81 | 81 |
See: [General purpose components](component_data.md)
### Entity
An ID which can be used for indirect component lookups for the purposes of graph traversal.
e.g.
| Entity | Position | HitPoints |
|--- | ---------- | -----------|
|0 | 64,30 | 69 |
|1 | 58,55 | 70 |
|2 | 95,81 | 81 |
See: [Entities](ecs_entities.md)
### SharedComponentData
Type of ComponentData where each unique value is only stored once. ComponentData streams are divided into subsets by each value of all SharedComponentData.
e.g. (Mesh SharedComponentData)
__Mesh = RocketShip__
| Position | HitPoints |
| ---------- | -----------|
| 64,30 | 69 |
| 58,55 | 70 |
| 95,81 | 81 |
__Mesh = Bullet__
| Position | HitPoints |
| ---------- | -----------|
| 10,50 | 19 |
| 36,24 | 38 |
| 67,33 | 40 |
See: [Shared components](shared_component_data.md)
### Dynamic Buffers
This is a type of component data that allows a variable-sized, "stretchy"
buffer to be associated with an entity. Behaves as a component type that
carries an internal capacity of a certain number of elements, but can allocate
a heap memory block if the internal capacity is exhausted.
See: [Dynamic Buffers](dynamic_buffers.md)
### EntityArchetype
Specific set of ComponentData types and SharedComponentData values which define the subsets of ComponentData streams stored in the EntityManager.
e.g. In the above, there are two EntityArchetypes:
1. Position, HitPoints, Mesh = RocketShip
2. Position, HitPoints, Mesh = Bullet
See: [EntityArchetype in detail](xref:Unity.Entities.EntityArchetype)
### ComponentSystem
Where gameplay/system logic/behavior occurs.
See: [ComponentSystem in detail](ecs_in_detail.md)
### World
A unique EntityManager with specific instances of defined ComponentSystems. Multiple Worlds may exist and work on independent data sets.
See: [World in detail](ecs_in_detail.md#world)
### SystemStateComponentData
A specific type of ComponentData which is not serialized or removed by default when an entity ID is deleted. Used for internal state and resource management inside a system. Allows you to manage construction and destruction of resources.
See: [SystemStateComponentData in detail](ecs_in_detail.md#systemstatecomponentdata)
### JobComponentSystem
A type of ComponentSystem where jobs are queued independently of the JobComponentSystem's update, in the background. Those jobs are guaranteed to be completed in the same order as the systems.
See: [JobComponentSystem in detail](xref:Unity.Entities.JobComponentSystem)
### EntityCommandBuffer
A list of structural changes to the data in an EntityManager for later completion. Structural changes are:
1. Adding Component
2. Removing Component
3. Changing SharedComponent value
See: [EntityCommandBuffer in detail](ecs_in_detail.md#entitycommandbuffer)
### EntityCommandBufferSystem
A type of ComponentSystem, which provides an EntityCommandBuffer. i.e. A specific (synchronization) point in the frame where that EntityCommandBuffer will be resolved.

8
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_data_structures.md


---
uid: ecs-data-structures
---
# Data structures
> Synopsis: About the Native data structures in the core module and in the extension module in detail (that isn't already covered in the script reference).
> How to create your own native data structures.

56
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_debugging.md


---
uid: ecs-debugging
---
# Debugging ECS
> Synopsis: All about debugging ECS
> Outline:
> Entity Debugger
> Inspecting an Entity
> Live-link
<a name="entity_debugger"></a>
## Entity Debugger
The Entity Debugger allows you to visualize your entities, systems, and components
Open the entity Debugger window using the menu: Window > Analysis > Entity Debugger.
<a name="systems_list"></a>
### Systems list
The Systems list shows the systems in your project and how much time a system takes to run each frame. You can turn systems on and off from the list using the checkbox provided for each system.
Use the System Display control drop down at the top of the list to control what to display in the System list. The System Display control contains:
* Worlds — Choose the World containing the entities and ComponentSystems to display. By default, an **Editor World** exists when not in play mode and a **Default World** exists in play mode.
* **Show Full Player Loop** option — Choose to display the systems of all Worlds and show all of the Unity execution phases (not just those containing systems).
* **Show Inactive Systems** option — Choose to show systems that are not currently running in addition to the running systems.
Select a system to view its details.
**Note:** If you select the EntityManager entry in the System list, then you have different options on the System details section.
<a name="system_details"></a>
### System details
The System details section shows the groups of components that a System operates on and the list of entities associated with those component groups.
Each component group shows the components in the group along with the number of entities associated with it. Select a component group to view information about the Chunks containing the data for the components in the group.
When you select the EntityManager entry in the system list, the details section shows all of the entities in the displayed World. When you display a World (rather than the full player loop), you can also filter the list of entities by component
To filter the Entity list:
1. Select a World in the System Display control.
2. Select the EntityManager for that World.
3. At the top of the System details section, click **Edit**.
4. In the **Choose Component** window, check the components whose entities you want to view.
<a name="chunk_information"></a>
### Chunk information
The Chunk information section shows the Chunks containing data for the components and entities selected in the details section.
## Inspecting an Entity
Select an entity in the Entity Debugger to view its data in the Unity Inspector window.

54
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_entities.md


---
uid: ecs-entities
---
# Entities
<!--
> Topics to add
> * Spawning Entities in Jobs -- iEntity Command Buffers
> * Transferring Entities between worlds: EM.MoveEntity
> * Coming soon: Entities with components in sub-worlds
-->
Entities are one of the three principle elements of an Entity Component System architecture. They represent the individual "things" in you game or program. An entity has neither behavior nor data; instead, it identifies which pieces of data belong together. [Systems](ecs_systems.md) provide the behavior. [Components](ecs_components.md) store the data.
An entity is essentially an ID. You can think of it as a super lightweight [GameObject](https://docs.unity3d.com/Manual/class-GameObject.html) that does not even have a name by default. entity ID's are stable. They are the only stable way to store a reference to another component or entity.
An [EntityManager](xref:Unity.Entities.EntityManager) manages all of the entities in a [World](xref:Unity.Entities.World). An EntityManager maintains the list of entities and organizes the data associated with an entity for optimal performance.
Although an entity does not have a type, groups of entities can be categorized by the types of the data components associated with them. As you create entities and add components to them, the EntityManager keeps track of the unique combinations of components on the existing entities. Such a unique combination is called an _Archetype_. The EntityManager creates an [EntityArchetype](xref:Unity.Entities.EntityArchetype) struct as you add components to an entity. You can use existing EntityArchetypes to create new entities conforming to that archetype. You can also create an EntityArchetype in advance and use that to create entities.
## Creating Entities
The easiest way to create an entity is in the Unity Editor. You can set up both GameObjects placed in a scene and Prefabs to be converted into entities at runtime. For more dynamic parts of your game or program, you can create spawning systems that create multiple entities in a job. Finally, you can create entities one at a time using one of the [EntityManager.CreateEntity](xref:Unity.Entities.EntityManager.CreateEntity) functions.
### Creating Entities with an EntityManager
Use one of the [EntityManager.CreateEntity](xref:Unity.Entities.EntityManager.CreateEntity) functions to create an entity. The entity is created in the same World as the EntityManager.
You can create entities one-by-one in the following ways:
* Create an entity with components using an array of [ComponentType](xref:Unity.Entities.ComponentType) objects.
* Create an entity with components using an [EntityArchetype](xref:Unity.Entities.EntityArchetype).
* Copy an existing entity, including its current data, with [Instantiate](xref:Unity.Entities.EntityManager.Instantiate%28Unity.Entities.Entity%29)
* Create an entity with no components and then add components to it. (You can add components immediately or as additional components are needed.)
You can create multiple entities at a time also:
* Fill a NativeArray with new entities with the same archetype using [CreateEntity](xref:Unity.Entities.EntityManager.CreateEntity).
* Fill a NativeArray with copies of an existing entity, including its current data, using [Instantiate](xref:Unity.Entities.EntityManager.Instantiate%28Unity.Entities.Entity%29).
* Explicitly create Chunks populated with a specified number of entities with a given archetype with [CreateChunk](xref:Unity.Entities.EntityManager.CreateChunk*).
## Adding and Removing Components
After an entity has been created, you can add or remove components When you do this, the archetype of the affected entities change and the EntityManager must move altered data to a new Chunk of memory, as well as condense the component arrays in the original Chunks.
Changes to an entity that cause structural changes — that is, adding or removing components changing the values of SharedComponentData, and destroying the entity — cannot be done inside a Job since these could invalidate the data that the Job is working on. Instead, you add the commands to make these types of changes to an [EntityCommandBuffer](xref:Unity.Entities.EntityCommandBuffer) and execute this command buffer after the Job is complete.
The EntityManager provides functions for removing a component from a single entity as well as all of the entities in a NativeArray. See [Components](ecs_components.md) for more information.
## Iterating entities
Iterating over all entities that have a matching set of components, is at the center of the ECS architecture. See [Accessing entity Data](chunk_iteration.md).

8
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_gameplay.md


---
uid: ecs-gameplay
---
# Creating Gameplay with ECS
<!--
> Synopsis: Introductory topic about using ECS make things happen. Should probably put any discussions of hybrid versus all-ecs solutions here (unless such discussions become too involved and need thier own page)
>

101
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_in_detail.md


---
uid: ecs-in-detail
---
# ECS features in detail
> **Note**: The main content of this page has migrated to the Unity Data-Oriented reference. ECS related features are listed below in alphabetical order, with a short description and links to further information about it. This page is not an exhaustive list and can be added to over time as ECS, and its related documentation expands. If you spot something that is out-of-date or broken links, then make sure to let us know in the [forums](http://unity3d.com/performance-by-default) or as an [issue](https://github.com/Unity-Technologies/EntityComponentSystemSamples/issues/new) in the repository.
## EntityCommandBufferSystem
When using jobs, you must request command buffers from an entity command buffer system on the main thread, and pass them to the jobs. When the `EntityCommandBufferSystem` updates, the command buffers playback on the main thread in the order they were created. This extra step is required so that memory management can be centralized and determinism of the generated entities and components can be guaranteed.
For more information, see the [EntityCommandBuffer](xref:Unity.Entities.EntityCommandBuffer) reference page.
## Chunk
A `Chunk` contains the `ComponentData` for each entity. All entities in one `Chunk` follow the same memory layout. When iterating over components, memory access of components within a `Chunk` is always completely linear, with no waste loaded into cache lines. This is a hard guarantee.
For more information, see the [Chunk](chunk_iteration.md) reference page.
## ComponentDataFromEntity
If you need to access `ComponentData` on another entity, the only stable way of referencing that component data is via the entity ID. `EntityManager` provides a simple get & set `ComponentData` API for it. However, you can't use the `EntityManager` in a C# job. `ComponentDataFromEntity` gives you a simple API that you can also safely use in a job.
For more information, see the [ComponentDataFromEntity](xref:Unity.Entities.ComponentDataFromEntity`1) reference page.
## EntityQuery
The `EntityQuery` is the foundation class on top of which all iteration methods are built `foreach`, `IJobForEach`, etc.). Essentially a `EntityQuery` is constructed with a set of required components and or subtractive components. `EntityQuery` lets you extract individual arrays of entities based on their components.
For more information, see the [EntityQuery](xref:Unity.Entities.EntityQuery) reference page.
## Entity
An entity is an ID. You can think of it as a super lightweight [GameObject](https://docs.unity3d.com/Manual/GameObjects.html) that does not even have a name by default.
You can add and remove components from entities at runtime. entity ID's are stable. They are the only stable way to store a reference to another component or entity.
For more information, see the [Entity](xref:Unity.Entities.Entity) reference page.
## EntityArchetype
An `EntityArchetype` is a unique array of `ComponentType` structs. The `EntityManager` uses `EntityArchetype`structs to group all entities using the same `ComponentType` structs into `Chunks`.
For more information, see the [EntityArchetype](xref:Unity.Entities.EntityArchetype) reference page.
## EntityCommandBuffer
The `EntityCommandBuffer` abstraction allows you to queue up changes (from either a job or from the main thread) so that they can take effect later on the main thread.
For more information, see the [EntityCommandBuffer](xref:Unity.Entities.EntityCommandBuffer) reference page.
## EntityManager
`EntityManager` is where you find APIs to create entities, check if an entity is still alive, instantiate entities and add or remove components.
For more information, see the [EntityManager](xref:Unity.Entities.EntityManager) reference page.
## ExclusiveEntityTransaction
`ExclusiveEntityTransaction` is an API to create & destroy entities from a job. The purpose is to enable procedural generation scenarios where instantiation on a big scale must happen in jobs. As the name implies, it is exclusive to any other access to the `EntityManager`.
For more information, see the [ExclusiveEntityTransaction](xref:Unity.Entities.ExclusiveEntityTransaction) reference page.
## IComponentData
`IComponentData` is a pure ECS-style component, meaning that it defines no behavior, only data. `IComponentData` is a struct rather than a class, meaning that it is copied [by value instead of by reference](https://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value?answertab=votes#tab-top) by default.
For more information, see the [ComponentData](xref:Unity.Entities.IComponentData) reference page - see "IComponentData."
## JobComponentSystem (Automatic job dependency management)
Managing dependencies is hard, which is why the `JobComponentSystem` does it automatically for you. The rules are simple: jobs from different systems can read from IComponentData of the same type in parallel. If one of the jobs is writing to the data, then they can't run in parallel and will be scheduled with a dependency between the jobs.
For more information, see the [JobComponentSystem](xref:Unity.Entities.JobComponentSystem) reference page.
## Shared ComponentData
`ISharedComponentData` is useful when many entities have something in common, for example in the `Boid` demo we instantiate many entities from the same [Prefab](https://docs.unity3d.com/Manual/Prefabs.html), and thus the `RenderMesh` between many `Boid` entities is the same.
For more information, see the [SharedComponentData](xref:Unity.Entities.ISharedComponentData) reference page.
## SystemStateComponentData
The purpose of `SystemStateComponentData` is to allow you to track resources internal to a system and have the opportunity to appropriately create and destroy those resources as needed without relying on individual callbacks.
For more information, see the [SystemStateComponent](xref:Unity.Entities.ISystemStateComponentData) reference page.
## System update order
In ECS all systems are updated on the main thread. Systems update based on a set of constraints and an optimization pass, which tries to order the systems in a way so that the time between scheduling a job and waiting for it is as long as possible.
For more information, see the [System update order](system_update_order.md) reference page.
## World
A `World` owns both an `EntityManager` and a set of `ComponentSystems`. You can create as many `World` objects as you like. Commonly you would create a simulation `World` and rendering or presentation `World`.
For more information, see the [World](xref:Unity.Entities.World) reference page.

25
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_job_extensions.md


---
uid: ecs-job-extensions
---
# Job extensions
The Unity C# Job System lets you run code on multiple threads. The system provides scheduling,
parallel processing, and multi-threaded safety. The Job System is a core Unity module that provides
the general purpose interfaces and classes for creating and running jobs (whether or not you are using ECS).
These interfaces include:
* [IJob](https://docs.unity3d.com/ScriptReference/Unity.Jobs.IJob.html) — create a Job that runs on any thread or core, as determined by the Job System scheduler.
* [IJobParallelFor](https://docs.unity3d.com/ScriptReference/Unity.Jobs.IJobParallelFor.html) — create a Job that can run on multiple threads in parallel to process the elements of a [NativeContainer](https://docs.unity3d.com/Manual/JobSystemNativeContainer.html).
* [IJobExtensions](https://docs.unity3d.com/ScriptReference/Unity.Jobs.IJobExtensions.html) — provides extension methods for running IJobs.
* [IJobParalllelForExtensions](https://docs.unity3d.com/ScriptReference/Unity.Jobs.IJobParallelForExtensions.html)— provides extension methods for running IJobParallelFor jobs.
* [JobHandle](https://docs.unity3d.com/ScriptReference/Unity.Jobs.JobHandle.html) — a handle for accessing a scheduled job. `JobHandle` instances also allow you to specify dependencies between Jobs.
For an overview of the Jobs System see [C# Job System](https://docs.unity3d.com/Manual/JobSystemSafetySystem.html) in the Unity Manual.
The Jobs package extends the Job System to support ECS. It contains:
* [IJobParallelForDeferExtensions](https://docs.unity3d.com/Packages/com.unity.jobs@0.0/api/Unity.Jobs.IJobParallelForDeferExtensions.html)
* [IJobParallelForFilter](https://docs.unity3d.com/Packages/com.unity.jobs@0.0/api/Unity.Jobs.IJobParallelForFilter.html)
* [JobParallelIndexListExtensions](https://docs.unity3d.com/Packages/com.unity.jobs@0.0/api/Unity.Jobs.JobParallelIndexListExtensions.html)
* [Job​Struct​Produce<T>](https://docs.unity3d.com/Packages/com.unity.jobs@0.0/api/Unity.Jobs.JobParallelIndexListExtensions.JobStructProduce-1.html)

44
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_job_overview.md


---
uid: ecs-jobs
---
# Jobs in ECS
ECS uses the Job system to implement behavior -- the *System* part of ECS. An ECS System is concretely a Job created to transform the data stored in entity components
For example, the following system updates positions:
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Transforms;
using UnityEngine;
public class MovementSpeedSystem : JobComponentSystem
{
[BurstCompile]
struct MovementSpeedJob : IJobForEach<Position, MovementSpeed>
{
public float dT;
public void Execute(ref Position Position, [ReadOnly] ref MovementSpeed movementSpeed)
{
float3 moveSpeed = movementSpeed.Value * dT;
Position.Value = Position.Value + moveSpeed;
}
}
// OnUpdate runs on the main thread.
protected override JobHandle OnUpdate(JobHandle inputDependencies)
{
var job = new MovementSpeedJob()
{
dT = Time.deltaTime
};
return job.Schedule(this, inputDependencies);
}
}
For more information about systems, see [ECS Systems](ecs_systems.md).

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_profiling.md


---
uid: ecs-profiling
---
# Profiling
> Synopsis: All about profiling ECS programs

16
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_project_status.md


---
uid: ecs-project-status
---
# ECS project status
# Current best practices
As the ECS APIs change, so too will these best practices. For the time being, these are our best recommendations when using the ECS APIs.
### Do's
* Use IJobForEach for processing many entities' components in a job.
* Use chunk iteration if you need finer-grained control.
### Don'ts
* Do not use injection. It is deprecated.
* Do not use ComponentDataArray. It is deprecated.

6
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_systems.md


---
uid: ecs-systems
---
# Systems
A **System**, the *S* in ECS, provides the logic that transforms the component data from its current state to its next state — for example, a system might update the positions of all moving entities by their velocity times the time interval since the previous frame.

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_testing.md


---
uid: ecs-testing
---
# Testing ECS code
> Synopsis: Using the Unity test framework with ECS. Tips for testing ECS code effectively.

164
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/ecs_write_groups.md


---
uid: ecs-writegroups
---
# WriteGroups
A common ECS pattern is for a system to read one set of *input* components and write to another, *output* component. However, you may want to override that system and update the output component based on your own set of inputs.
WriteGroups allow you to override whether a system writes to a component without having to change the overridden system. A WriteGroup identifies a set of components used as the source for writing to a particular component. The system defining that WriteGroup must also enable WriteGroup filtering on the EntityQuery objects it uses to select the entities to update.
Define a WriteGroup using the WriteGroup attribute. This attribute takes the type of the target, output component as a parameter. Place the attribute on every component used as a source when updating the target component. For example, the following declaration specifies that component A is part of the WriteGroup targeting component W:
```
[WriteGroup(typeof(W))]
public struct A : IComponentData{ public int Value; }
```
Note that the target component of the WriteGroup must be included in the query and accessed as writable. Otherwise, the WriteGroup is ignored for that query.
When you turn on WriteGroup filtering in a query, the query adds all components in a WriteGroup to the *None* list of the query unless you explicitly add them to the *All* or *Any* lists. As a result, the query only selects an entity if every component on that entity from a particular WriteGroup is explicitly required by the query. If an entity has one or more additional components from that WriteGroup, the query rejects it.
So far, WriteGroups don’t do anything that you couldn’t achieve by just rewriting the query. However, the benefit comes when you are working with a system that you cannot rewrite. You can add your own component to any WriteGroup defined by that system and, when you put that component on an entity along with the preexisting components, the system no longer selects and updates that entity. Your own system can then update the entity without contention from the other system.
**WriteGroup Example:**
Given:
* Components A and B in a WriteGroup targeting component W
* Query:
* All: A, W
* WriteGroup filtering enabled
* Entities:
| Entity X | Entity Y |
| :--------- | :---------- |
| A | A |
| W | B |
| | W |
The query selects Entity X, but not Y.
Entity Y is not selected because it has component B, which is part of the same WriteGroup, but is not required by the query. Enabling WriteGroup filtering changes the query to be:
* All: A, W
* None: B
Without WriteGroup filtering, the query would select both Entity X and Y.
**Note:** for more examples you can look at the Unity.Transforms code, which uses WriteGroups for every component it updates, including LocalToWorld.
## Creating WriteGroups
You can create WriteGroups by adding the WriteGroup attribute to the declarations of each component in the WriteGroup. The WriteGroup attribute takes one parameter, which is the type of component that the components in the group are used to update. A single component can be a member of more than one WriteGroup.
For example, if component W = A + B, then you would define a WriteGroup for W as follows:
```
public struct W : IComponentData
{
public int Value;
}
[WriteGroup(typeof(W))]
public struct A : IComponentData
{
public int Value;
}
[WriteGroup(typeof(W))]
public struct B : IComponentData
{
public int Value;
}
```
Note that you do not add the target of the WriteGroup (struct W in the example above) to its own WriteGroup.
## Enabling WriteGroup filtering
To enable WriteGroup filtering, set the FilterWriteGroups flag on the query description object you use to create the query:
```
public class AddingSystem : JobComponentSystem
{
private EntityQuery m_Query;
protected override void OnCreate()
{
var queryDescription = new EntityQueryDesc
{
All = new ComponentType[] {typeof(A), typeof(B)},
Options = EntityQueryOptions.FilterWriteGroup
};
m_Query = GetEntityQuery(queryDescription);
}
// Define Job and schedule...
}
```
## Overriding another system that uses WriteGroups
If a system defines WriteGroups for the components it writes to, you can override that system and write to those components using your own system. To override the system, add your own components to the WriteGroups defined by that system. Since WriteGroup filtering excludes any components in the WriteGroup that aren’t explicitly required by a query, any entities that have your components will then be ignored by the other system.
For example, if you wanted to set the orientation of your entities by specifying the angle and axis of rotation, you could create a component and a system to convert the angle and axis values into a quaternion and write that to the Unity.Transforms.Rotation component. To prevent the Unity.Transforms systems from updating Rotation, no matter what other components besides yours are present, you can put your component in the Rotation WriteGroup:
```
using System;
using Unity.Collections;
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
[Serializable]
[WriteGroup(typeof(Rotation))]
public struct RotationAngleAxis : IComponentData
{
public float Angle;
public float3 Axis;
}
You can then update any entities containing RotationAngleAxis without contention:
using Unity.Burst;
using Unity.Entities;
using Unity.Jobs;
using Unity.Collections;
using Unity.Mathematics;
using Unity.Transforms;
public class RotationAngleAxisSystem : JobComponentSystem
{
[BurstCompile]
struct RotationAngleAxisSystemJob : IJobForEach<RotationAngleAxis, Rotation>
{
public void Execute([ReadOnly] ref RotationAngleAxis source, ref Rotation destination)
{
destination.Value = quaternion.AxisAngle(math.normalize(source.Axis), source.Angle);
}
}
protected override JobHandle OnUpdate(JobHandle inputDependencies)
{
var job = new RotationAngleAxisSystemJob();
return job.Schedule(this, inputDependencies);
}
}
```
## Extending another system that uses WriteGroups
If you want to extend the other system rather than just override it, and further, you want to allow future systems to override or extend your system, then you can enable WriteGroup filtering on your own system. When you do this, however, no combinations of components will be handled by either system by default. You must explicitly query for and process each combination.
As an example, let’s return to the AddingSystem example described earlier, which defined a WriteGroup containing components A and B that targeted component W. If you simply add a new component, call it “C”, to the WriteGroup, then the new system that knows about C can query for entities containing C and it does not matter if those entities also have components A or B. However, if the new system also enables WriteGroup filtering, that is no longer true. If you only require component C, then WriteGroup filtering excludes any entities with either A or B. Instead, you must explicitly query for each combination of components that make sense. (You can use the “Any” clause of the query when appropriate.)
```
var query = new EntityQueryDesc
{
All = new ComponentType[] {ComponentType.ReadOnly<C>(), ComponentType.ReadWrite<W>()},
Any = new ComponentType[] {ComponentType.ReadOnly<A>(), ComponentType.ReadOnly<B>()},
Options = EntityQueryOptions.FilterWriteGroup
};
```
Any entities containing combinations of components in the WriteGroup that are not explicitly handled will not be handled by any system that writes to the target of the WriterGroup (and filters on WriteGroups). But then, it is most likely a logical error in the program to create such entities in the first place.

12
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/entities.md


# Entity
`Entity` is an ID. You can think of it as a super lightweight [GameObject](https://docs.unity3d.com/Manual/class-GameObject.html) that does not even have a name by default.
You can add and remove components from entities at runtime. entity ID's are stable. They are the only stable way to store a reference to another component or entity.
You can add and remove components from entities at runtime in much the same way as a `GameObject`. Entities can be created from [Prefabs](https://docs.unity3d.com/Manual/Prefabs.html) by using `ComponentDataProxy`. The `EntityManager` will parse the Prefab for [ComponentData](component_data.md) and add it when it creates the entity.
## Iterating entities
Iterating over all entities that have a matching set of components, is at the center of the ECS architecture.

41
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/entity_command_buffer.md


---
uid: ecs-entity-command-buffer
---
# Entity Command Buffer
The `EntityCommandBuffer` class solves two important problems:
1. When you're in a job, you can't access the `EntityManager`.
2. When you access the `EntityManager` (to say, create an entity) you invalidate all injected arrays and `EntityQuery` objects.
The `EntityCommandBuffer` abstraction allows you to queue up changes (from either a job or from the main thread) so that they can take effect later on the main thread. There are two ways to use a `EntityCommandBuffer`:
`ComponentSystem` subclasses which update on the main thread have one available automatically called `PostUpdateCommands`. To use it, simply reference the attribute and queue up your changes. They will be automatically applied to the world immediately after you return from your system's `Update` function.
Here's an example:
```cs
PostUpdateCommands.CreateEntity(TwoStickBootstrap.BasicEnemyArchetype);
PostUpdateCommands.SetComponent(new Position2D { Value = spawnPosition });
PostUpdateCommands.SetComponent(new Heading2D { Value = new float2(0.0f, -1.0f) });
PostUpdateCommands.SetComponent(default(Enemy));
PostUpdateCommands.SetComponent(new Health { Value = TwoStickBootstrap.Settings.enemyInitialHealth });
PostUpdateCommands.SetComponent(new EnemyShootState { Cooldown = 0.5f });
PostUpdateCommands.SetComponent(new MoveSpeed { speed = TwoStickBootstrap.Settings.enemySpeed });
PostUpdateCommands.AddSharedComponent(TwoStickBootstrap.EnemyLook);
```
As you can see, the API is very similar to the `EntityManager` API. In this mode, it is helpful to think of the automatic `EntityCommandBuffer` as a convenience that allows you to prevent array invalidation inside your system while still making changes to the world.
For jobs, you must request `EntityCommandBuffer` from a entity command buffer system on the main thread, and pass them to jobs. When the `EntityCommandBufferSystem` updates, the command buffers will play back on the main thread in the order they were created. This extra step is required so that memory management can be centralized and determinism of the generated entities and components can be guaranteed.
Again let's look at the two stick shooter sample to see how this works in practice.
## Entity Command Buffer Systems
The default World initialization provides three system groups, for initialization, simulation, and presentation, that are updated in order each frame. Within a group, there is an entity command buffer system that runs before any other system in the group and another that runs after all other systems in the group. Preferably, you should use one of the existing command buffer systems rather than creating your own in order to minimize synchronization points. See [Default System Groups](system_update_order.md) for a list of the default groups and command buffer systems.
## Using EntityCommandBuffers from ParallelFor jobs
When using an `EntityCommandBuffer` to issue `EntityManager` commands from [ParallelFor jobs](https://docs.unity3d.com/Manual/JobSystemParallelForJobs.html), the `EntityCommandBuffer.Concurrent` interface is used to guarantee thread safety and deterministic playback. The public methods in this interface take an extra `jobIndex` parameter, which is used to playback the recorded commands in a deterministic order. The `jobIndex` must be a unique ID for each job. For performance reasons, `jobIndex` should be the (increasing) `index` values passed to `IJobParallelFor.Execute()`. Unless you *really* know what you're doing, using the `index` as `jobIndex` is the safest choice. Using other `jobIndex` values will produce the correct output, but can have severe performance implications in some cases.

113
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/entity_iteration_foreach.md


# Using ComponentSystem
You can use a ComponentSystem to process your data. ComponentSystem methods run on the main thread and thus don’t take advantage of multiple CPU cores. Use ComponentSystems in the following circumstances:
* Debugging or exploratory development — sometimes it is easier to observe what is going on when the code is running on the main thread. You can, for example, log debug text and draw debug graphics.
* When the system needs to access or interface with other APIs that can only run on the main thread — this can help you gradually convert your game systems to ECS rather than having to rewrite everything from the start.
* The amount of work the system performs is less than the small overhead of creating and scheduling a Job.
__Important:__ Making structural changes forces the completion of all Jobs. This event is called a *sync point* and can lead to a drop in performance because the system cannot take advantage of all the available CPU cores while it waits for the sync point. In a ComponentSystem, you should use a post-update command buffer. The sync point still occurs, but all the structural changes happen in a batch, so it has a slightly lower impact. For maximum efficiency, use a JobComponentSystem and an entity command buffer. When creating a large number of entities, you can also use a separate World to create the entities and then transfer those entities to the main game world.
## Iterating with ForEach delegates
The ComponentSystem provides an Entities.ForEach function that simplifies the task of iterating over a set of entities. Call ForEach in the system’s OnUpdate() function passing in a lambda function that takes the relevant components as parameters and whose function body performs the necessary work.
The following example, from the HelloCube ForEach sample, animates the rotation for any entities that have both a RotationQuaternion and a RotationSpeed component:
public class RotationSpeedSystem : ComponentSystem
{
protected override void OnUpdate()
{
Entities.ForEach( (ref RotationSpeed rotationSpeed, ref RotationQuaternion rotation) =>
{
var deltaTime = Time.deltaTime;
rotation.Value = math.mul(math.normalize(rotation.Value),
quaternion.AxisAngle(math.up(), rotationSpeed.RadiansPerSecond * deltaTime));
});
}
You can use ForEach lambda functions with up to six types of components.
If you need to make structural changes to existing entities, you can add an Entity component to your lambda function parameters and use it to add the commands to your `ComponentSystem`'s `PostUpdateCommands` buffer. (If you were allowed to make structural changes inside the lambda function, you might change the layout of the data in the arrays you are iterating over, leading to bugs or other undefined behavior.)
For example, if you wanted to remove the RotationSpeed component form any entities whose rotation speed is currently zero, you could alter your ForEach function as follows:
``` c#
Entities.ForEach( (Entity entity, ref RotationSpeed rotationSpeed, ref RotationQuaternion rotation) =>
{
var __deltaTime __= Time.deltaTime;
rotation.Value = math.mul(math.normalize(rotation.Value),
quaternion.AxisAngle(math.up(), rotationSpeed.RadiansPerSecond * __deltaTime__));
if(math.abs(rotationSpeed.RadiansPerSecond) <= float.Epsilon) //Speed effectively zero
PostUpdateCommands.RemoveComponent(entity, typeof(RotationSpeed));
});
```
The system executes the commands in the post-update buffer after the OnUpdate() function is finished.
## Fluent Queries
You can use a [fluent-style](https://en.wikipedia.org/wiki/Fluent_interface) query to constrain a ForEach lambda such that it executes on a specific set of entities satisfying some constraints. These queries can specify whether the work should be done on entities that have any, all or none of a set of components. Constraints can be chained together and should look very familiar to users of C#'s LINQ system.
Note that any components passed as parameters to the ForEach lambda function are automatically included in the WithAll set and must not be included explicitly in the WithAll, WithAny, or WithNone portions of the query.
A **WithAll** constraint allows you to specify that an entity have all of a set of components. For example, with the following query, the ComponentSystem executes a lambda function for all entities that have the Rotation and Scale component:
```csharp
Entities.WithAll<Rotation, Scale>().ForEach( (Entity e) =>
{
// do stuff
});
```
Use WithAll for components that must exist on an entity, but which you do not need to read or write (add components that you want to access, as parameters of the ForEach lambda function). For example:
```csharp
Entities.WithAll<SpinningTag>().ForEach( (Entity e, ref Rotation r) =>
{
// do stuff
});
```
A **WithAny** constraint allows you to specify that an entity must have at least one of a set of components. The ComponentSystem executes the following lambda function for all entities that have both Rotation and Scale, AND either RenderDataA or RenderDataB (or both):
```csharp
Entities.WithAll<Rotation, Scale>().WithAny<RenderDataA, RenderDataB>().ForEach( (Entity e) =>
{
// do stuff
});
```
Note that there is no way to know which components in the WithAny set exist for a specific entity. If you need to treat entities differently depending on which of these components exist, you must either create a specific query for each situation, or use a JobComponentSystem with [IJobChunk](chunk_iteration_job.md).
A **WithNone** constraint allows you to exclude entities that have at least one of a set of components. The ComponentSystem executes the following lambda function for all entities that do not have a Rotation component:
```csharp
Entities.WithNone<Rotation>().ForEach( (Entity e) =>
{
// do stuff
});
```
Additionally, you can specify `WithAnyReadOnly` and `WithAllReadOnly` to filter for entities with any, or all (respectively) of a set of components; but also ensure that they are queried as read only components. This will ensure that they are not marked as written and their chunk IDs changed.
### Options
You can also specify a number of options for a query using **With**:
| Option | Description |
|---|---|
| Default | No options specified. |
| IncludePrefab | The query does not implicitly exclude entities with the special Prefab component. |
| IncludeDisabled | The query does not implicitly exclude entities with the special Disabled component. |
| FilterWriteGroup | The query should filter selected entities based on the WriteGroupAttribute settings of the components specified in the query. |
The ComponentSystem executes the following lambda function for all entities that do not have a Rotation component, including those that do have the special Disabled component:
```csharp
Entities.WithNone<Rotation>().With(EntityQueryOptions.IncludeDisabled).ForEach( (Entity e) =>
{
// do stuff
});
```

147
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/entity_iteration_job.md


# Using IJobForEach
You can define an `IJobForEach` Job in a JobComponentSystem to read and write component data.
When the Job runs, the ECS framework finds all of the entities that have the required components and calls the Job’s Execute() function for each of them. The data is processed in the order it is laid out in memory and the Job runs in parallel, so a `IJobForEach` combines simplicity and efficiency.
The following example illustrates a simple system that uses `IJobForEach`. The Job reads a `RotationSpeed` component and writes to a `RotationQuaternion` component.
```c#
public class RotationSpeedSystem : JobComponentSystem
{
// Use the [BurstCompile] attribute to compile a job with Burst.
[BurstCompile]
struct RotationSpeedJob : IJobForEach<RotationQuaternion, RotationSpeed>
{
public float DeltaTime;
// The [ReadOnly] attribute tells the job scheduler that this job will not write to rotSpeed
public void Execute(ref RotationQuaternion rotationQuaternion, [ReadOnly] ref RotationSpeed rotSpeed)
{
// Rotate something about its up vector at the speed given by RotationSpeed.
rotationQuaternion.Value = math.mul(math.normalize(rotationQuaternion.Value), quaternion.AxisAngle(math.up(), rotSpeed.RadiansPerSecond * DeltaTime));
}
}
// OnUpdate runs on the main thread.
// Any previously scheduled jobs reading/writing from Rotation or writing to RotationSpeed
// will automatically be included in the inputDependencies.
protected override JobHandle OnUpdate(JobHandle inputDependencies)
{
var job = new RotationSpeedJob()
{
DeltaTime = Time.deltaTime
};
return job.Schedule(this, inputDependencies);
}
}
```
Note: the above system is based on the HelloCube IJobForEach sample in the [ECS Samples repository](https://github.com/Unity-Technologies/EntityComponentSystemSamples).
## Defining the IJobForEach signature
The `IJobForEach` struct signature identifies which components your system operates on:
struct RotationSpeedJob : IJobForEach<RotationQuaternion, RotationSpeed>
You can also use the following attributes to modify which entities the Job selects:
* [ExcludeComponent(typeof(T)] — excludes entities whose Archetype contains the component of type T.
* [RequireComponentTag(typeof(T)] — only include entities whose Archetype contains a component of type T. Use this attribute when a system does not read or write to a component that still must be associated with an entity.
For example, the following Job definition selects entities that have archetypes containing Gravity, RotationQuaternion, and RotationSpeed components, but not a Frozen component:
[ExcludeComponent(typeof(Frozen))]
[RequireComponentTag(typeof(Gravity))]
[BurstCompile]
struct RotationSpeedJob : IJobForEach<RotationQuaternion, RotationSpeed>
If you need a more complex query to select the entities to operate upon, you can use an IJobChunk Job instead of IJobForEach.
## Writing the Execute() method
The JobComponentSystem calls your Execute() method for each eligible entity, passing in the components identified by the IJobForEach signature. Thus, the parameters of your Execute() function must match the generic arguments you defined for the struct.
For example, the following Execute() method reads a RotationSpeed component and reads and writes a RotationQuaternion component. (Read/write is the default, so no attribute is needed.)
public void Execute(ref RotationQuaternion rotationQuaternion, [ReadOnly] ref RotationSpeed rotSpeed){}
You can add attributes to the function parameters to help ECS optimize your system:
* [ReadOnly] — use for components that the function reads, but does not write.
* [WriteOnly] — use for components that the function writes, but does not read.
* [ChangeFilter] — use when you only want to run the function on entities for which that component value may have changed since the last time your system ran.
Identifying read-only and write-only components allows the Job scheduler to schedule your Jobs efficiently. For example, the scheduler won’t schedule a Job that writes to a component at the same time as a Job that reads that component, but it can run two Jobs in parallel if they only read the same components.
Note that for efficiency, the change filter works on whole chunks of entities; it does not track individual entities. If a chunk has been accessed by another Job which had the ability to write to that type of component, then the ECS framework considers that chunk to have changed and includes all of the entities in the Job. Otherwise, the ECS framework excludes the entities in that chunk entirely.
<a name="with-entity"></a>
## Using IJobForEachWithEntity
The Jobs implementing the IJobForEachWithEntity interface behave much the same as those implementing IJobForEach. The difference is that the Execute() function signature in IJobForEachWithEntity provides you with the Entity object for the current entity and the index into the extended, parallel arrays of components.
### Using the Entity parameter
You can use the Entity object to add commands to an EntityCommandBuffer. For example, you can add commands to add or remove components on that entity or to destroy the entity — all operations that cannot be done directly inside a Job to avoid race conditions. Command buffers allow you to perform any, potentially costly, calculations on a worker thread, while queuing up the actual insertions and deletions to be performed later on the main thread.
The following system, based on the HelloCube SpawnFromEntity sample, uses a command buffer to instantiate entities after calculating their positions in a Job:
``` c#
public class SpawnerSystem : JobComponentSystem
{
// EndFrameBarrier provides the CommandBuffer
EndFrameBarrier m_EndFrameBarrier;
protected override void OnCreate()
{
// Cache the EndFrameBarrier in a field, so we don't have to get it every frame
m_EndFrameBarrier = World.GetOrCreateSystem<EndFrameBarrier>();
}
struct SpawnJob : IJobForEachWithEntity<Spawner, LocalToWorld>
{
public EntityCommandBuffer CommandBuffer;
public void Execute(Entity entity, int index, [ReadOnly] ref Spawner spawner,
[ReadOnly] ref LocalToWorld location)
{
for (int x = 0; x < spawner.CountX; x++)
{
for (int y = 0; y < spawner.CountY; y++)
{
var __instance __= CommandBuffer.Instantiate(spawner.Prefab);
// Place the instantiated in a grid with some noise
var position = math.transform(location.Value,
new float3(x * 1.3F, noise.cnoise(new float2(x, y) * 0.21F) * 2, y * 1.3F));
CommandBuffer.SetComponent(instance, new Translation {Value = position});
}
}
CommandBuffer.DestroyEntity(entity);
}
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
// Schedule the job that will add Instantiate commands to the EntityCommandBuffer.
var job = new SpawnJob
{
CommandBuffer = m_EndFrameBarrier.CreateCommandBuffer()
}.ScheduleSingle(this, inputDeps);
// We need to tell the barrier system which job it needs to complete before it can play back the commands.
m_EndFrameBarrier.AddJobHandleForProducer(job);
return job;
}
}
```
__Note:__ this example uses IJobForEach.ScheduleSingle(), which performs the Job on a single thread. If you used the Schedule() method instead, the system uses parallel jobs to process the entities. In the parallel case, you must use a concurrent entity command buffer (EntityCommandBuffer.Concurrent).
See the [ECS samples repository](https://github.com/Unity-Technologies/EntityComponentSystemSamples) for the full example source code.
### Using the index parameter
You can use the index when adding a command to a concurrent command buffer. You use concurrent command buffers when running Jobs that process entities in parallel. In an IJobForEachWithEntity Job, the Job System process entities in parallel when you use the Schedule() method rather than the ScheduleSingle() method used in the example above. Concurrent command buffers should always be used for parallel Jobs to guarantee thread safety and deterministic execution of the buffer commands.
You can also use the index to reference the same entities across Jobs within the same system. For example, if you need to process a set of entities in multiple passes and collect temporary data along the way, you can use the index to insert the temporary data into a NativeArray in one Job and then use the index to access that data in a subsequent Job. (Naturally, you have to pass the same NativeArray to both Jobs.)

53
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/entity_manager.md


---
uid: ecs-entity-manager
---
# EntityManager
The `EntityManager` owns `EntityData`, [EntityArchetypes](xref:Unity.Entities.EntityArchetype), [SharedComponentData](xref:Unity.Entities.ISharedComponentData) and [EntityQuery](xref:Unity.Entities.EntityQuery).
`EntityManager` is where you find APIs to create entities, check if an entity is still alive, instantiate entities and add or remove components.
```cs
// Create an entity with no components on it
var entity = EntityManager.CreateEntity();
// Adding a component at runtime
EntityManager.AddComponent(entity, new MyComponentData());
// Get the ComponentData
MyComponentData myData = EntityManager.GetComponentData<MyComponentData>(entity);
// Set the ComponentData
EntityManager.SetComponentData(entity, myData);
// Removing a component at runtime
EntityManager.RemoveComponent<MyComponentData>(entity);
// Does the entity exist and does it have the component?
bool has = EntityManager.HasComponent<MyComponentData>(entity);
// Is the entity still alive?
bool has = EntityManager.Exists(entity);
// Instantiate the entity
var instance = EntityManager.Instantiate(entity);
// Destroy the created instance
EntityManager.DestroyEntity(instance);
```
```cs
// EntityManager also provides batch APIs
// to create and destroy many entities in one call.
// They are significantly faster
// and should be used where ever possible
// for performance reasons.
// Instantiate 500 entities and write the resulting entity IDs to the instances array
var instances = new NativeArray<Entity>(500, Allocator.Temp);
EntityManager.Instantiate(entity, instances);
// Destroy all 500 entities
EntityManager.DestroyEntity(instances);
```

11
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/exclusive_entity_transaction.md


---
uid: ecs-exclusive-entity-transaction
---
# ExclusiveEntityTransaction
`ExclusiveEntityTransaction` is an API to create & destroy entities from a job. The purpose is to enable procedural generation scenarios where instantiation on big scale must happen on jobs. As the name implies it is exclusive to any other access to the [EntityManager](entity_manager.md).
`ExclusiveEntityTransaction` should be used on a manually created [World](world.md) that acts as a staging area to construct & setup entities.
After the job has completed you can end the `ExclusiveEntityTransaction` and use ```EntityManager.MoveEntitiesFrom(EntityManager srcEntities);``` to move the entities to an active `World`.

8
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/execution_order.md


---
uid: ecs-execution-order
---
# Execution order
> Synopsis: The ECS equivalent to Unity Execution order of events functions (https://docs.unity3d.com/Manual/ExecutionOrder.html). Must discuss Job dependencies and barriers

37
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/filter.yml


apiRules:
- exclude:
# inherited Object methods
uidRegex: ^System\.Object\..*$
type: Method
- exclude:
# mentioning types from System.* namespace
uidRegex: ^System\..*$
type: Type
- exclude:
hasAttribute:
uid: System.ObsoleteAttribute
type: Member
- exclude:
hasAttribute:
uid: System.ObsoleteAttribute
type: Type
- include:
uidRegex: IJobForEach`1
type: Interface
- include:
uidRegex: IJobForEachWithEntity`1
type: Interface
- exclude:
uidRegex: IJobForEach
type: Interface
- exclude:
uidRegex: Unity\.Entities\.JobForEachExtensions\.IBaseJobForEach_
type: Interface
- exclude:
uidRegex: Unity\.Entities.EntityQueryBuilder
type: Delegate
- exclude:
uidRegex: Unity\.Entities.EntityQueryBuilder\.ForEach``\d
- exclude:
uidRegex: Tests$
type: Namespace

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_ai.md


---
uid: gameplay-ai
---
# Pathfinding and AI
> Synopsis: Describe how to do pathfinding and other AI tasks. At the very least, this topic must cover using existing Unity constructs such as the Nav Mesh. Ideally, the topic also covers data-oriented approaches to AI systems or provides resources for developers tackling the problem.

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_animation.md


---
uid: gameplay-animation
---
# Animation
> Synopsis: How to use Unity's animation features with ECS. How to optimize animation with ECS.

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_assets.md


---
uid: gameplay-assets
---
# Assets and resources
> Synopsis: Considerations for using Unity assets and loading resources in an ECS-based project.

8
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_audio.md


---
uid: gameplay-audio
---
# Audio
> Synopsis: How to use Unity's audio features with ECS. How to optimize audio with ECS.

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_ecs_interop.md


---
uid: gameplay-interop
---
# Sharing data between ECS and MonoBehaviours
> Synopsis: interoperation between ECS components and systems and MonoBehaviours or other managed code.

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_input.md


---
uid: gameplay-input
---
# Player input
> Synopsis: How to use Unity's input features with ECS. How to optimize input with ECS.

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_multiplayer.md


---
uid: gameplay-multiplayer
---
# Networking and Multiplayer
> Synopsis: How to use Unity's networking and multiplayer features with ECS. How to optimize networking and multiplayer with ECS.

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_physics.md


---
uid: gameplay-physics
---
# Physics
> Synopsis: How to use Unity's physics features with ECS. How to optimize physics with ECS.

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_prefabs.md


---
uid: gameplay-prefabs
---
# Prefabs
> Synopsis: Using prefabs in ECS-based programs

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_rendering.md


---
uid: gameplay-rendering
---
# Rendering
The Hybrid.Rendering package provides a ECS system to render 3D objects.

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_scenes.md


---
uid: gameplay-scenes
---
# Scenes
> Synopsis: How to organize an ECS-based project. Creating, loading, unloading scenes, etc

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_text_handling.md


---
uid: gameplay-text
---
# Handling text
> Synopsis: Handling text in a performant way

7
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/gp_ui.md


---
uid: gameplay-ui
---
# User Interfaces
> Synopsis: How to use Unity's UI features with ECS. How to optimize your UI with ECS.

4
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/images/pixel.png

之前 之后
宽度: 1  |  高度: 1  |  大小: 122 B

40
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/images/sec1-1.png

之前 之后
宽度: 675  |  高度: 69  |  大小: 10 KiB

50
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/images/sec1-2.png

之前 之后
宽度: 676  |  高度: 171  |  大小: 13 KiB

79
Packages/com.unity.entities@0.0.12-preview.33/Documentation~/images/sec2-1.png

之前 之后
宽度: 676  |  高度: 303  |  大小: 17 KiB

部分文件因为文件数量过多而无法显示

正在加载...
取消
保存