Particles And Vector3 Not Turning Back On

Okay, I have created this script that works for both bodies of water and flowing water (such as waterfalls):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Water : MonoBehaviour
{
    //holds the rigidbody of whatever comes into contact with it
    [SerializeField]
    private Rigidbody rb;
    //holds the density of the water
    public float waterDensity;
    //gets the player script
    [SerializeField]
    private Aquatic aquatic;
    //gets the grabbable script
    [SerializeField]
    private Grabbable grabbable;
    //holds the force of the water's current in the three cardinal directions
    [SerializeField]
    private float xForce;
    [SerializeField]
    private float yForce;
    [SerializeField]
    private float zForce;
    //holds the player script
    [SerializeField]
    private Player player;
    //holds the current force
    [SerializeField]
    private Vector3 CurrentForce;
    //holds water wheels
    [SerializeField]
    private WaterWheel waterWheel;
    //holds the current torque
    [SerializeField]
    private Vector3 CurrentTorque;
    //gets the steam particles
    [SerializeField]
    private ParticleSystem steam;
    //holds the ice
    [SerializeField]
    private GameObject ice;
    //holds the ice's dimensions
    [SerializeField]
    private float iceX;
    [SerializeField]
    private float iceY;
    [SerializeField]
    private float iceZ;
    //holds the starting torque
    [SerializeField]
    private Vector3 InitialTorque;
    //gets water flow particles
    [SerializeField]
    private ParticleSystem flow;

    //gets the rigidbody of objects put in water, and sets the force of the current
    private void Awake()
    {
        aquatic = Object.FindObjectOfType<Aquatic>();
        player = Object.FindObjectOfType<Player>();
        CurrentForce = xForce * Vector3.right + yForce * Vector3.up + zForce * Vector3.forward;
        CurrentTorque = InitialTorque;
    }

    //applies force of buoyancy when the object enters the water
    private void OnTriggerEnter(Collider other)
    {
        //releases steam if exposed to fire
        if(other.gameObject.tag == "FireEffect")
        {
            steam.Play();
            StartCoroutine(StopParticles());
            CurrentForce = xForce * Vector3.right + yForce * Vector3.up + zForce * Vector3.forward;
            CurrentTorque = InitialTorque;
            flow.Play();
        }
        //freezes if exposed to ice
        else if(other.gameObject.tag == "IceEffect")
        {
            GameObject newobject = Instantiate(ice, transform.position, Quaternion.Euler(new Vector3(-90, 0, 0)));
            newobject.transform.localScale = new Vector3(iceX, iceY, iceZ);
            CurrentForce = Vector3.zero;
            CurrentTorque = Vector3.zero;
            flow.Stop();
        }
        //applies buoyancy
        if(other.TryGetComponent<Grabbable>(out Grabbable grabbable))
        {
            //applise buoyancy
            grabbable.isSubmerged = true;
            other.transform.gameObject.SendMessage("FloatInWater", waterDensity);
            //applies the force of the current
            other.transform.gameObject.SendMessage("Current", CurrentForce);
        }
        else if (other.TryGetComponent<Aquatic>(out Aquatic aquatic))
        {
            aquatic.isSubmerged = true;
            other.transform.gameObject.SendMessage("FloatInWater", waterDensity);
        }
        //applies current force to the player
        else if (other.TryGetComponent<Player>(out Player player))
        {
            other.transform.gameObject.SendMessage("Current", CurrentForce);
        }
        //applies current force to water wheel
        else if (other.TryGetComponent<WaterWheel>(out WaterWheel waterWheel))
        {
            other.transform.gameObject.SendMessage("Current", CurrentTorque);
        }
    }

    //stops water wheels and currents if frozen
    private void OnTriggerStay(Collider other)
    {
        if(other.TryGetComponent<Grabbable>(out Grabbable grabbable))
        {
            //applies the force of the current
            other.transform.gameObject.SendMessage("Current", CurrentForce);
        }
        //applies current force to the player
        else if(other.TryGetComponent<Player>(out Player player))
        {
            other.transform.gameObject.SendMessage("Current", CurrentForce);
        }
        //applies current force to water wheel
        else if(other.TryGetComponent<WaterWheel>(out WaterWheel waterWheel))
        {
            other.transform.gameObject.SendMessage("Current", CurrentTorque);
        }
    }

    //removes force of buoyancy and water current when the object exits the water
    private void OnTriggerExit(Collider other)
    {
        if(other.TryGetComponent<Grabbable>(out Grabbable grabbable))
        {
            grabbable.isSubmerged = false;
            grabbable.currentForce = Vector3.zero;
        }
        else if(other.TryGetComponent<Aquatic>(out Aquatic aquatic))
        {
            aquatic.isSubmerged = false;
        }
        else if(other.TryGetComponent<Player>(out Player player))
        {
            player.currentForce = Vector3.zero;
        }
        else if(other.TryGetComponent<WaterWheel>(out WaterWheel waterWheel))
        {
            waterWheel.currentTorque = Vector3.zero;
        }
    }

    //stops the particles
    private IEnumerator StopParticles()
    {
        yield return new WaitForSeconds(1f);
        steam.Stop();
    }
}

When certain objects touch flowing water, a Vector3 force is applied to them. If an object with the tag “IceEffect” touches the water, it freezes the water, setting any currents to Vector3.zero, and stopping the particle effect I use to represent flowing water. And if an object with the tag “FireEffect” is put on the ice, it melts, and the water flows and particles should start back up. In theory. In reality, while the ice melts like it should, the particle system for water flows remains inactive and the Vector3 forces applied remain at zero. What am I doing wrong, and how can I fix it?

Time to start debugging! Here is how you can begin your exciting new debugging adventures:

You must find a way to get the information you need in order to reason about what the problem is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

What is often happening in these cases is one of the following:

  • the code you think is executing is not actually executing at all
  • the code is executing far EARLIER or LATER than you think
  • the code is executing far LESS OFTEN than you think
  • the code is executing far MORE OFTEN than you think
  • the code is executing on another GameObject than you think it is
  • you’re getting an error or warning and you haven’t noticed it in the console window

To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run? what order does it run in?
  • what are the names of the GameObjects or Components involved?
  • what are the values of the variables involved? Are they initialized? Are the values reasonable?
  • are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

Knowing this information will help you reason about the behavior you are seeing.

You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as Debug.Log("Problem!",this);

If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

You could also just display various important quantities in UI Text elements to watch them change as you play the game.

Visit Google for how to see console output from builds. If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: How To - Capturing Device Logs on iOS or this answer for Android: How To - Capturing Device Logs on Android

If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

Here’s an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

“When in doubt, print it out!™” - Kurt Dekker (and many others)

Note: the print() function is an alias for Debug.Log() provided by the MonoBehaviour class.

Okay, Kurt, I’ve added a Debug.Log, and found out that the if loop that’s being called if the object that enters the water trigger has a FireEffect tag is not being called. I properly named the tag and everything, but the method is not being called. Why could that be?

I wouldn’t stop there with Debug.Log, because you still haven’t really narrowed down the problem. You’re assuming the tag is to blame, but that may very well be incorrect.

Try checking if OnTriggerEnter is even being called at all by having Debug.Log come before anything else.

If OnTriggerEnter is indeed being called, take it a step further by using Debug.Log to print out the info of the colliding object (“other”), such as its name and/or tag.

1 Like

I know that the OnTriggerEnter itself is being called. Objects tagged IceEffect freeze water, objects with a Rigidbody component are pushed by the currents, and so forth. It’s just that objects tagged FireEffect don’t interact with the water.

UPDATE: The OnTriggerEnter is recognizing objects tagged “FireEffect”, it’s just that the “if(other.gameObject.CompareTag(“FireEffect”))” that’s not firing. What could be the cause of this?

SOLVED: It’s that I have unassigned variables in the inspector.

1 Like

Chubz said this:

and that is exactly right.

It’s like looking for your glasses. If they’re not on the bedstand you don’t just stop. You keep looking. If the closet is too dark to look in, get a flashlight. No flashlight? Then start pulling everything out of your closet. Etc.

And then the magic happens:

and now you feel smart!

Remember the Six Stages Of Debugging:

DENIAL. That can’t happen.
FRUSTRATION. That doesn’t happen on my machine.
DISBELIEF. That shouldn’t happen.
TESTING. Why does that happen?
GOTCHA. Oh, I see.
RELIEF. How did that ever work?

You may laugh now, but it will really seem hilarious to you after the 1000th time it happens.