Search code examples
c#unity-game-engineraycastingparticle-system

The particles spawn on the wrong place


I'm making a game in Unity where you can chop down trees, I want to make it so that particles spawn where you hit the tree. At this point the particles spawn where the player is, this is because the script is on the player. But how can I spawn the particles in the right place? (Where I hit the tree) It's probably not even that hard to solve, but I can't figure it out. My current C# code is below.

 public class ChopTree : MonoBehaviour
     {
         public int damage = 25;
         public Camera FPSCamera;
         public float hitRange = 2.5f;
         private TreeScript Tree;
     
         // Particles
         public GameObject particles;
     
         void Update()
         {
             Ray ray = FPSCamera.ScreenPointToRay(new Vector2(Screen.width / 2, Screen.height / 2));
             RaycastHit hitInfo;
     
             if(Input.GetKeyDown(KeyCode.Mouse0))
             {
                 if(Physics.Raycast(ray, out hitInfo, hitRange))
                 {
                     // The tag must be set on an object like a tree
                     if(hitInfo.collider.tag == "Tree" && isEquipped == true)
                     {
                         Tree = hitInfo.collider.GetComponentInParent<TreeScript>();
                         StartCoroutine(DamageTree());
                         StartCoroutine(ParticleShow());
                     }
                 }
             }
         }
     
         private IEnumerator DamageTree()
         {
             // After 0.3 seconds the tree will lose HP
             yield return new WaitForSeconds(0.3f);

             Tree.health -= damage;
         }
     
         private IEnumerator ParticleShow()
         {
             // After 0.3 second the particles show up
             yield return new WaitForSeconds(0.3f);

             Instantiate(particles, transform.position, transform.rotation);
         }
     }

Solution

  • Well instead of

    Instantiate(particles, transform.position, transform.rotation);
    

    make sure you use the hit tree positions like

    Instantiate(particles, Tree.transform.position, transform.rotation);
    

    Actually personally I would merge both Coroutines together and pass in the according tree:

    private IEnumerator ChopTree(TreeScript tree)
    {
        // After 0.3 seconds the tree will lose HP
        yield return new WaitForSeconds(0.3f);
    
        Instantiate(particles, tree.transform.position, transform.rotation);
        tree.health -= damage;
    }
    

    and then

    void Update()
    {
        var ray = FPSCamera.ScreenPointToRay(new Vector2(Screen.width / 2, Screen.height / 2));
     
         if(Input.GetKeyDown(KeyCode.Mouse0))
         {
             if(Physics.Raycast(ray, out var hitInfo, hitRange))
             {
                 // The tag must be set on an object like a tree
                 if(hitInfo.collider.CompareTag("Tree") && isEquipped)
                 {
                     var tree = hitInfo.collider.GetComponentInParent<TreeScript>();
                     if(tree) 
                     {
                         StartCoroutine(ChopTree(tree));
                     }
                 }
             }
         }
    }