Search Unity

Parameters for particle projectiles

Discussion in '2017.1 Beta' started by iivo_k, Apr 16, 2017.

  1. iivo_k

    iivo_k

    Joined:
    Jan 28, 2013
    Posts:
    312
    First of all, sorry for reposting this here, as this is not beta related per se, but it seems just impossible to get Unity dev attention on the general scripting forum.

    ---

    Particles with collision work nicely as weapon projectiles, however the OnParticleCollision method only identifies the GameObject that the collision happened with and there's no possibility for additional parameters that I can see.

    Imagine you have a powerup that's active for a limited time and should be applied to each projectile when they're fired. The powerup runs out before the particle collides, so it's no longer active on the weapon, but should still be active for the projectile. In this case it's not enough to identify the weapon that fired it via the GameObject upon collision, you'd need some way to attach data to the particle or at least identify it. Getting a particle ID on emit and the same one on collision would be enough, you could then map data to the particle ID yourself.

    Of course you could just update particles manually or use some other method, but I feel this would be a pretty simple and useful way to do it. Are there ways to accomplish this currenly, or would it be possible go get something like this added?
     
  2. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    4,474
    Particle collisions seem to be designed to miss collisions in favor to performance when required, which makes me believe they should not be used to drive (important) game-logic.

    Quality settings also use different amounts of Particle Raycast Budgets. Which could mean that Low Quality has a much higher chance to drop particle collisions, resulting in different game-logic behavior depending in the quality setting.

    See World Collision Quality.

    I guess I would implement a "Projectile" MonoBehaviour that checks for collisions, but represents the projectile logic only, not the visual appearance. Checking for collisions could be done by doing a Raycast from the current to the new position for example. The weapon could pass additional data to the projectile when it is fired. Particles would be a visual goody only and could be completely removed or replaced while game-logic would still stay intact.
     
  3. iivo_k

    iivo_k

    Joined:
    Jan 28, 2013
    Posts:
    312
    With high quality particle collisions all of them are checked with PhysX and the budgets are ignored (AFAIK).

    Just to clarify, I do have a system using raycasts and GL draw commands that I can also use, I just think that using particle systems for bullets is delightfully simple and would be even better if there was a way to get particle IDs, which could then be used to fetch additional data.
     
  4. superpig

    superpig

    Quis aedificabit ipsos aedificatores? Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,250
    From the docs page on OnParticleCollision:

     
  5. iivo_k

    iivo_k

    Joined:
    Jan 28, 2013
    Posts:
    312
    I'm not sure how that helps? I did look at the docs, but as far as I know ParticleCollisionEvent doesn't allow me to add custom parameters or identify a specific particle ( https://docs.unity3d.com/2017.1/Documentation/ScriptReference/ParticleCollisionEvent.html ).

    I mean a case like this:

    - Fire a weapon, using ParticleSystem.Emit. A powerup is temporarily active, increasing damage for the bullet. If I'm given an ID for the particle, I can store a struct containing the current bullet parameters at that specific time

    - The particle collides with an enemy, OnParticleCollision is called on the weapon and the enemy and the particle ID is supplied as a parameter. The powerup on the weapon has already ended but we need to know the damage at the time when the bullet was fired. The particle ID could be used to fetch the bullet params struct.

    I'm just wondering if there's already a way to identify a specific manually emitted particle when it collides and if something like this would make sense to be added, if it's not yet possible.
     
  6. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    1,318
    iivo_k likes this.
  7. iivo_k

    iivo_k

    Joined:
    Jan 28, 2013
    Posts:
    312
    That's very understandable, the signal to noise ratio is much more manageable at the beta forums.

    Right, so that way I can assign IDs inside vertices to the ParticleSystem's custom data stream. I'm still not quite sure how to connect that data to a specific particle that caused an OnParticleCollision call. If it means having to loop the particles through and comparing positions or something like that, then I may as well do the whole thing manually some other way.
     
  8. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    1,318
    Ah, you're right. I'd not thought about this.. i don't think you can get the appropriate custom data from inside OnParticleCollision :(
     
  9. iivo_k

    iivo_k

    Joined:
    Jan 28, 2013
    Posts:
    312
    Well, something to think about. Could be useful. :)
     
    richardkettlewell likes this.
  10. iivo_k

    iivo_k

    Joined:
    Jan 28, 2013
    Posts:
    312
    Turns out I'd really like this! Using GL.QUADS seems to be much slower than particles and using ParticleSystem.GetParticles -> update -> ParticleSystem.SetParticles is also much slower.

    So just ParticleSystem.Emit returning an ID and being able to get that same ID in OnParticleCollision would be very helpful. Or is there some other way to draw a lot of quads really fast from a script?

    Edit:
    I think I'll need benchmark Graphics.DrawMeshInstanced(Indirect) with quad meshes too. And I guess in the end I won't need tens of thousands of projectiles at once, like in the tests, but I just really hate to waste CPU time if I know there's some more efficient method attainable.
     
    Last edited: Apr 28, 2017
  11. mh114

    mh114

    Joined:
    Nov 17, 2013
    Posts:
    291
    I'm all for the particle ID mapping, would be an useful thing to have! But in the meantime, have you tried a constant size dynamic mesh where you populate the quad verts and indices yourself? Reusing the same buffers (+ Mesh.MarkDynamic()), I think there is even List-overloads these days. Zero out the unneeded triangles and/or make them degenerate with indices.

    (Disclaimer: I haven't tried this in Unity and the cost of going from C# to native land might make it too slow but perhaps something to try. Unless you already have. :))

    EDIT: Another idea, have a few of meshes that have allocated buffers for, say, 128 quads, 256, 512 quads and so on. Switch to the approriate mesh depending on needed quad amount, populate and fill the unused with zeroes. I think you can have prepopulated indices across the whole buffer, and just zero the positions for unused stuff, making them degenerate.
     
    Last edited: Apr 28, 2017
    iivo_k likes this.
  12. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    26,211
    The fastest possible way is to prepare a single mesh of a lot of quads and update each quad within a shader. It doesn't get quicker than this if you're able to code shaders, that is.

    A vertex stream can control all the positions or better just calculate them within the shader itself, but I suspect you will want script control.

    Also set particles isn't that slow. Get particles really is, so if you just keep your own array handy you can avoid get particle if using it as a dumb renderer. In cases like this you should stop the particle system from simulating or otherwise doing anything.
     
    iivo_k likes this.
  13. iivo_k

    iivo_k

    Joined:
    Jan 28, 2013
    Posts:
    312
    Thanks for the ideas! Didn't think of updating a single mesh, I'll have to give that a try. Updating in a shader probably won't do though.

    In the end though I'm pretty sure whatever I try on the C# side it won't come close to the performance of a ParticleSystem, it seems to be quite efficient with the collision checks too and I haven't even tested the hit I'm gonna take from raycasts yet. So it would be great to have the particle IDs and use ParticleSystems whenever possible and whatever is the second most efficient method when something else is needed (like projectiles going through things but registering hits, which I don't think is possible with ParticleSystem collisions).
     
  14. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    1,318
    The Trigger Module can do this :)

    Regarding the original problem, I'll add something to our roadmap to add access to the custom data in the colllision (and trigger) callbacks. It's an oversight that it's not already possible.
     
    mh114 and iivo_k like this.
unityunity