Search Unity

Particle Playground

Discussion in 'Assets and Asset Store' started by save, Dec 4, 2013.

  1. DMeville


    May 5, 2013
    - I'm not sure what I did, but I seemed to fix the hierarchy exploding with objects, I must have done something wrong but it's not happening anymore.. :)

    - It doesn't seem to happen in Play mode, which is the most important thing I suppose. It seems to be happening the most when I change the selection of the hierarchy in edit mode. E.g. I have two particle systems with trails. System A is selected to so it autoplays in the editor. I select System B and things go stringy like in the image. Not a huge problem upon inspecting it further though, because it doesn't seem to happen in play mode.

    One more question; Any way to disable trails casting shadows?
  2. save


    Nov 21, 2008
    If it comes back let me know! It should be a fairly simple fix as well. :)
    Will have a closer look into the Editor throwing end-points to start location, it's great if we can keep it somewhat true to runtime when editing.

    Shadow settings etc. is coming up very soon, right now that part needs to be handled in the shader for the material you're using. Hang in there!
    DMeville likes this.
  3. DMeville


    May 5, 2013
    Cool cool. I didn't think it's shader related, using a custom shader on my trails anyways.
    Maybe let us assign a mesh renderer to the trail component, and copy the values from that per trail?

    Adding this in PlaygroundTrails.cs - line 470 is a quick fix.
    Code (CSharp):
    1. newTrail.trailRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
  4. save


    Nov 21, 2008
    And of course you could hack the code for an even quicker fix. :) Will give you proper Inspector values soon though!
    hopeful and DMeville like this.
  5. AGeorgy


    Sep 16, 2013
    The problem with this:

    Attached Files:

  6. Simie


    Oct 26, 2012
    Hey @save, I'm considering using Particle Playground for my project (I already bought it back when v2 was released because of your excellent demo videos!).

    In my game I have particles that are affected by the air-velocity of the tile they occur on (example video: link). Is it possible in PP to have a custom affector that can lookup this velocity data based on the particle position?
  7. save


    Nov 21, 2008
    Hey Georgy, I sent you an email with the solution. The problem is that you're using a Playground Spline as a Source and not a Manipulator to move the particles. There are two general ways of moving particle like this, one is through a Manipulator using the Particle Time as Target Method and one is using it as a Source without a Manipulator and offsetting the Spline Time.

    Hey, happy to hear that!
    Indeed there is, you could try use Manipulators with shape as a box in case there isn't crazy many different in the grid. If there is I would suggest the alternative of using a lookup table of rects and access the particles cached array to insert your velocity through script. It should be fairly quick to implement. What you then would be using is the PlaygroundCache to edit the particle data.

    I will have better suggestions later down the road when implementing vector fields though. :)
  8. save


    Nov 21, 2008
  9. Anglerteam-Games


    Mar 27, 2014

    I'm mostly enjoying my time with PP so far, but I have a seemingly simple thing I want to do and I can't figure out how to do it.

    I would like a fractional, evenly-spaced emission rate. The "emission rate" seems to just emit for the first fraction, then nothing for the rest of the loop, no matter what the lifetime sorting is. I am not sure what "lifetime emission" does, but it's not what I want it to do.

    Any thoughts?

    The goal is to have a mesh-based state with, say 1024 particles, lifetime 1, but emit one particle only once every 0.1s, for instance.
  10. DMeville


    May 5, 2013
    I have a feature request, that may or may not be outside the scope of the project.. :)

    I see that you have a SplineMesh component, that renders a quad strip along the spline, what about something similar, but instead renders a tube around the spline.

    I made something similar, although sloppy, that makes a tube and follows along when the spline is deformed - although it's not super performant it adds some cool looks to some effects!
  11. DangerFro


    Oct 18, 2012

    I've been exploring different fx packages for Unity since Shuriken doesn't have the functionality that the company I work for is looking for. For the most part we've been making use of popcornfx most recently, but we're interested in the possibilities that particle playground presents.

    My main curiosity at this time is if particle playground has a functionality similar to what popcornfx presents here:

    In short it allows a particle system to move across the surface of a mesh regardless of UV's or normal direction, with eventual hopes of developing it to apply to skinned meshes as well. The closest function that generates similar results that I've been able to find within PP is the Source Scatter coupled with Lifetime Sorting.

    Even if this isn't currently possible to replicate, I'm sure it'd make for an excellent feature in the future.
  12. DMeville


    May 5, 2013
    It came back. Every time I hit play a new trail object is created, and on cancel it's not destroyed. :(
  13. ian_facepunch


    Mar 16, 2015
    I've got the same issue with the trails. I've had a quick look at the code and it seems that they get destroyed when the application calls OnDestroy from play mode but then created again in OnEnable inside the editor. This new object doesn't get removed when switching back again from the editor to play mode.

    Any way to get a quick fix for this?
    DMeville likes this.
  14. save


    Nov 21, 2008
    Currently that is unfortunately not possible due to the lifetime sorting and particle time structure. It is something I really want to address but will take time as there's so many nested features depending on this structure.
    There is a more advanced scripted emission coming soon which enables iteration over another Source, which I believe would be a perfect approach in your type of scenario. This means you will be able to call emission on a specific source point created by a State for example with a custom lifetime setting on your particles.

    Sounds like a fun side project, if I make one I'll make sure to post it. :) Otherwise feel free to dissect and improve PlaygroundSplineMesh.cs!

    Hi! You can for example use the Source: Projection, but that requires colliders which raycasts from a texture can bounce on. Otherwise masking for meshes and skinned meshes is on the roadmap, which would potentially produce something very similar, but it would require to still birth at vertices (or scattered positions from them). Indeed a good feature for the future!

    Quick fix is coming up very soon, hopefully tonight together with a fix for an issue found with creating Snapshots.
  15. save


    Nov 21, 2008
    Quick fixes are up!

    Let me know how it works. The Playground Trails issue I was never able to reproduce, however the alternative approach should work better as it has a verification on its necessity to exist.
  16. save


    Nov 21, 2008
    I got a question recently how to play audio on particle collisions. This is something I haven't addressed yet with the example scenes or the script library but is something you many times want to do. One really easy way of approaching this is by adding or modifying this script: :)

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using ParticlePlayground;
    5. public class PlayAudioOnParticleCollision : MonoBehaviour {
    7.     public PlaygroundParticlesC particles;
    8.     public GameObject audioSourceReference;
    9.     public int audioSourcePoolCount = 10;
    10.     public float randomPitch = .1f;
    12.     private AudioSource[] _audioSourcePool;
    13.     private int _audioSourceIndex = 0;
    14.     private PlaygroundEventC _collisionEvent;
    16.     void OnEnable ()
    17.     {
    18.         // Create the audio pool based on the audio source reference
    19.         AudioSource sourceRef = audioSourceReference.GetComponent<AudioSource>();
    20.         sourceRef.playOnAwake = false;
    21.         _audioSourcePool = new AudioSource[audioSourcePoolCount];
    22.         for (int i = 0; i<_audioSourcePool.Length; i++)
    23.         {
    24.             GameObject go = (GameObject)Instantiate (audioSourceReference);
    25.             go.transform.parent = transform;
    26.             _audioSourcePool[i] = go.GetComponent<AudioSource>();
    27.         }
    29.         // Try to get the particle system on the GameObject this script is attached to
    30.         if (particles == null)
    31.             particles = GetComponent<PlaygroundParticlesC>();
    33.         // Set event reference if collision event already exists
    34.         foreach (PlaygroundEventC e in
    35.         {
    36.             if (e.eventType == EVENTTYPEC.Collision && (e.broadcastType == EVENTBROADCASTC.EventListeners || e.broadcastType == EVENTBROADCASTC.Both))
    37.             {
    38.                 _collisionEvent = e;
    39.                 break;
    40.             }
    41.         }
    43.         // Otherwise create the event
    44.         if (_collisionEvent == null)
    45.         {
    46.             _collisionEvent = PlaygroundC.CreateEvent(particles);
    47.             _collisionEvent.eventType = EVENTTYPEC.Collision;
    48.             _collisionEvent.broadcastType = EVENTBROADCASTC.EventListeners;
    49.         }
    51.         // Start listening to the event
    52.         _collisionEvent.particleEvent += OnParticleCollisionEvent;
    53.     }
    55.     void OnDisable ()
    56.     {
    57.         // Remove the event whenever disabling this component
    58.         if (_collisionEvent != null)
    59.             _collisionEvent.particleEvent -= OnParticleCollisionEvent;
    60.     }
    62.     void OnParticleCollisionEvent (PlaygroundEventParticle eventParticle)
    63.     {
    64.         // Position the audio source
    65.         _audioSourcePool[_audioSourceIndex].transform.position = eventParticle.collisionParticlePosition;
    67.         // Randomize the pitch
    68.         _audioSourcePool[_audioSourceIndex].pitch = Random.Range (1f-randomPitch, 1f+randomPitch);
    70.         // Play the audio
    71.         _audioSourcePool[_audioSourceIndex].Play();
    73.         // Increment index
    74.         _audioSourceIndex = (_audioSourceIndex + 1) % _audioSourcePool.Length;
    76.         // Remember that the eventParticle has more info about the particle, for example:
    77.         //
    78.         // eventParticle.size
    79.         // eventParticle.position
    80.         // eventParticle.velocity
    81.         // eventParticle.collisionCollider
    82.         //
    83.         // and so on!
    84.     }
    85. }
    hopeful likes this.
  17. Image3d


    Jun 20, 2008

    How do I start the play of a recorded particle at Runtime ?
  18. save


    Nov 21, 2008
    In short you could use recorder.Play(). To give some better understanding of how it works;
    The Playground Recorder Data object (a Scriptable Object) store information about the particles in a per-recorded-frame structure whenever assigned and recording. It is not necessary to assign one if both recording and playback happens during runtime in the same session (for example instant replay).
    To replay between sessions you must have assigned a Playground Recorder Data object to the Playground Recorder. Any Particle Playground system will be able to replay a recording, even if the recording didn't originate from it.
    Loading of the data happens during OnEnable of the Playground Recorder and is an asynchronous procedure if you have enabled Playground Recorder > Advanced > Multithreading.

    There's quite some things supported in the recorder, here's a cheat sheet for the most common operations:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using ParticlePlayground;
    5. public class RecorderExamples : MonoBehaviour {
    7.     /// <summary>
    8.     /// The reference to the Playground Recorder.
    9.     /// </summary>
    10.     public PlaygroundRecorder recorder;
    13.     /***********************************************************************************
    14.         Playback control
    15.     ***********************************************************************************/
    17.     /// <summary>
    18.     /// Starts the playback of this Playground Recorder.
    19.     /// </summary>
    20.     public void Play ()
    21.     {
    22.         recorder.Play ();
    23.     }
    25.     /// <summary>
    26.     /// Starts the playback of this Playground Recorder with specified playback speed.
    27.     /// </summary>
    28.     /// <param name="speed">The speed of the playback.</param>
    29.     public void Play (float speed)
    30.     {
    31.         recorder.Play (speed);
    32.     }
    34.     /// <summary>
    35.     /// Starts the playback of this Playground Recorder with specified starting point, playback speed and if looping should occur.
    36.     /// </summary>
    37.     /// <param name="fromNormalizedTime">From normalized time in recording.</param>
    38.     /// <param name="speed">The speed of the playback.</param>
    39.     /// <param name="repeat">If set to <c>true</c> then enable looping.</param>
    40.     public void Play (float fromNormalizedTime, float speed, bool repeat)
    41.     {
    42.         recorder.Play (fromNormalizedTime, speed, repeat);
    43.     }
    45.     /// <summary>
    46.     /// Pauses the playback of this Playground Recorder.
    47.     /// </summary>
    48.     public void Pause ()
    49.     {
    50.         recorder.Pause ();
    51.     }
    53.     /// <summary>
    54.     /// Stops the playback and recording of this Playground Recorder.
    55.     /// </summary>
    56.     public void Stop ()
    57.     {
    58.         recorder.Stop ();
    59.     }
    61.     /// <summary>
    62.     /// Scrub to specified time in particle recording. This will linearly interpolate between the closest recorded frames of the passed in time (normalized between 0f - 1f).
    63.     /// </summary>
    64.     /// <param name="normalizedTime">The normalized time (0f to 1f).</param>
    65.     public void Scrub (float normalizedTime)
    66.     {
    67.         recorder.Scrub (normalizedTime);
    68.     }
    70.     /// <summary>
    71.     /// Sets the speed of the playback. Set this to a negative value to make the playback go backwards.
    72.     /// </summary>
    73.     public void SetPlaybackSpeed (float speed)
    74.     {
    75.         recorder.playbackSpeed = speed;
    76.     }
    78.     /// <summary>
    79.     /// Determines if the playback should loop when reaching the end of the recording.
    80.     /// </summary>
    81.     public void SetPlaybackLoop (bool loop)
    82.     {
    83.         recorder.loopPlayback = loop;
    84.     }
    87.     /***********************************************************************************
    88.         Record control
    89.     ***********************************************************************************/
    91.     /// <summary>
    92.     /// Starts a recording until StopRecording() is called. This overload will by default use the previously set keyframe interval during recording.
    93.     /// </summary>
    94.     public void StartRecording ()
    95.     {
    96.         recorder.StartRecording ();
    97.     }
    99.     /// <summary>
    100.     /// Starts a recording until StopRecording() is called. This overload takes a keyframe interval as parameter.
    101.     /// </summary>
    102.     /// <param name="keyframeInterval">The Keyframe Interval determines the rate of created keyframes (measured in seconds where 1f is 1 second).</param>
    103.     public void StartRecording (float keyframeInterval)
    104.     {
    105.         recorder.StartRecording (keyframeInterval);
    106.     }
    108.     /// <summary>
    109.     /// Starts a recording with specified length or until StopRecording() is called. This overload takes a recording length and keyframe interval as parameter.
    110.     /// </summary>
    111.     /// <param name="recordingLength">The amount of seconds the recording should be.</param>
    112.     /// <param name="keyframeInterval">The Keyframe Interval determines the rate of created keyframes (measured in seconds where 1f is 1 second).</param>
    113.     public void StartRecording (float recordingLength, float keyframeInterval)
    114.     {
    115.         recorder.StartRecording (recordingLength, keyframeInterval);
    116.     }
    118.     /// <summary>
    119.     /// Records one frame. This can be useful if you want exact control of when keyframes should be created.
    120.     /// </summary>
    121.     public void RecordOneFrame ()
    122.     {
    123.         recorder.RecordOneFrame ();
    124.     }
    126.     /// <summary>
    127.     /// Inserts a recorded frame into the specified frame index. This can be useful if you want to add frames into the recording that shouldn't be placed last. Use FrameCount() to determine how many frames you currently have.
    128.     /// </summary>
    129.     /// <param name="frame">The index of where the frame should be inserted.</param>
    130.     /// <param name="frameType">The type of the inserted frame (by default FrameType.Middle).</param>
    131.     public void InsertOneFrame (int frame, FrameType frameType = FrameType.Middle)
    132.     {
    133.         recorder.InsertOneFrame (frame, frameType);
    134.     }
    136.     /// <summary>
    137.     /// Stops the ongoing recording.
    138.     /// </summary>
    139.     public void StopRecording ()
    140.     {
    141.         recorder.StopRecording ();
    142.     }
    144.     /// <summary>
    145.     /// Clears out the current recorded frames.
    146.     /// </summary>
    147.     public void ClearRecording ()
    148.     {
    149.         recorder.ClearRecording ();
    150.     }
    153.     /***********************************************************************************
    154.         Set live particle system as playback
    155.     ***********************************************************************************/
    157.     /// <summary>
    158.     /// Sets the particle system's live particles at the current position in playback (using the playhead) of this Playground Recorder. If multithreading is enabled this operation will run asynchronously.
    159.     /// </summary>
    160.     public void SetParticleSystemAsCurrentPlayback ()
    161.     {
    162.         recorder.SetParticleSystemAsCurrentPlayback ();
    163.     }
    165.     /// <summary>
    166.     /// Sets the particle system's live particles at normalized time of the recorded frames. If multithreading is enabled this operation will run asynchronously.
    167.     /// </summary>
    168.     public void SetParticleSystemAsRecording (float normalizedTime)
    169.     {
    170.         recorder.SetParticleSystemAsRecording (normalizedTime);
    171.     }
    174.     /***********************************************************************************
    175.         Saving/Loading
    176.     ***********************************************************************************/
    178.     /// <summary>
    179.     /// Stops the playback and recording of this Playground Recorder and serializes data into Recorder Data. If multithreading is enabled then the serialization will be asynchronous.
    180.     /// </summary>
    181.     public void StopAndSerialize ()
    182.     {
    183.         recorder.StopAndSerialize ();
    184.     }
    186.     /// <summary>
    187.     /// Serializes the current recorded frames into the Recorder Data. If multithreading is enabled then the serialization will be asynchronous.
    188.     /// </summary>
    189.     public void Serialize ()
    190.     {
    191.         recorder.Serialize ();
    192.     }
    194.     /// <summary>
    195.     /// Loads frames from the Recorder Data. This or LoadAsync happens automatically if recorderData is assigned.
    196.     /// </summary>
    197.     public void Load ()
    198.     {
    199.         recorder.Load ();
    200.     }
    202.     /// <summary>
    203.     /// Loads frames from the Recorder Data asynchronously. This or Load happens automatically if recorderData is assigned.
    204.     /// </summary>
    205.     public void LoadAsync ()
    206.     {
    207.         recorder.LoadAsync ();
    208.     }
    211.     /***********************************************************************************
    212.         Frame trimming
    213.     ***********************************************************************************/
    215.     /// <summary>
    216.     /// Trims (remove) the specified frames outside of normalized leftTime to rightTime. Returns true if trimming occurred.
    217.     /// </summary>
    218.     /// <param name="leftTime">The normalized left time (0 - 1).</param>
    219.     /// <param name="rightTime">The normalized right time (0 - 1).</param>
    220.     public bool Trim (float leftTime, float rightTime)
    221.     {
    222.         return recorder.Trim (leftTime, rightTime);
    223.     }
    225.     /// <summary>
    226.     /// Trims (removes) the specified frames inside of normalized leftTime to rightTime.
    227.     /// </summary>
    228.     /// <param name="leftTime">The normalized left time (0 - 1).</param>
    229.     /// <param name="rightTime">The normalized right time (0 - 1).</param>
    230.     public void TrimInner (float leftTime, float rightTime)
    231.     {
    232.         recorder.TrimInner (leftTime, rightTime);
    233.     }
    234. }
    More members can be found in the script reference.

    You can also have a look in the example scenes Recording One System and Recording Multiple Systems. The latter using the Playground Multi Recorder component which basically is a list of recorders controlled from single function calls.
    Last edited: Dec 25, 2015
  19. jashan


    Mar 9, 2007
    I believe I've just found a really nasty issue in Particle Playground (current version from the Asset Store, 3.02):

    For several weeks, I had sporadic hiccups in Unity when entering Play mode and also after compilation completed. What happened was that Unity simply stopped doing anything for about 100 seconds very much looking as if Unity crashed while it actually didn't crash. With some patience (waiting about 100 seconds), Unity would continue going into Play mode or return from the compilation hiccup.

    Joachim Ante from UT said the issue probably had to do Unity waiting for some Threads that domain reload has to wait for. So I tried figuring it out with the Visual Studio debugger (after going down a few long roads that didn't lead anywhere) ... and that finally revealed the (almost certain) cause of this issue:

    Code (csharp):
    1. stream = client.OpenRead(playgroundSettings.versionUrl);
    in PlaygroundParticleWindowC.CheckForInternetConnection().

    After replacing that method with return false; the issue did not occur for a few hours of developing / testing. After restoring the original implementation, it just took a few attempts to run into it again, and once again, the debugger showed one Thread getting stuck on that line, so I'm fairly certain that this is what's causing the issue.

    You might want to replace OpenRead with OpenReadAsync to prevent this from happening.
  20. manny003


    Mar 18, 2014
    I'm in somewhat of a pickle here. I just installed PP3 for the first time with the intention of using it in a project that's nearly complete -- and was written in Javascript (UnityScript).

    I'm having trouble getting references to PP3 objects at run time to perform simple things like enable/disable emitters, manipulators, change colors, etc. Nothing I've tried work.

    I've looked at Unity's guide for script compilation order at and even moved the entire ParticlePlayground folder into "Plugins".

    Nothing has worked.

    I cannot find any Simple Script Javascript starter as eluded in Version History. Nor does the Playground Wizard has any option to select coding language as mentioned in the Version History document for version 1.18.

    Can someone please provide step-by step instructions, examples, tutorials on how to leverage PP3 in a Javascript dominated project?

  21. save


    Nov 21, 2008
    Thank you that helps immensely! This will be fixed in the next update.
    jashan and hopeful like this.
  22. save


    Nov 21, 2008
    To make Particle Playground work with UnityScript:

    1) Create a folder called Plugins in the Project View then drag and drop Particle Playground into the Plugins folder using the Project View.

    2) Open the Playground Wizard (Window > Particle Playground) and press Find Playground Settings and the very top. This is needed in order for you to store your settings. The location is then stored in a file found in YourProject/PlaygroundCache/PlaygroundSettingsLocation so Playground won't have to search for its settings file again.

    In the Playground Wizard go to Settings > Paths and set the Playground Path to the Plugins folder. For example: Plugins/Particle Playground/. This is needed in order to load all Presets and other assets connected to Particle Playground.

    4) When referencing any Particle Playground components you will need to import ParticlePlayground into your UnityScript. For example:
    Code (JavaScript):
    1. #pragma strict
    2. import ParticlePlayground;
    4. var particles : PlaygroundParticlesC;
  23. jashan


    Mar 9, 2007
    You're welcome! Great to hear it will be fixed in the next update - so I can update / overwrite my changes without worries. Thank you! :)
  24. manny003


    Mar 18, 2014

    Just what I needed! Thanks.
  25. Obsurveyor


    Nov 22, 2012
    Is the Interactive/Manipulator Events scene script broken? It doesn't seem to do anything when you hit Play except some flashing in the Hierarchy about "Manipulator Events (not loaded)". I'm currently digging into it but any help would be appreciated.

    edit: Figured it out, it doesn't like the Playground Next Scene With Enter script. Disabling that script makes it work.
    Last edited: Jan 2, 2016
  26. save


    Nov 21, 2008
    Fixing this in the next update!
    Last edited: Jan 4, 2016
  27. save


    Nov 21, 2008
    Would love some feedback in this thread if you're still on Unity 4, I'm looking into streamlining the development and adding features for PP!
  28. Disastercake


    Apr 7, 2012
    Hey save, I picked up the FT particle package that uses Particle Playground, but I can no longer attach the particles to a prefabed game object (like a missile). Are there detailed instructions on how to get playground particles to work in prefabbed objects?

    Here is the error I get:
    Code (csharp):
    2. NullReferenceException: Object reference not set to an instance of an object
    3. FTME01_ParticleController.Update () (at Assets/_Assets/Particles/FT_MagicEffects_volume01/Script/FTME01_ParticleController.cs:124)
    Last edited: Jan 3, 2016
  29. save


    Nov 21, 2008
    The only thing I can think of is that a Particle Playground system need its dependency references inside the prefab or be hooked up at Awake/Start. For example your Source's or Manipulator Transform(s) needs to be parented to the prefab. Which object is not assigned on line 124?

    In general I can't give my best support on the plugins as they are third-party, in case you need a more detailed answer you could check with the publisher @frontakk.
  30. save


    Nov 21, 2008
    Update 3.0.3 is available, it's a smaller one taking care of the recent found bugs, adding Playground Trails shadow casting/receiving settings and Universal 10 build support (experimental/beta implementation).

    1. Playground Trails shadow casting & receiving
      Playground Trails can now be set to cast and receive shadows. Note that the shader for the trail material needs to support this to have any effect.
    2. Windows Universal 10 build support
      Particle Playground projects should now be able to build towards Universal 10 apps. The implementation is still experimental where additional updates to the multithreading architecture could be needed in further releases.
    1. Example scene issues
      Some example scenes got broken in the Unity 5.3 compatibility update due to a miss in PlaygroundNextScene.cs.
    2. Occasional Editor freezes when having the Playground Wizard open and hitting Play
      Due to the Playground Wizard checking the online version using a non-asynchronous method the Unity Editor could freeze before the returning timeout.
    3. Playground Trails having inconsistent length upon calculation cycle frame skips
      The Playground Trails was relying on a global delta time to update all trail points. This made each trail point inconsistent in their length as time would be updated slower when skipping calculation cycles. This was mostly noticeable on particle systems generating a higher amount of trails (~200+). Each trail point is now relying on their own delta time which results in a consistent behavior no matter the time between calculation cycles.
    Last edited: Jan 5, 2016
    ian_facepunch, hopeful and DMeville like this.
  31. s_guy


    Feb 27, 2013
    Hi @save ,

    In updating from v2 to v3.0.3, we're encountering a Unity hard crash "Fatal error in gc; too many threads" when a scene with various Particle Playground emitters is loaded. Sometimes it happens from simply loading it in the editor, but it occurs more reliably upon scene load during play. Saving the problem scene with all "t: PlaygroundParticlesC" objects disabled reliably avoids the crash (reverting the project to v2 of particle playground also removes this issue).

    I probably can't share the project, but I can try to get a reduced case. I just wondered if there was any known issue or solution to this before starting the hunt for specific problem assets.

    Also, could you please confirm (or advise) that the following are reasonable and appropriate steps for updating a project from v2 to v3:
    1. Delete v2 install
    2. Import v3 with Unity's download manager
    3. Update custom path in the Particle Playground settings (we put 3rd party stuff under a tools folder)
    Is a step 4 expected, where pre-existing particle emitters need to be rebuilt under v3? We haven't taken this step.


    EDIT: Some additional info.
    • This occurs on both an i5 with 8GB and i7 with 32GB.
    • The thread settings for Particle Playground are the default (auto, 128).
    • The crasher does not seem to be related to any single emitter, but having too many emitters enabled in the scene. There are about 50 total in the scene; about half of them are on characters and don't emit anything until a script calls it.
    Last edited: Jan 6, 2016
    xDavidLeon likes this.
  32. save


    Nov 21, 2008
    This was not a known issue, but let's see if we can track it down.
    - Which version of Unity are you using?
    - How is the Playground Manager > Advanced > Multithreading settings setup (default or custom)?
    - How many particle systems are you trying to load at scene start?

    I'm trying to reproduce this with jumping between scenes having 10, 100 and 1000 particle systems loading at the same time but I can't seem to replicate it using multithreaded startup for the particle systems and then having all calculations running inside the Thread Pool Method: Playground Pool.

    What you could try is disable Advanced > Misc > Multithreaded Startup on your particle systems. I suspect there could be an issue with having a lot of particle systems loading at the same time on certain hardware. Another approach you could try is to batch instantiate particle systems in a sequence after the scene was loaded.

    When updating you should not need to delete the previous version as PP3 is backwards compatible (your old particle systems will still work).
    When putting the Particle Playground folder into another location you should be presented with a dialogue which enables you to automatically find the Playground Settings at the very top in the Playground Wizard (at least after the next Unity start). Then in the Playground Wizard go to Settings > Paths and set the Playground Path to the new location.
  33. save


    Nov 21, 2008
    Thanks for additional info!
    Ok, 50 systems should not be the issue.
    When using Thread Pool Methoid: Playground Pool you should try to keep Max Threads as low as possible (default 8), this has an affect on how many threads will be generated to reuse. From the Playground Performance page:
    Try use Thread Pool Method: Playground Pool and lower Max Threads to 8 to see if it helps.

    I'm trying to reproduce this using 128 threads for the pool but still no issues (Unity 4.3.4 / 5.0 / 5.3 on an i7). Looking at the CPU resources Unity is overall using around 180 threads when doing this (apart from around 60 threads when Max Threads is set to 8).

    In case you keep having issues it would be great if you could send a stripped down project scenario for debugging to
    Last edited: Jan 6, 2016
  34. s_guy


    Feb 27, 2013
    Thanks a lot for the super fast reply!

    I'm on Unity 5.3.0f4.
    The Playground Manager > Advanced > Multithreading settings are all default. ("Playground Pool", "Automatic", "Inside Particle Calculation", "One per System", 128)
    Currently, all Particle Playground systems at scene start are on pre-placed scene objects. Some are instantiated on actor spawn / re-spawn, but I'm fairly certain that doesn't occur at scene start. I'll confirm this asap.

    Sorry, I can't seem to find the Multithreaded Startup option. I don't see a "Misc" section under "Playground Manager > Advanced". I'll give the script suggestion a try after I can find this option.

    I'll try this now and report my results. I'm not sure how the default threads are decided, but that setting was at 128 to start with. How are you seeing the count of threads in use?

    EDIT: Setting Max Threads to 8 seems to resolve the issue! I'll need to profile this but I'm guessing that I'm just providing a hint to the Playground Manager about limitations it already has to deal with. Is that correct? Should I expect a performance hit from this constraint? With a quick check, things seem to be performant still. Max Threads seems to be a setting that is saved per scene, when perhaps it is a project-wide concern?

    Thanks again for the great support. It makes use of this fun package all the more enjoyable.
    Last edited: Jan 6, 2016
  35. DMeville


    May 5, 2013
    Hey @save

    Playground trails are quickly becoming my favorite thing ever.
    Just wondering if there would be any plans to have a "smooth trails" version? Using some sort of catmul-rom spline interpolation or something to smooth out jagged edges on fast moving particles.

    Keep up the awesome work!

    Attached Files:

  36. save


    Nov 21, 2008
    The Multithreaded Startup option is done per particle system and can be set through their Inspector. It is although preferred whenever possible to do this operation asynchronously as you'll have faster loading times (especially on scenes with a higher amount of particle systems).

    When a new Playground Manager instantiates it will default to 8 (the recommended value in most hardware setups). If you install over a previous version the previous value will be serialized within the scene, this is why you had the old value of 128.

    Max Threads is clamping the generated threads before calculations start to bundle into the same thread calls, if you have less CPUs than Max Threads the processor count will be used instead. The Playground Pool will although generate the specified Max Threads within the pool and iterate through them, which is why you encountered problems as you had too many threads generated from Unity (what that exact number is I'm not sure yet and is not consistent due to Unity versions, projects and hardware).

    You can do this with the built in Resource Monitor on Windows or Activity Monitor on Mac OS.

    You will need to set the Max Threads for each scene as this is a public serialized member on the Playground Manager. This can also be done from script by calling:
    Code (CSharp):
    1. PlaygroundC.SetMaxThreads(int);
    You can use this to have an overall control over how particle calculations bundle at runtime, perhaps most interesting when working with limited hardware where you want to distribute calculation differently depending on how the scene works and how heavy particle systems you have in it. This can also be controlled by an override on a per particle system basis if you want to bundle certain particle systems together or have a separate thread for a particular one (page 63 in the manual).

    The lower the Max Threads value the better, you will have less threads to iterate through in the Playground Pool and should see a noticeable CPU time difference in the profiler for the PlaygroundC component.

    Awesome to hear, thank you! :)
  37. save


    Nov 21, 2008
    Great to hear! :)
    Oh yes, this is on the roadmap for version 3.1.
    DMeville likes this.
  38. 8r3nd4n


    Sep 10, 2011
    Hi @save

    I have been using script to change the texture state of particles with success using the following:

    Code (CSharp):
    1. public void StartNewParticles(string s, Texture2D t)
    2.     {
    3.         particles.lifetimeColor = CM.StringToGradient(s);
    4.         particles.states[0].stateTexture = t;
    5.         particles.states[0].Initialize();
    6.         particles.emit = true;
    7.     }
    The issue that I am having is that each time the texture gets swapped, it is of different sizes and the particle count does not change according to the new texture. Well, it does in the particle state but not in the particle count section under particle settings. What I am trying to do is set the particle count to be double what the texture sets it at but cant find how to access the particle states particle count variable. If I have this, I would use:

    Code (CSharp):
    1. particles.particleCount = particles.states[0].particleCount * 2; // does not find the particle states count
    How can I set the particle setting count to that of the states?

  39. hierro__


    Sep 22, 2014
    Hi all, im trying to generate kind of fire from a skinned mesh renderer, is there any hint about this kind of effect ? Thank you very much in advance
  40. Pyroka


    Oct 22, 2012

    We recently updated from PP 2 to PP 3 and it seems some behaviour has changed regarding rotation (and in particular, rotation of child VFX).

    We have a few VFX prefabs that represent a muzzle-flash, something like this (simplified):
    + Flash
    +---- Fire

    Where Flash is a GameObject with one particle system, and Fire is a child game-object with another one.

    When the player fires a gun we spawn one of these at the end of the barrel and rotate the top-level GameObject so that it points in the correct direction. In PP 2 this worked fine, but in PP 3 the 'Fire' vfx is not being rotated when the parent is. This seems to be tied up to the Rotation part of the Particle Settings, in that if Rotation is 'Off' then the sprite always has no rotation regardless of the parent rotation and if it's on it will use that rotation instead of any rotation on the transforms.

    Is there any-way to re-enable the old behaviour?
  41. topsekret


    Apr 18, 2013

    We are currently using Particle Playground 2 (we are hesitant to risk upgrading to 3 since we are within weeks of shipping our game) and we seem to have found an issue with the snapshot feature.

    We have a particle system that has two snapshots that we blend between at runtime. Each snapshot has a world object as its source.

    Originally, we only needed one instance of this particle system. But now we need to have multiple instances, with the only difference between instances being the world object used as the source and the particle count.

    To achieve this, I tried to make the original particle system a prefab. Obviously, the prefab itself lost the references to the game objects in the scene used as sources in the snapshot, but that is fine since it maintained all the other settings. After dragging an instance of the prefab into the scene, I tried setting a new game object as the the source in the two snapshots.

    Everything looked fine until I tried blending between the snapshots (using the "Load" button with a transition time of 2 and "Ease In"). For snapshot 1, I could see particles coming from the new mesh. For snapshot 2 I could see particles from for the new mesh. But as I blended between them , the particles transitioned from the new mesh to the old mesh, then warped to the new mesh again at the end of the transition.

    This same behavior happened even if I just duplicated the particle system in the scene instead of making a prefab first.

    It seems that the particle system is serializing a reference to the old mesh somewhere for the snapshot transition feature and is not correctly reassigning this when I reassign the source world object.

    Any idea on how to fix this? Am I using the tool wrong, or is this a bug?
  42. save


    Nov 21, 2008
    Sorry about the late reply. A state has a variable called positionLength which is the amount of positions generated by the texture or mesh. Here's an example:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using ParticlePlayground;
    5. public class SetParticleCountToState : MonoBehaviour {
    7.     public PlaygroundParticlesC particles;
    9.     void Update () {
    10.         if (particles.particleCount != particles.states[particles.activeState].positionLength * 2)
    11.             particles.particleCount = particles.states[particles.activeState].positionLength * 2;
    12.     }
    13. }
    Last edited: Jan 18, 2016
  43. save


    Nov 21, 2008
    You can try the Fire - Burning Robot example found in Window > Particle Playground > Presets > Fire. (example)
  44. save


    Nov 21, 2008
    Hi! There is no specific changes regarding rotations in version 3 opposed to version 2. I believe that this is based on how Shuriken is functioning since Unity 5.3. What you could do though is set the initialRotationMin and initialRotationMax to the angle you'd prefer (for example based on the z-axis of the parent). Would that work? Otherwise I could have a deeper look into making something flexible for the next update, which will have more options regarding rotations.
  45. save


    Nov 21, 2008

    If I understand correctly you would need to create a new Snapshot from the duplicated particle system as you have changed the information of where the Source positions are located due to the new World Object.

    If this becomes a world space issue you can then use the script SnapshotToLocalPosition found in the Simple Scripts folder to be able to reposition your snapshots within a local space.

    If you're looking for more flexibility when transitioning between particle systems you could use a (Skinned / Mesh) Target Manipulator and enable whenever transitions should occur. This requires more fine-tuning work though, but will give good control in how particles behave. You can top that with any other Manipulators, such as size and color.

    I am looking into more flexibility for Snapshots in future updates, if you have any suggestions in what's missing feel free to shoot them at me! I can recommend to upgrade to PP3 at a good point in your development cycle to gain performance (CPU time, stack- and heap memory). PP3 is backwards compatible with your PP2 systems.
  46. Hilbert


    Dec 3, 2014
    Is it possible to get the trails working in local space?
    I want my particles to move in a circle around an object which itself moves, and I would like to have trails that only follow this local circular motion, and not the global motion which also depends on the movement of the object that is being circled.

    [And while I'm talking about circles: what is the recommended way to get particles moving in a circle? I'm currently "faking" a circle with a spline. It works, but I'm not entirely happy with it because the "seam" where the beginning and end of the spline meet is somewhat visible.]
  47. save


    Nov 21, 2008
    Trails are calculated in local space (using a TRS matrix set by the particle system's Transform) when the particle system is set to Advanced > Simulation Space > Local. So by moving the particle system your entire trails should follow accordingly.

    There are some different ways to get particles to move in a circle:
    • Use Force > Force Annihilation > Only Source Positions and rotate the source by its Transform.

    • Force > Force Annihilation > Lifetime Positioning (examples of particle system setups in Example Scenes/Interactive/Lifetime Positioning and Example Scenes/Lifetime Positioning - Manipulators).

    • Use Spline Target Property Manipulator (handmade circle) with Target Method: Particle Time, Transition: Linear, Shape: Infinite and Distance Effect: 0.

    • Use Combined Manipulator, two Math Manipulators setting either Particle Property: Position or Velocity:
      • Type: Sin
      • Type: Cos

    What method to choose is up to what you're looking to do in the end, for example using a Force Annihilation method means that you can't combine the effect with any type of forces. Using any Manipulator Targets you can combine with forces to some extent. Based on your description I would try either Only Source Positions and rotating the Transform or Lifetime Positioning using the Vector3 Animation Curves.
  48. Hilbert


    Dec 3, 2014
    Indeed they do. I was accidentally moving the spline manipulator instead of the particle system, now everything is fine. :)

    (A note for anyone else who might try these: When using the spline manipulator method, it appears that Smoothing should also be set to 0.)

    Thanks a lot. I almost feel guilty for having bought PP during a sale and thus having paid so little for such a great asset.

    EDIT: Now I'm confused again. I played around with the math manipulators, but I haven't managed to understand what it really is that they are supposed to do. I looked at the source code and apparently the Math/Position Sin/Cos manipulators add the value of a (possibly scaled) sin/cos evaluated at the current time onto the current value... this puzzles me, because in essence this leads to the resulting position behaving roughly like an integral of sin/cos, but how close they are the actual integral depends on how evenly spaced the evaluated time indices were. And even worse: while this can be used to approximate some circle, it makes it pretty much impossible to center that circle properly, because we are looking at approximated integrals of the form Int(sin(x), t0, t) that only equal the desired function cos(t) up to an additive constant that depends on the initial time t0 when the particle spawned.
    TL;DR: Sin/Cos math manipulators provide me with something roughly circle-shaped, but as far as I can see they cannot be reliably used to make particles orbit a specific center point.
    Last edited: Jan 24, 2016
  49. mcmorry


    Dec 2, 2012
    @save I have an issue with the Trails. I can't set the layer where they should be created. I could tweak the code for but would be nice to have a better solution. Please let me know if you have any suggestion.
  50. save


    Nov 21, 2008
    Ah that makes sense. :)

    Regarding the Math Manipulator and the Particle Property: Position; the structure is because of its necessity of remaining additive and foremost compatible with the other translation and velocity features. If particles were to be set only to the returned sin/cos value then it would have been a really specific scenario removing or interfering any other position and velocity settings, but perhaps I'm looking at it from the wrong angle in this answer - feel free to suggest improvements of course if I'm missing something! Math Manipulator is not a good way of making 'perfect' circles, but rather moving particles in circular motion through translation or velocity.

    The most effective way would be to use local simulation space, emit particles in a circle through script and then rotate the particle system transform, example:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using ParticlePlayground;
    5. public class MoveParticlesInCircle : MonoBehaviour {
    7.     public float rotationSpeed = 10f;
    8.     public float radius = 1f;
    9.     public Color32 color;
    10.     public PlaygroundParticlesC particles;
    12.     IEnumerator Start ()
    13.     {
    14.         while (!particles.IsReady())
    15.             yield return null;
    17.         particles.shurikenParticleSystem.simulationSpace = ParticleSystemSimulationSpace.Local;
    19.         for (int i = 0; i<particles.particleCount; i++)
    20.         {
    21.             float angle = ((i*1f) / particles.particleCount) * Mathf.PI * 2;
    22.             particles.Emit(
    23.                 new Vector3(Mathf.Sin(angle) * radius, Mathf.Cos(angle) * radius),
    24.       ,
    25.                 color
    26.             );
    28.         }
    29.     }
    31.     void Update ()
    32.     {
    33.         // Rotate the particle system transform
    34.         particles.particleSystemTransform.Rotate(Vector3.forward * Time.deltaTime * rotationSpeed);
    35.     }
    36. }
    Another way is using the Sticky feature (which will make particles stick onto a transform just as if they were parented to it, similar to how local space would behave but in global space and actively responding to scaling). Here's a Sticky example:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using ParticlePlayground;
    5. public class MoveParticlesInCircle : MonoBehaviour {
    7.     public Transform centreTransform;
    8.     public float rotationSpeed = 10f;
    9.     public float radius = 1f;
    10.     public Color32 color;
    11.     public PlaygroundParticlesC particles;
    13.     IEnumerator Start ()
    14.     {
    15.         while (!particles.IsReady())
    16.             yield return null;
    18.         particles.stickyCollisions = true;
    20.         Vector3 centrePos = centreTransform.position;
    22.         for (int i = 0; i<particles.particleCount; i++)
    23.         {
    24.             float angle = ((i*1f) / particles.particleCount) * Mathf.PI * 2;
    25.             Vector3 pos = centrePos + new Vector3(Mathf.Sin(angle) * radius, Mathf.Cos(angle) * radius);
    26.             particles.Emit(
    27.                 pos,
    28.       ,
    29.                 color
    30.             );
    32.             particles.SetSticky (i, pos, Vector3.forward, 0, centreTransform);
    33.         }
    34.     }
    36.     void Update ()
    37.     {
    38.         // Update the sticky positions
    39.         for (int i = 0; i<particles.particleCount; i++)
    40.             particles.UpdateSticky(i);
    42.         // Rotate the transform
    43.         centreTransform.Rotate(Vector3.forward * Time.deltaTime * rotationSpeed);
    44.     }
    45. }
    Last edited: Jan 25, 2016