- Home /
How can I serialize the Particles of a Particle Emitter
I want to save the array of Particles returned by the particles property so that I can load it at a later time. How can I do this?
Answer by ricardo_arango · Nov 24, 2011 at 04:48 PM
You can use .net marshalling to save the array of particles (structs). First you need to convert the array to a byte[], then save it as a binary file. To load you would read each particle, and convert from byte[] to a Particle struct.
Create a CSharp script named SerializeParticles .cs. Copy/paste the following code:
using UnityEngine;
public class SerializeParticles : MonoBehaviour
{
}
You need to attach the previous script to the GameObjec with the particle emitter component.
Create another CSharp script named CustomInspectorParticles.cs and place it inside an Editor folder. Copy/paste the following code:
using System.IO;
using UnityEngine;
using UnityEditor;
using System;
using System.Runtime.InteropServices;
[CustomEditor(typeof(SerializeParticles))]
public class CustomInspectorParticles : Editor
{
public override void OnInspectorGUI()
{
var t = target as SerializeParticles;
if (t != null){
if (GUILayout.Button("Load Particle Data"))
t.gameObject.GetComponent<ParticleEmitter>().particles = LoadParticleData();
if (GUILayout.Button("Save Particle Data"))
SaveParticleData(t.gameObject.GetComponent<ParticleEmitter>().particles);
}
if (GUI.changed)
EditorUtility.SetDirty(target);
}
static Particle[] LoadParticleData()
{
// Load the byte array
var fs = new FileStream(Application.dataPath + "/particleData.asset", FileMode.Open, FileAccess.Read, FileShare.None);
// Number of particles
var dataSize = Marshal.SizeOf(new Particle());
var numParticles = ((int)fs.Length / dataSize);
var particles = new Particle[numParticles];
// Create a byte[] to hold all the particle data
var byteArray = new byte[dataSize];
var pointer = Marshal.AllocHGlobal(dataSize);
try {
for (var i = 0; i < numParticles; i++) {
// Read the bytes of a particle
fs.Read(byteArray, 0, dataSize);
// Copy the byteArray to unmanaged memory
Marshal.Copy(byteArray, 0, pointer, dataSize);
// Particle in unmanaged memory
particles[i] = (Particle)Marshal.PtrToStructure(pointer, typeof(Particle));
}
}
finally {
// Free the unmanaged memory.
Marshal.FreeHGlobal(pointer);
}
fs.Close();
return particles;
}
static void SaveParticleData(Particle[] particles)
{
if (particles == null)
return;
if (particles.Length == 0)
return;
// Size of the entire array
int totalSize = Marshal.SizeOf(new Particle()) * particles.Length;
int dataSize = Marshal.SizeOf(new Particle());
// Create a byte[] to hold all the particles, but only one can be copied at the time
var byteArray = new byte[totalSize];
IntPtr pointer = Marshal.AllocHGlobal(Marshal.SizeOf(new Particle()));
try {
for (var i = 0; i < particles.Length; i++) {
Marshal.StructureToPtr(particles[i], pointer, false);
Marshal.Copy(pointer, byteArray, i * dataSize, dataSize);
}
}
finally {
// Free the unmanaged memory.
Marshal.FreeHGlobal(pointer);
}
// Save the byte array
var fs = new FileStream(Application.dataPath + "/particleData.asset", FileMode.Create, FileAccess.Write, FileShare.None);
// Save the particle data
fs.Write(byteArray, 0, byteArray.Length);
fs.Close();
}
}
[Note: This code is a guideline, it needs more data validation]
Your answer
Follow this Question
Related Questions
container class save based on Cherno's example 1 Answer
Delete a serialized binary save file 2 Answers
Save and load a class 0 Answers
Serialize GameObject 1 Answer