public unsafe void PoolCapacity(ParticlePool.ListPolicy policy) { const int maxParticles = 10; var pool = new ParticlePool(0, maxParticles, policy); const bool forceCreation = true; pool.FieldExists(ParticleFields.Position, forceCreation); pool.FieldExists(ParticleFields.RemainingLife, forceCreation); pool.FieldExists(ParticleFields.Velocity, forceCreation); pool.FieldExists(ParticleFields.Size, forceCreation); var testPos = new Vector3(1, 2, 3); var testVel = new Vector3(5, 6, 7); var testLife = 5f; var testSize = 4f; // Spawn all particles for (int i = 0; i < maxParticles; i++) { pool.AddParticle(); } { // Field accessors break every time there is a change in the pool, so we need to exract them every time // We can extract them before the tight loop on all living particles var positionField = pool.GetField(ParticleFields.Position); var lifetimeField = pool.GetField(ParticleFields.RemainingLife); var velocityField = pool.GetField(ParticleFields.Velocity); var sizeField = pool.GetField(ParticleFields.Size); foreach (var particle in pool) { *((Vector3 *)particle[positionField]) = testPos; *((float *)particle[lifetimeField]) = testLife; *((Vector3 *)particle[velocityField]) = testVel; *((float *)particle[sizeField]) = testSize; } } // Double the pool capacity and assert that the first half of particles still have the same fields pool.SetCapacity(2 * maxParticles); { // Field accessors break every time there is a change in the pool var positionField = pool.GetField(ParticleFields.Position); var lifetimeField = pool.GetField(ParticleFields.RemainingLife); var velocityField = pool.GetField(ParticleFields.Velocity); var sizeField = pool.GetField(ParticleFields.Size); var sorter = new ParticleSorterLiving(pool); var sortedList = sorter.GetSortedList(new Vector3(0, 0, -1)); var i = 0; foreach (var particle in sortedList) { Assert.Equal(testPos, *((Vector3 *)particle[positionField])); Assert.Equal(testLife, *((float *)particle[lifetimeField])); Assert.Equal(testVel, *((Vector3 *)particle[velocityField])); Assert.Equal(testSize, *((float *)particle[sizeField])); i++; } sorter.FreeSortedList(ref sortedList); // Assert that the number of living particles is still maxParticles, not maxParticles x2 Assert.Equal(maxParticles, i); } // Halve the pool capacity from its original size. Now all the particles should still have the same fields pool.SetCapacity(maxParticles / 2); { // Field accessors break every time there is a change in the pool var positionField = pool.GetField(ParticleFields.Position); var lifetimeField = pool.GetField(ParticleFields.RemainingLife); var velocityField = pool.GetField(ParticleFields.Velocity); var sizeField = pool.GetField(ParticleFields.Size); var sorter = new ParticleSorterLiving(pool); var sortedList = sorter.GetSortedList(new Vector3(0, 0, -1)); var i = 0; foreach (var particle in sortedList) { Assert.Equal(testPos, *((Vector3 *)particle[positionField])); Assert.Equal(testLife, *((float *)particle[lifetimeField])); Assert.Equal(testVel, *((Vector3 *)particle[velocityField])); Assert.Equal(testSize, *((float *)particle[sizeField])); i++; } sorter.FreeSortedList(ref sortedList); // Assert that the number of living particles is still maxParticles /2, not maxParticles x2 Assert.Equal(maxParticles / 2, i); } }
public unsafe void PoolFields(ParticlePool.ListPolicy policy) { const int maxParticles = 10; var pool = new ParticlePool(0, maxParticles, policy); // Spawn all particles for (int i = 0; i < maxParticles; i++) { pool.AddParticle(); } const bool forceCreation = true; // Position pool.FieldExists(ParticleFields.Position, forceCreation); var testPos = new Vector3(1, 2, 3); { // Field accessors break every time there is a change in the pool, so we need to exract them every time // We can extract them before the tight loop on all living particles var positionField = pool.GetField(ParticleFields.Position); foreach (var particle in pool) { *((Vector3 *)particle[positionField]) = testPos; } } // Life pool.FieldExists(ParticleFields.RemainingLife, forceCreation); var testLife = 5f; { // Field accessors break every time there is a change in the pool, so we need to exract them every time // We can extract them before the tight loop on all living particles var positionField = pool.GetField(ParticleFields.Position); var lifetimeField = pool.GetField(ParticleFields.RemainingLife); foreach (var particle in pool) { Assert.That(*((Vector3 *)particle[positionField]), Is.EqualTo(testPos)); *((float *)particle[lifetimeField]) = testLife; } } // Velocity pool.FieldExists(ParticleFields.Velocity, forceCreation); var testVel = new Vector3(5, 6, 7); { // Field accessors break every time there is a change in the pool, so we need to exract them every time // We can extract them before the tight loop on all living particles var positionField = pool.GetField(ParticleFields.Position); var lifetimeField = pool.GetField(ParticleFields.RemainingLife); var velocityField = pool.GetField(ParticleFields.Velocity); foreach (var particle in pool) { Assert.That(*((Vector3 *)particle[positionField]), Is.EqualTo(testPos)); Assert.That(*((float *)particle[lifetimeField]), Is.EqualTo(testLife)); *((Vector3 *)particle[velocityField]) = testVel; } } // Size pool.FieldExists(ParticleFields.Size, forceCreation); var testSize = 4f; { // Field accessors break every time there is a change in the pool, so we need to exract them every time // We can extract them before the tight loop on all living particles var positionField = pool.GetField(ParticleFields.Position); var lifetimeField = pool.GetField(ParticleFields.RemainingLife); var velocityField = pool.GetField(ParticleFields.Velocity); var sizeField = pool.GetField(ParticleFields.Size); foreach (var particle in pool) { Assert.That(*((Vector3 *)particle[positionField]), Is.EqualTo(testPos)); Assert.That(*((float *)particle[lifetimeField]), Is.EqualTo(testLife)); Assert.That(*((Vector3 *)particle[velocityField]), Is.EqualTo(testVel)); *((float *)particle[sizeField]) = testSize; } } // II. Change the capacity and assert that fields are still accessible pool.SetCapacity(2 * maxParticles); { // Field accessors break every time there is a change in the pool var positionField = pool.GetField(ParticleFields.Position); var lifetimeField = pool.GetField(ParticleFields.RemainingLife); var velocityField = pool.GetField(ParticleFields.Velocity); var sizeField = pool.GetField(ParticleFields.Size); var sorter = new ParticleSorterLiving(pool); sorter.Sort(); var i = 0; foreach (var particle in sorter) { Assert.That(*((Vector3 *)particle[positionField]), Is.EqualTo(testPos)); Assert.That(*((float *)particle[lifetimeField]), Is.EqualTo(testLife)); Assert.That(*((Vector3 *)particle[velocityField]), Is.EqualTo(testVel)); Assert.That(*((float *)particle[sizeField]), Is.EqualTo(testSize)); i++; } // Assert that the number of living particles is still maxParticles, not maxParticles x2 Assert.That(i, Is.EqualTo(maxParticles)); } // Halve the pool capacity from its original size. Now all the particles should still have the same fields pool.SetCapacity(maxParticles / 2); { // Field accessors break every time there is a change in the pool var positionField = pool.GetField(ParticleFields.Position); var lifetimeField = pool.GetField(ParticleFields.RemainingLife); var velocityField = pool.GetField(ParticleFields.Velocity); var sizeField = pool.GetField(ParticleFields.Size); var sorter = new ParticleSorterLiving(pool); sorter.Sort(); var i = 0; foreach (var particle in sorter) { Assert.That(*((Vector3 *)particle[positionField]), Is.EqualTo(testPos)); Assert.That(*((float *)particle[lifetimeField]), Is.EqualTo(testLife)); Assert.That(*((Vector3 *)particle[velocityField]), Is.EqualTo(testVel)); Assert.That(*((float *)particle[sizeField]), Is.EqualTo(testSize)); i++; } // Assert that the number of living particles is still maxParticles /2, not maxParticles x2 Assert.That(i, Is.EqualTo(maxParticles / 2)); } // III. Remove fields and assert the remaining fields are unchanged // Remove velocity pool.RemoveField(ParticleFields.Velocity); { // Field accessors break every time there is a change in the pool var positionField = pool.GetField(ParticleFields.Position); var lifetimeField = pool.GetField(ParticleFields.RemainingLife); var velocityField = pool.GetField(ParticleFields.Velocity); var sizeField = pool.GetField(ParticleFields.Size); Assert.That(velocityField.IsValid(), Is.EqualTo(false)); var sorter = new ParticleSorterLiving(pool); sorter.Sort(); var i = 0; foreach (var particle in sorter) { Assert.That(*((Vector3 *)particle[positionField]), Is.EqualTo(testPos)); Assert.That(*((float *)particle[lifetimeField]), Is.EqualTo(testLife)); Assert.That(*((float *)particle[sizeField]), Is.EqualTo(testSize)); i++; } // Assert that the number of living particles is still maxParticles /2, not maxParticles x2 Assert.That(i, Is.EqualTo(maxParticles / 2)); } // Remove size pool.RemoveField(ParticleFields.Size); { // Field accessors break every time there is a change in the pool var positionField = pool.GetField(ParticleFields.Position); var lifetimeField = pool.GetField(ParticleFields.RemainingLife); var velocityField = pool.GetField(ParticleFields.Velocity); var sizeField = pool.GetField(ParticleFields.Size); Assert.That(velocityField.IsValid(), Is.EqualTo(false)); Assert.That(sizeField.IsValid(), Is.EqualTo(false)); var sorter = new ParticleSorterLiving(pool); sorter.Sort(); var i = 0; foreach (var particle in sorter) { Assert.That(*((Vector3 *)particle[positionField]), Is.EqualTo(testPos)); Assert.That(*((float *)particle[lifetimeField]), Is.EqualTo(testLife)); i++; } // Assert that the number of living particles is still maxParticles /2, not maxParticles x2 Assert.That(i, Is.EqualTo(maxParticles / 2)); } // Remove position pool.RemoveField(ParticleFields.Position); { // Field accessors break every time there is a change in the pool var positionField = pool.GetField(ParticleFields.Position); var lifetimeField = pool.GetField(ParticleFields.RemainingLife); var velocityField = pool.GetField(ParticleFields.Velocity); var sizeField = pool.GetField(ParticleFields.Size); Assert.That(velocityField.IsValid(), Is.EqualTo(false)); Assert.That(sizeField.IsValid(), Is.EqualTo(false)); Assert.That(positionField.IsValid(), Is.EqualTo(false)); var sorter = new ParticleSorterLiving(pool); sorter.Sort(); var i = 0; foreach (var particle in sorter) { Assert.That(*((float *)particle[lifetimeField]), Is.EqualTo(testLife)); i++; } // Assert that the number of living particles is still maxParticles /2, not maxParticles x2 Assert.That(i, Is.EqualTo(maxParticles / 2)); } }