├── README.md ├── .gitignore ├── LICENSE └── BufferWithJobSystem.cs /README.md: -------------------------------------------------------------------------------- 1 | Unity DOTS-ECS very simple example with IJobForEachWithEntity, IJobForEach_BC and IBufferElementData. 2 | 3 | Updated 2019.12.10 4 | 5 | 6 | Requires Unity 2020.1.0a15+ 7 | 8 | 9 | Tested with 10 | 11 | Burst 1.2.0-preview.10 12 | 13 | Collections 0.2.0-Preview.13 14 | 15 | Entities 0.2.0-preview.18 16 | 17 | Jobs 0.2.1-Preview.3 18 | 19 | Mathematics 1.1.0.preview.1 20 | 21 | See official discussion 22 | 23 | https://forum.unity.com/threads/example-ijobforeach-and-ibufferelementdata-unity-2020-1.584548/ 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | [Ll]ibrary/ 2 | [Tt]emp/ 3 | [Oo]bj/ 4 | [Bb]uild/ 5 | [Bb]uilds/ 6 | Assets/AssetStoreTools* 7 | 8 | # Visual Studio cache directory 9 | .vs/ 10 | 11 | # Autogenerated VS/MD/Consulo solution and project files 12 | ExportedObj/ 13 | .consulo/ 14 | *.csproj 15 | *.unityproj 16 | *.sln 17 | *.suo 18 | *.tmp 19 | *.user 20 | *.userprefs 21 | *.pidb 22 | *.booproj 23 | *.svd 24 | *.pdb 25 | *.opendb 26 | 27 | # Unity3D generated meta files 28 | *.pidb.meta 29 | *.pdb.meta 30 | 31 | # Unity3D Generated File On Crash Reports 32 | sysinfo.txt 33 | 34 | # Builds 35 | *.apk 36 | *.unitypackage 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Dobromił Duda 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /BufferWithJobSystem.cs: -------------------------------------------------------------------------------- 1 | // Unity ECS very simple example with IJobForEachWithEntity, IJobForEach_BC and IBufferElementData. 2 | 3 | // 2019.12.10 4 | 5 | // Requires Unity 2020.1.0a15+ 6 | 7 | // Tested with 8 | // Burst 1.2.0-preview.10 9 | // Collections 0.2.0-Preview.13 10 | // Entities 0.2.0-preview.18 11 | // Jobs 0.2.1-Preview.3 12 | // Mathematics 1.1.0.preview.1 13 | 14 | using Unity.Collections ; 15 | using Unity.Entities ; 16 | using Unity.Jobs ; 17 | using Unity.Burst ; // See commented out [BurstCompile] lines, above jobs. 18 | 19 | using UnityEngine ; 20 | 21 | namespace ECS.Test 22 | { 23 | 24 | struct Instance : IComponentData 25 | { 26 | public float f ; 27 | } 28 | 29 | // For testing in Job_BC 30 | struct SomeBufferElement : IBufferElementData 31 | { 32 | public int i ; 33 | } 34 | 35 | // For testing in JobWithEntity 36 | struct SomeFromEntityBufferElement : IBufferElementData 37 | { 38 | public int i ; 39 | } 40 | 41 | public class BufferWithJobSystem : JobComponentSystem 42 | { 43 | 44 | // protected override void OnCreateManager ( int capacity ) // Obsolete 45 | protected override void OnCreate ( ) 46 | { 47 | base.OnCreate ( ) ; 48 | 49 | Debug.LogWarning ( "Burst is disabled, to use Debug.Log in jobs." ) ; 50 | Debug.LogWarning ( "Jobs are executed approx every second." ) ; 51 | 52 | Instance instance = new Instance () ; 53 | 54 | Entity entity = EntityManager.CreateEntity ( typeof (Instance) ) ; 55 | 56 | EntityManager.SetComponentData ( entity, instance ) ; 57 | EntityManager.AddBuffer ( entity ) ; 58 | 59 | DynamicBuffer someBuffer = EntityManager.GetBuffer ( entity ) ; 60 | 61 | // Add two elements to dynamic buffer. 62 | SomeBufferElement someBufferElement = new SomeBufferElement () ; 63 | someBufferElement.i = 100000 ; 64 | someBuffer.Add ( someBufferElement ) ; 65 | someBufferElement.i = 200000 ; 66 | someBuffer.Add ( someBufferElement ) ; 67 | 68 | EntityManager.Instantiate ( entity ) ; // Clone entity. 69 | 70 | 71 | entity = EntityManager.CreateEntity ( typeof (Instance) ) ; 72 | 73 | EntityManager.SetComponentData ( entity, instance ) ; 74 | EntityManager.AddBuffer ( entity ) ; 75 | 76 | DynamicBuffer someFromEntityBuffer = EntityManager.GetBuffer ( entity ) ; 77 | 78 | // Add two elements to dynamic buffer. 79 | SomeFromEntityBufferElement someFromEntityBufferElement = new SomeFromEntityBufferElement () ; 80 | someFromEntityBufferElement.i = 1000 ; 81 | someFromEntityBuffer.Add ( someFromEntityBufferElement ) ; 82 | someFromEntityBufferElement.i = 10 ; 83 | someFromEntityBuffer.Add ( someFromEntityBufferElement ) ; 84 | 85 | EntityManager.Instantiate ( entity ) ; // Clone entity. 86 | 87 | } 88 | 89 | float previoudTime = 0 ; 90 | 91 | protected override JobHandle OnUpdate ( JobHandle inputDeps ) 92 | { 93 | 94 | float time = Time.time ; 95 | 96 | // Execute approx every second. 97 | if ( time > previoudTime + 1 ) 98 | { 99 | previoudTime = time ; 100 | } 101 | else 102 | { 103 | return inputDeps ; 104 | } 105 | 106 | JobHandle job_withEntity = new Job_WithEntity () 107 | { 108 | time = time, 109 | someBuffer = GetBufferFromEntity ( false ) // Read and write 110 | 111 | }.ScheduleSingle ( this, inputDeps ) ; // Using instead job.Schedule ( this, inputDeps ), for single threaded test and debug. 112 | // }.Schedule ( this, inputDeps ) ; // Allow execute job in parallel, if there is enough entities. 113 | 114 | JobHandle job_BC = new Job_BC () 115 | { 116 | time = time, 117 | 118 | }.ScheduleSingle ( this, job_withEntity ) ; // Using instead job.Schedule ( this, inputDeps ), for single threaded test and debug. 119 | // }.Schedule ( this, jobWithEntity ) ; // Allow execute job in parallel, if there is enough entities. 120 | 121 | return job_BC ; 122 | } 123 | 124 | // [BurstCompile] // Disbaled burst, as Debug.Log is used. 125 | [RequireComponentTag ( typeof (SomeFromEntityBufferElement ) ) ] 126 | // struct Job: IJobProcessComponentDataWithEntity // Obsolete 127 | struct Job_WithEntity : IJobForEachWithEntity 128 | { 129 | public float time; 130 | 131 | // Allow buffer read write in parralel jobs 132 | // Ensure, no two jobs can write to same entity, at the same time. 133 | // !! "You are somehow completely certain that there is no race condition possible here, because you are absolutely certain that you will not be writing to the same Entity ID multiple times from your parallel for job. (If you do thats a race condition and you can easily crash unity, overwrite memory etc) If you are indeed certain and ready to take the risks. 134 | // https://forum.unity.com/threads/how-can-i-improve-or-jobify-this-system-building-a-list.547324/#post-3614833 135 | [NativeDisableParallelForRestriction] 136 | public BufferFromEntity someBuffer ; 137 | 138 | public void Execute( Entity entity, int index, ref Instance tester ) 139 | { 140 | tester.f = time ; 141 | 142 | DynamicBuffer dynamicBuffer = someBuffer [entity] ; 143 | 144 | SomeFromEntityBufferElement bufferElement = dynamicBuffer [0] ; 145 | bufferElement.i ++ ; // Increment. 146 | dynamicBuffer [0] = bufferElement ; // Set back. 147 | 148 | // Console will throw error when using debug and burst is enabled. 149 | // Comment out Debug, when using burst. 150 | Debug.Log ( "T: " + tester.f + " IJobForEachWIthEntity " + " #" + index + "; entity: " + entity + "; " + dynamicBuffer [0].i + "; " + dynamicBuffer [1].i ) ; 151 | 152 | } 153 | 154 | } 155 | 156 | // [BurstCompile] // Disbaled burst, as Debug.Log is used. 157 | struct Job_BC : IJobForEach_BC 158 | { 159 | public float time; 160 | 161 | // Allow buffer read write in parralel jobs 162 | // Ensure, no two jobs can write to same entity, at the same time. 163 | public void Execute( DynamicBuffer dynamicBuffer, ref Instance tester ) 164 | { 165 | tester.f = time ; 166 | 167 | 168 | SomeBufferElement bufferElement = dynamicBuffer [0] ; 169 | bufferElement.i ++ ; // Increment. 170 | dynamicBuffer [0] = bufferElement ; // Set back. 171 | 172 | // Console will throw error when using debug and burst is enabled. 173 | // Comment out Debug, when using burst. 174 | Debug.Log ( "T: " + tester.f + " IJobForEach_BC (Buffer, Component) " + "; " + dynamicBuffer [0].i + "; " + dynamicBuffer [1].i ) ; 175 | 176 | } 177 | 178 | } 179 | 180 | } 181 | } 182 | --------------------------------------------------------------------------------