I have a script that allows me to create an explosion effect on a sprite. It iterates through each pixel of the sprite (24x24 on average) and creates a 1x1 pixel game object for each pixel with the color of the original pixel. It then gives each pixel a random velocity. This creates the effect that the sprite is exploding into it’s individual pixels and looks pretty cool.
My issue is that when using this on larger sprites or on more than 5 sprites at once I run into some performance issues and lag spikes. I can’t really use an object pool for this since the pixels have to be specific to the object’s current sprite during it’s animation.
How could I optimize the code below?
using UnityEngine;
using System.Collections;
public class ExplodeEffect : MonoBehaviour
{
public GameObject pixelPrefab;
public void Explode(Vector3 velocity, Sprite sprite)
{
for (int i = 0; i <= sprite.bounds.size.x * 10f; i++)
{
for (int j = 0; j <= sprite.bounds.size.y * 10f; j++)
{
Vector2 positionOffest = new Vector2(sprite.bounds.extents.x - sprite.bounds.center.x,
sprite.bounds.extents.y - sprite.bounds.center.y - 0.05f);
Vector3 pixelPosition = transform.TransformPoint((i / 10f) - positionOffest.x,
(j / 10f) - positionOffest.y, 0);
Color pixelColor = sprite.texture.GetPixel((int)sprite.rect.x + i,
(int)sprite.rect.y + j);
if (pixelColor.a != 0f)
{
GameObject pixelInstance = Instantiate(pixelPrefab, pixelPosition, Quaternion.identity) as GameObject;
pixelInstance.GetComponent<SpriteRenderer>().color = pixelColor;
pixelInstance.rigidbody2D.AddForce(new Vector2(((velocity.x * 10f) + Random.Range(-250, 250)) * 2.5f,
((velocity.y * 10f) + Random.Range(-250, 300)) * 2.5f));
}
}
}
}
}
Update:
Thanks to @Bunny83 I got a working particle system implementation.
Below is my modified version of his code.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class SpriteExplosion : MonoBehaviour
{
public float pixelsPerUnit = 10f;
public float lifetime = 4f;
public string sortingLayer = "Foreground";
public int sortingOrder = 1;
public void Explode(Vector3 velocity, Sprite sprite)
{
StartCoroutine(DoExplode(velocity, sprite));
}
private IEnumerator DoExplode(Vector3 velocity, Sprite sprite)
{
ParticleSystem partSystem = GetComponent<ParticleSystem>();
List<ParticleSystem.Particle> particles = new List<ParticleSystem.Particle>();
ParticleSystem.Particle currentParticle = new ParticleSystem.Particle();
partSystem.renderer.sortingLayerName = sortingLayer;
partSystem.renderer.sortingOrder = sortingOrder;
currentParticle.size = 1f / pixelsPerUnit;
for (int i = 0; i < sprite.bounds.size.x * 10f; i++)
{
for (int j = 0; j < sprite.bounds.size.y * 10f; j++)
{
Vector2 positionOffset = new Vector2(sprite.bounds.extents.x - sprite.bounds.center.x - 0.05f,
sprite.bounds.extents.y - sprite.bounds.center.y - 0.05f);
Vector3 particlePosition = transform.TransformPoint((i / 10f) - positionOffset.x,
(j / 10f) - positionOffset.y, 0);
Color particleColor = sprite.texture.GetPixel((int)sprite.rect.x + i,
(int)sprite.rect.y + j);
if (particleColor.a != 0f)
{
currentParticle.position = particlePosition;
currentParticle.rotation = 0f;
currentParticle.color = particleColor;
currentParticle.startLifetime = currentParticle.lifetime = lifetime;
currentParticle.velocity = new Vector2(velocity.x + Random.Range(-5f, 5f),
velocity.y + Random.Range(-5f, 6f));
particles.Add(currentParticle);
}
}
}
partSystem.SetParticles(particles.ToArray(), particles.ToArray().Length);
Destroy(gameObject, lifetime);
yield return new WaitForSeconds(1f);
}
}