Search Unity

Question Particles And Vector3 Not Turning Back On

Discussion in 'Scripting' started by tysongrunter, Apr 22, 2023.

  1. tysongrunter

    tysongrunter

    Joined:
    Mar 25, 2023
    Posts:
    19
    Okay, I have created this script that works for both bodies of water and flowing water (such as waterfalls):
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Water : MonoBehaviour
    6. {
    7.     //holds the rigidbody of whatever comes into contact with it
    8.     [SerializeField]
    9.     private Rigidbody rb;
    10.     //holds the density of the water
    11.     public float waterDensity;
    12.     //gets the player script
    13.     [SerializeField]
    14.     private Aquatic aquatic;
    15.     //gets the grabbable script
    16.     [SerializeField]
    17.     private Grabbable grabbable;
    18.     //holds the force of the water's current in the three cardinal directions
    19.     [SerializeField]
    20.     private float xForce;
    21.     [SerializeField]
    22.     private float yForce;
    23.     [SerializeField]
    24.     private float zForce;
    25.     //holds the player script
    26.     [SerializeField]
    27.     private Player player;
    28.     //holds the current force
    29.     [SerializeField]
    30.     private Vector3 CurrentForce;
    31.     //holds water wheels
    32.     [SerializeField]
    33.     private WaterWheel waterWheel;
    34.     //holds the current torque
    35.     [SerializeField]
    36.     private Vector3 CurrentTorque;
    37.     //gets the steam particles
    38.     [SerializeField]
    39.     private ParticleSystem steam;
    40.     //holds the ice
    41.     [SerializeField]
    42.     private GameObject ice;
    43.     //holds the ice's dimensions
    44.     [SerializeField]
    45.     private float iceX;
    46.     [SerializeField]
    47.     private float iceY;
    48.     [SerializeField]
    49.     private float iceZ;
    50.     //holds the starting torque
    51.     [SerializeField]
    52.     private Vector3 InitialTorque;
    53.     //gets water flow particles
    54.     [SerializeField]
    55.     private ParticleSystem flow;
    56.  
    57.     //gets the rigidbody of objects put in water, and sets the force of the current
    58.     private void Awake()
    59.     {
    60.         aquatic = Object.FindObjectOfType<Aquatic>();
    61.         player = Object.FindObjectOfType<Player>();
    62.         CurrentForce = xForce * Vector3.right + yForce * Vector3.up + zForce * Vector3.forward;
    63.         CurrentTorque = InitialTorque;
    64.     }
    65.  
    66.     //applies force of buoyancy when the object enters the water
    67.     private void OnTriggerEnter(Collider other)
    68.     {
    69.         //releases steam if exposed to fire
    70.         if(other.gameObject.tag == "FireEffect")
    71.         {
    72.             steam.Play();
    73.             StartCoroutine(StopParticles());
    74.             CurrentForce = xForce * Vector3.right + yForce * Vector3.up + zForce * Vector3.forward;
    75.             CurrentTorque = InitialTorque;
    76.             flow.Play();
    77.         }
    78.         //freezes if exposed to ice
    79.         else if(other.gameObject.tag == "IceEffect")
    80.         {
    81.             GameObject newobject = Instantiate(ice, transform.position, Quaternion.Euler(new Vector3(-90, 0, 0)));
    82.             newobject.transform.localScale = new Vector3(iceX, iceY, iceZ);
    83.             CurrentForce = Vector3.zero;
    84.             CurrentTorque = Vector3.zero;
    85.             flow.Stop();
    86.         }
    87.         //applies buoyancy
    88.         if(other.TryGetComponent<Grabbable>(out Grabbable grabbable))
    89.         {
    90.             //applise buoyancy
    91.             grabbable.isSubmerged = true;
    92.             other.transform.gameObject.SendMessage("FloatInWater", waterDensity);
    93.             //applies the force of the current
    94.             other.transform.gameObject.SendMessage("Current", CurrentForce);
    95.         }
    96.         else if (other.TryGetComponent<Aquatic>(out Aquatic aquatic))
    97.         {
    98.             aquatic.isSubmerged = true;
    99.             other.transform.gameObject.SendMessage("FloatInWater", waterDensity);
    100.         }
    101.         //applies current force to the player
    102.         else if (other.TryGetComponent<Player>(out Player player))
    103.         {
    104.             other.transform.gameObject.SendMessage("Current", CurrentForce);
    105.         }
    106.         //applies current force to water wheel
    107.         else if (other.TryGetComponent<WaterWheel>(out WaterWheel waterWheel))
    108.         {
    109.             other.transform.gameObject.SendMessage("Current", CurrentTorque);
    110.         }
    111.     }
    112.  
    113.     //stops water wheels and currents if frozen
    114.     private void OnTriggerStay(Collider other)
    115.     {
    116.         if(other.TryGetComponent<Grabbable>(out Grabbable grabbable))
    117.         {
    118.             //applies the force of the current
    119.             other.transform.gameObject.SendMessage("Current", CurrentForce);
    120.         }
    121.         //applies current force to the player
    122.         else if(other.TryGetComponent<Player>(out Player player))
    123.         {
    124.             other.transform.gameObject.SendMessage("Current", CurrentForce);
    125.         }
    126.         //applies current force to water wheel
    127.         else if(other.TryGetComponent<WaterWheel>(out WaterWheel waterWheel))
    128.         {
    129.             other.transform.gameObject.SendMessage("Current", CurrentTorque);
    130.         }
    131.     }
    132.  
    133.     //removes force of buoyancy and water current when the object exits the water
    134.     private void OnTriggerExit(Collider other)
    135.     {
    136.         if(other.TryGetComponent<Grabbable>(out Grabbable grabbable))
    137.         {
    138.             grabbable.isSubmerged = false;
    139.             grabbable.currentForce = Vector3.zero;
    140.         }
    141.         else if(other.TryGetComponent<Aquatic>(out Aquatic aquatic))
    142.         {
    143.             aquatic.isSubmerged = false;
    144.         }
    145.         else if(other.TryGetComponent<Player>(out Player player))
    146.         {
    147.             player.currentForce = Vector3.zero;
    148.         }
    149.         else if(other.TryGetComponent<WaterWheel>(out WaterWheel waterWheel))
    150.         {
    151.             waterWheel.currentTorque = Vector3.zero;
    152.         }
    153.     }
    154.  
    155.     //stops the particles
    156.     private IEnumerator StopParticles()
    157.     {
    158.         yield return new WaitForSeconds(1f);
    159.         steam.Stop();
    160.     }
    161. }
    162.  
    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?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,695
    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: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    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:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    "When in doubt, print it out!(tm)" - Kurt Dekker (and many others)

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

    tysongrunter

    Joined:
    Mar 25, 2023
    Posts:
    19
    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?
     
  4. Chubzdoomer

    Chubzdoomer

    Joined:
    Sep 27, 2014
    Posts:
    131
    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.
     
    Last edited: Apr 23, 2023
    Kurt-Dekker likes this.
  5. tysongrunter

    tysongrunter

    Joined:
    Mar 25, 2023
    Posts:
    19
    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.
     
    Last edited: Apr 23, 2023
    Kurt-Dekker likes this.
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,695
    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.