Search Unity

Resolved Can't Play Unity Particle System WHEN I want and WHERE I want

Discussion in 'Scripting' started by SirioRigel, Jul 24, 2021.

  1. SirioRigel

    SirioRigel

    Joined:
    Apr 10, 2021
    Posts:
    27
    So I'm making a little 2d game where you have to mine a certain ore, the newest feature that I'm introducing is( using the particle system ) generating little pixels whenever you click the ore, I'm using the function
    Code (CSharp):
    1. [SerializeField] private ParticleSystem miningParticles;
    2.  
    3. private void Start()
    4.     {
    5.         miningParticles.Stop();
    6.     }
    7.     private void Update()
    8.     {
    9.         if (Click.clicked) //clicked checks if the ore has been clicked from another script called "Click"
    10.         {
    11.             miningParticles.Play();
    12.         }
    13.         else
    14.         {
    15.             miningParticles.Stop();
    16.         }
    17.     }
    But the particle system just doesn't play at all, what am I getting wrong?

    Also I wanted to play it where it was the last mouse position, let's say using a new Vector2 (Input.mouseposition.x, Input.mouseposition.y) but when I check the particle system's transform it's out of the screen, so if anyone could help me it would be so great!
     
    Last edited: Jul 24, 2021
  2. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    The latter one is because mousePosition is not world space, it's in screen pixels, you need to convert it to world space with something like myCamera.ScreenToWorldPoint
     
  3. SirioRigel

    SirioRigel

    Joined:
    Apr 10, 2021
    Posts:
    27
    Thx for the reply, so I tryied using this instead in a void Update like you suggested, and it works! But now I stumbled upon the second issue, the particle system doesn't play at all

    **EDIT: from the console I can see that the coords are right but in the scene when the particle system is looping the position is wayy off, it's actually much more moved to the upper left corner than it should**
    Code (CSharp):
    1.     private void Update()
    2.     {
    3.         position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
    4.         cam.ScreenToWorldPoint(position);
    5.         miningParticles.transform.localPosition = position;
    6.         if (clicked == true)
    7.         {
    8.             miningParticles.Play();
    9.             Debug.Log("Playing");
    10.         }
    11.         else
    12.         {
    13.             miningParticles.Stop();
    14.         }
    When I run the code, I know that the particle system will be played only for 1/200 of a second, but the debug log there just doesn't show in the console for some reason. Thx in advance
     
    Last edited: Jul 24, 2021
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    I almost never start / stop my particle systems. Here's how I do what you want:

    - craft your particle system
    - mark it as Play on Awake
    - set Emit over time and Emit over Distance --> ZERO
    - Simulation space: World

    When you need a poof anywhere:

    - move the particle system there
    - align its rotation (such as for splashes away from water or a wall)
    - call
    myParticleSystem.Emit( XXX);
    to emit XXX particles

    For something continuous like a flamethrower, you would set the emit over time to what you want, then turn it to zero and back up to that level in code, always leaving it playing.

    EDIT: note: you would need one instance of a particle system per location that you intend to use in one single given frame. If you only intend to spark / poof at one spot per frame, great, one ParticleSystem will suffice. Otherwise you would need to have a round-robin pool of them to recycle.
     
    Last edited: Feb 19, 2024
    EmilyBest, exiguous and adamgolden like this.
  5. SirioRigel

    SirioRigel

    Joined:
    Apr 10, 2021
    Posts:
    27
    Thank you, the function myParticleSystem.Emit( XXX) worked perfectly and now I'm able to control it, however I still can't convert the mouse position as the world position, so the particle system appears in the wrong position, here is what I did to get the particle system position even though it doesn't seem to work
    Code (CSharp):
    1.         position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);   //gets the mouse position
    2.         cam.ScreenToWorldPoint(position);                                       //Sets the mouse position to as the world position
    3.         miningParticles.transform.position = position;                         //Sets the mouse position to the world position of the particles
     
    Last edited: Jul 25, 2021
  6. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    Code (csharp):
    1. cam.ScreenToWorldPoint(position);
    The method returns the value you are interested in (look in its documentation!). You do nothing with it. If you want to use it store it in a variable of the return type and apply it where necessary (fe in the next line). You should also wonder about the type "mismatch" as mouse position is a Vector2 and transform.position is a Vector3. This already indicates that they are not used for the same purpose.

    Edit: The Vector provided should already be a Vector3 where z is the "depth" of the point. If you have variable depths you should cast a Ray through that point to get an intersection with your geometry or an "abstract" plane of the playfield.
     
  7. SirioRigel

    SirioRigel

    Joined:
    Apr 10, 2021
    Posts:
    27
    Yeah then how should I do that, is there any function that sets the center of the world as the current mouse pos so taht by setting the particle system pos to 0,0 it appears where the mouse is? Also how can I convert from the pixels of the screen to the world pos, is there any formula? Thx in advance
     
  8. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    Do what?

    It seems you are "messing things up" a bit here. Mouse coordinates are in screen space (screen pixel coordinates). GameObjects (particle systems) are placed in world space (Vector3). The method you use calculates the former in the latter. But you have to use its return value since that is the value you are interested in. Currently you are omitting the value since you don't store amd use the return value. As I said, look in the documentation since there is an example.

    Thats exactly what the method is doing. You just have to use it properly.

    As a general note: The documentation of the Unity API is your friend. It tells you what parameters a method expects and what it returns. Use it. If you have problems with general coding and don't know what a return value is, I recommend to learn C# properly first before venturing into Unity. A good resource for that is the free C# Yellow book by Rob Miles.

    You should also use Debug.Log statements to "verify" what your code does, what values variables have etc.. It's important to "evaluate" or "execute" the code in your mind and follow it. What happens where.
     
  9. SirioRigel

    SirioRigel

    Joined:
    Apr 10, 2021
    Posts:
    27
    I finally figured it out I succeded in correctly placing my particles where the mouse is without using ScreenToWorldPoint() since I didn't quite understand how it works, here is what I did if you care
    Code (CSharp):
    1.     private void Awake()
    2.     {
    3.  
    4.         //Finding Pixel To World Unit Conversion Based On Orthographic Size Of Camera
    5.         WorldUnitsInCamera.y = cam.GetComponent<Camera>().orthographicSize * 2;
    6.         WorldUnitsInCamera.x = WorldUnitsInCamera.y * Screen.width / Screen.height;
    7.  
    8.         WorldToPixelAmount.x = Screen.width / WorldUnitsInCamera.x;
    9.         WorldToPixelAmount.y = Screen.height / WorldUnitsInCamera.y;
    10.     }
    11.  
    12.     public void OnClick()
    13.     {
    14.         Vector2 ConvertToWorldUnits; //converts the pixels in world units
    15.         ConvertToWorldUnits.x = ((Input.mousePosition.x / WorldToPixelAmount.x) - (WorldUnitsInCamera.x / 2)) + cam.transform.position.x;
    16.         ConvertToWorldUnits.y = ((Input.mousePosition.y / WorldToPixelAmount.y) - (WorldUnitsInCamera.y / 2)) + cam.transform.position.y;
    17.         miningParticles.transform.position = ConvertToWorldUnits;    //Sets the particles position as the converted units
    18.         miningParticles.Emit(3);
    19.     }
    It's pretty messy and I admit that I helped myself by using an old thread to find the conversion formula inside the OnClick method.
    Thank you anyways for your help and your time you dedicated to me!
     
  10. JustTiredOfEverything

    JustTiredOfEverything

    Joined:
    Aug 4, 2022
    Posts:
    80
    I'm sorry, I can't resist. This is driving me crazy.

    All you had to do was simply change:
    Code (CSharp):
    1. position = new Vector2 (Input.mousePosition.x, Input.mousePosition.y); //gets the mouse position
    2. cam.ScreenToWorldPoint (position); //Sets the mouse position to as the world position
    3. miningParticles.transform.position = position; //Sets the mouse position to the world position of the particles
    To:
    Code (CSharp):
    1. position = new Vector2 (Input.mousePosition.x, Input.mousePosition.y); //gets the mouse position
    2. Vector3 positionInWorld = cam.ScreenToWorldPoint (position); //Sets the mouse position to as the world position
    3. miningParticles.transform.position = positionInWorld; //Sets the mouse position to the world position of the particles
    This is what everyone meant by you weren't using it, or you have to use it properly, etc. I suppose they weren't trying to just outright give you the answer, but I just don't see the point in beating around the bush.
     
    Last edited: Feb 8, 2023
    exiguous likes this.