Unity Particle System - starting velocity?

Helloooo

So while making Orbits for the past LD, I came across this problem that I've had for a long, long time but hadn't been able to figure out and had done tons of googling for.

I want to make a gameobject with a particle system, and I want that particle system to inherit velocity from the body from which it was made.

So, like a thing flies along a path, hits something. I want the resultant explosion/debris to go along with the same initial movement vector as the object was moving at.

So for example, these explosions don't have debris flying in the direction the object exploded from. I want to change these:
image

Now I hear you "yes there's a inherit velocity module on the particle system". Well yes, I looked into that, and I hadn't been able to get it to work. Instantiating a gameobject.

I could manually make gameobjects and hurl them in the vector, but that's more overhead. I want PARTICLES! How do I control particle emitters??

Comments

  • Tuism said:
    Now I hear you "yes there's a inherit velocity module on the particle system". Well yes, I looked into that, and I hadn't been able to get it to work. Instantiating a gameobject.
    Unity docs, in case this is the issue:
    This module only has an effect on the particles when Simulation Space is set to World in the Main module.
    For what you're doing here, in case you can't get that to work, you might look at using a cone for spawning instead, and rotating the particle system that's spawned to be in the direction to point in the direction that the spheres were moving.
    Thanked by 1Tuism
  • Tuism said:
    Now I hear you "yes there's a inherit velocity module on the particle system". Well yes, I looked into that, and I hadn't been able to get it to work. Instantiating a gameobject.
    Unity docs, in case this is the issue:
    This module only has an effect on the particles when Simulation Space is set to World in the Main module.
    For what you're doing here, in case you can't get that to work, you might look at using a cone for spawning instead, and rotating the particle system that's spawned to be in the direction to point in the direction that the spheres were moving.
    Yeah I've tried the world simulation space thing. Don't know. Okay so I know if I had the particle system attached to the gameobject from the start and it being on constant emission, inherit velocity works. But if I want to instantiate particles at a particular time, it doesn't, which I understand works as intended. But how do I dive into the particlesystem's code and tell it to go with a given velocity vector?

    As for spawning with a cone, yeah I thought about that, but that means if the velocity is not the same every time, the particles will go at the same speed. IE a slow projectile will explode with the vigour of a bullet train crash :/
  • When you say instantiate, are you creating the gameobject/particle system at that point? Because then it doesn't have any data from the previous frame, so it doesn't know what velocity something is moving at.

    You'd then want to leave the particle system on the gameobject, but turn the emission module off, and when you want it to emit, you turn it on instead of spawning one in.
    https://docs.unity3d.com/ScriptReference/ParticleSystem-emission.html
  • Yeah I get that, I think we're saying the same thing - That's what I tried to say just now, but of course I'm not saying it quite right :P

    I understand that approach and it feels cumbersome, and also I have to attach a variety of particle emitters to the object, instead of pulling what I need at will.

    So what I'm trying to find out is - could I access the velocity at start or velocity over time module of a particle system, so I can instantiate or activate (if pooling), and then pass the velocity data into it? Or is that too damn hard? :/
  • Hey @Tuism, maybe try making the particle system in a cone shape or something that faces a direction. Then when you spawn a new hit effect let it face the direction of the hit and just adjust the "start speed" with the velocity magnitude. Let me know if that works or not a viable option
  • edited
    Tuism said:
    So what I'm trying to find out is - could I access the velocity at start or velocity over time module of a particle system, so I can instantiate or activate (if pooling), and then pass the velocity data into it? Or is that too damn hard? :/
    You can access the velocity per point using GetParticles(), which gives you an array of the particles in the system. You can change those values, and apply them to the particle system using SetParticles().

    If you're trying to access the velocity over time module, you can via this: https://docs.unity3d.com/ScriptReference/ParticleSystem-velocityOverLifetime.html

    Doing either of those seems just as much work (if not more) than just enabling the emission module though.

    The Unity particle editor's pretty rudimentary, and they just expose lots of it in the scripting to try make up for it.
  • Zaphire said:
    Hey @Tuism, maybe try making the particle system in a cone shape or something that faces a direction. Then when you spawn a new hit effect let it face the direction of the hit and just adjust the "start speed" with the velocity magnitude. Let me know if that works or not a viable option
    How do you access the start speed of a particle system, can you give me an example?
  • Tuism said:
    So what I'm trying to find out is - could I access the velocity at start or velocity over time module of a particle system, so I can instantiate or activate (if pooling), and then pass the velocity data into it? Or is that too damn hard? :/
    You can access the velocity per point using GetParticles(), which gives you an array of the particles in the system. You can change those values, and apply them to the particle system using SetParticles().

    If you're trying to access the velocity over time module, you can via this: https://docs.unity3d.com/ScriptReference/ParticleSystem-velocityOverLifetime.html

    Doing either of those seems just as much work (if not more) than just enabling the emission module though.

    The Unity particle editor's pretty rudimentary, and they just expose lots of it in the scripting to try make up for it.
    Omg, per particle??! Okay I'll give the enabling emissions thing a go, so the particle system & its game object must be active, just not emitting, then enable emissions via play it something, yeah?
  • That sounds right, yeah.

    Just make sure you're following the examples in the docs. "Particle system modules do not need to be reassigned back to the system; they are interfaces and not independent objects" -- which is different to pretty much everything else in Unity... <_<

  • edited
    Something like this
    ParticleSystem _particleSystem;
    	
    void Awake () {
            _particleSystem = GetComponent<ParticleSystem>();
            var mainModule = _particleSystem.main;
            mainModule.startSpeed = 10f;       
    }


    Edit. Maybe this is a bit more detailed of how I would do it (untested as I am at work atm)
    public class ParticleTest : MonoBehaviour {
    
        ParticleSystem _particleSystem;
    
    	void Awake () {
            _particleSystem = GetComponent<ParticleSystem>();
                
    	}
    
        public void StartParticles(float startingSpeed)
        {
            var mainModule = _particleSystem.main;
            mainModule.startSpeed = startingSpeed;
            var emission = _particleSystem.emission;
            emission.enabled = true;
        }
    
    }
    
    public class Test: MonoBehaviour
    {
        [SerializeField]
        GameObject _explosionPrefab;
    
        void OnCollisionEnter(Collision collision)
        {
            ContactPoint contact = collision.contacts[0];
            Quaternion rot = Quaternion.FromToRotation(Vector3.up, contact.normal);
            Vector3 pos = contact.point;
            var explosion = Instantiate(_explosionPrefab, pos, rot);
            explosion.GetComponent<ParticleTest>().StartParticles(10f);        
            Destroy(gameObject);
        }
    }
  • @elyaradine so I dug into my particles and realised I had been trying to do it that way, or at least I think I have been - this is my particle system setup:

    image

    And what I've been doing is simply to tell the particlesystem to play() when it hits. Does the particlesystem not know its velocity before it's playing? I tried changing the emission to be play on awake and added a constant looping particle, and those behave correctly (ie followed the velocity of the body) but if I turn play off and on when it needs to activate it doesn't work.

    I tried following your emissions on/off method and unity tells me "UnityEngine.ParticleSystemEmissionType' is obsolete:"
    `UnityEngine.ParticleSystem.EmissionModule.type' is obsolete: `ParticleSystemEmissionType no longer does anything. Time and Distance based emission are now both always active.'


    I thought it might still work and tried it but it seems that the emissions module example in the documentation (https://docs.unity3d.com/ScriptReference/ParticleSystem-emission.html) is inserting bursts at runtime, I tried to insert a burst at 0f seconds but it didn't do anything.............

    I can't believe how hard this is -_____-
    Screen Shot 2017-12-05 at 11.41.28.png
    332 x 627 - 46K
  • edited
    Hey @Tuism,

    I tested this and it worked.

    This part spawns the particle system and sets the startingSpeed variable before its spawned
    public class CollisionTest : MonoBehaviour {
    
        [SerializeField]
        GameObject _explosionPrefab;
    
        void OnCollisionEnter(Collision collision)
        {
            ContactPoint contact = collision.contacts[0];        
            Quaternion rot = Quaternion.FromToRotation(Vector3.forward, contact.normal);
            Vector3 pos = contact.point;
            _explosionPrefab.GetComponent<ParticleHit>().startSpeed = collision.relativeVelocity.magnitude;
            var explosion = Instantiate(_explosionPrefab, pos, rot);
            Destroy(gameObject);
        }
    }


    This part sets the starting speed of the system in the starting method.
    public class ParticleHit : MonoBehaviour {
    
        ParticleSystem _particleSystem;
        public float startSpeed = 5f;
    
    
        private void Start()
        {
            _particleSystem = GetComponent<ParticleSystem>();
            var mainModule = _particleSystem.main;
            mainModule.startSpeed = startSpeed;// new ParticleSystem.MinMaxCurve(startSpeed);
        }
    
    }
Sign In or Register to comment.