Items Combining

When an object with a tag of water and another object with a tag of water are combined, the two objects delete and I want to spawn an object with a tag of river. However, those water objects delete, but 2 river objects are spawned.

(An object with a tag of water and another object with a tag of water both have this script)

Why 2 rivers are spawned, and I need solution about this.

void OnCollisionEnter2D(Collision2D other)
{
    if (this.gameObject.tag == "Water" && other.gameObject.tag == "Dirt")
    {
        Destroy(this.gameObject);
        Destroy(other.gameObject);

        Instantiate(MudObj);
    }

    if (this.gameObject.tag == "Mud" && other.gameObject.tag == "Fire")
    {
        Destroy(this.gameObject);
        Destroy(other.gameObject);

        Instantiate(BrickObj);
    }

    if (this.gameObject.tag == "Fire" && other.gameObject.tag == "Water")
    {
        Destroy(this.gameObject);
        Destroy(other.gameObject);

        Instantiate(VaporObj);
    }

    if (this.gameObject.tag == "Water" && other.gameObject.tag == "Water")
    {
        Destroy(this.gameObject);
        Destroy(other.gameObject);

        Instantiate(RiverObj);
    }
}

}

well the “why” is obvious here: when you have 2 objects with the same tag and the same script then both will execute line 26 to line 32. Thus 2 River objects will spawn.

The “how to solve this” could look like this:
Create a

  public bool collided = false;

in your script.
Then On Collision get the script of the other object and set the collided flag to true (but only if one element combination was executed!). Then add this check in your OnCollisionEnter method:

  if(collided)
         return;

then it works.

Some general advice: using

   this.gameObject.tag == "Water"

is slow and not performant. Use

    this.gameObject.CompareTag("Water")

for better performance.

Also you repeat yourself a lot in your code. You might want to rewrite that.
For example create a “reactElements” function:

 public void reactElements(GameObject other, GameObject prefab) {
     Destroy(this.gameObject);
     Destroy(other.gameObject);
     Instantiate(prefab);
     collided = true;
     other.GetComponent<ThisScriptType>().collided = true;
 }

and then your code can look like:

void OnCollisionEnter2D(Collision2D other)
 {
     if(collided)
            return;
     if (this.gameObject.CompareTag("Water" )&& other.gameObject.CompareTag("Dirt"))
     {
         reactElements(other, MudObj);
     }
     else if (this.gameObject.CompareTag("Mud") && other.gameObject.CompareTag( "Fire"))
     {
         reactElements(other, BrickObj);
     }
     else if (this.gameObject.CompareTag("Fire" )&& other.gameObject.CompareTag("Water"))
     {
         reactElements(other, VaporObj);
     }
     else if (this.gameObject.CompareTag("Water" )&& other.gameObject.CompareTag("Water"))
     {
         reactElements(other, RiverObj);
     }
 }

In general you might want to find a different solution for the Element pair detection that you currently have. If you continue with that solution that you use now you’ll hate yourself for it in half a year.

But the console says: Assets/Scripts/Recipes.cs(20,27): error CS1503: Argument 1: cannot convert from ‘UnityEngine.Collision2D’ to ‘UnityEngine.GameObject’