Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved Particle system adjust speed by script

Discussion in 'Scripting' started by Lifee00, Apr 12, 2024.

  1. Lifee00

    Lifee00

    Joined:
    Apr 13, 2021
    Posts:
    88
    Hello, my particle sys only emits 1 particle at a time. What I'm trying to do is: After it collides with my hero, I will turn collision off, then I want the particle to continue its path. The script indeed turns off collision and adjusts velocity of the particle, however after the particle collides with the hero, no option I've tried will ever make it resume back its speed, script or non-script even. Any help? Thanks.

    Here is also my simple code.
    Code (CSharp):
    1. public class PArticles : MonoBehaviour
    2. {
    3.     public float particleSpeed = 5f; // Adjust as needed
    4.  
    5.     private ParticleSystem particleSystem;
    6.  
    7.     void Start()
    8.     {
    9.         particleSystem = GetComponent<ParticleSystem>();
    10.        
    11.     }
    12.  
    13.     void OnParticleCollision(GameObject other)
    14.     {
    15.  
    16.         //Turn off collision
    17.         ChangeCol();
    18.         //Velocity Restore
    19.         ParticleSystem.Particle[] particles = new ParticleSystem.Particle[particleSystem.particleCount];
    20.         int numParticlesAlive = particleSystem.GetParticles(particles);
    21.  
    22.         for (int i = 0; i < numParticlesAlive; i++)
    23.         {
    24.             // Example: Make particles continue their path by adjusting velocity
    25.             particles[i].velocity = particles[i].velocity.normalized * particleSpeed;
    26.         }
    27.  
    28.         //Update propeties of the particles
    29.         particleSystem.SetParticles(particles, numParticlesAlive);
    30.         Debug.Log(other.name);
    31.     }
    32.  
    33.     void ChangeCol()
    34.     {
    35.         var collisionModule = particleSystem.collision;
    36.         collisionModule.enabled = false;
    37.        
    38.     }
    39. }
     
  2. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,936
    It seems the particle already reacts to collision before OnParticleCollision is called.
    What you could do is keep track of the particles velocity in update, then when the collision occurs, just assign the last velocity to the particle.

    Code (csharp):
    1.  
    2. public Vector3[] lastVel;
    3.  
    4. void Update()
    5.     {
    6.         ParticleSystem.Particle[] particles = new ParticleSystem.Particle[particleSystem.particleCount];
    7.         int numParticlesAlive = particleSystem.GetParticles (particles);
    8.  
    9.         for (int i = 0; i < numParticlesAlive; i++) {
    10.             lastVel [i] = particles [i].velocity;
    11.         }
    12.     }
    13.  
    14. void OnParticleCollision (GameObject other)
    15.     {
    16.      
    17.         //Turn off collision
    18.         ChangeCol ();
    19.         //Velocity Restore
    20.         ParticleSystem.Particle[] particles = new ParticleSystem.Particle[particleSystem.particleCount];
    21.         int numParticlesAlive = particleSystem.GetParticles (particles);
    22.      
    23.         for (int i = 0; i < numParticlesAlive; i++) {        
    24.                 particles [i].velocity = lastVel [i];  
    25.         }
    26.      
    27.         //Update propeties of the particles
    28.         particleSystem.SetParticles (particles, numParticlesAlive);
    29.      
    30.     }
    31.  
    Note: this code might need some optimizations for performance
     
    Lifee00 likes this.
  3. Lifee00

    Lifee00

    Joined:
    Apr 13, 2021
    Posts:
    88
    Thanks, works fine now, I also noticed mistake in my code there is actually multiplication by zero, but I hadn't caught it before.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,020
    When you do stuff like this in code:

    ... you are setting yourself up for mass confusion when you change that 5f and (amazingly!) nothing changes in your scene.

    Here's why:

    Serialized / public fields in Unity are initialized as a cascade of possible values, each subsequent value (if present) overwriting the previous value:

    - what the class constructor makes (either default(T) or else field initializers, eg "what's in your code")

    - what may be saved with the prefab

    - what may be saved with the prefab override(s)/variant(s)

    - what may be saved in the scene and not applied to the prefab

    - what may be changed in the scene and not yet saved to disk

    - what may be changed in OnEnable(), Awake(), Start(), or even later

    Make sure you only initialize things at ONE of the above levels, or if necessary, at levels that you specifically understand in your use case. Otherwise errors will seem very mysterious.

    Here's the official discussion: https://blog.unity.com/technology/serialization-in-unity

    If you must initialize fields, then do so in the void
    Reset()
    method, which ONLY runs in the UnityEditor.

    Field initializers versus using Reset() function and Unity serialization:

    https://forum.unity.com/threads/sensitivity-in-my-mouselook-script.1061612/#post-6858908

    https://forum.unity.com/threads/crouch-speed-is-faster-than-movement-speed.1132054/#post-7274596

    To avoid complexity in your prefabs / scenes, I recommend NEVER using the
    FormerlySerializedAsAttribute