Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. We are looking for feedback on the experimental Unity Safe Mode which is aiming to help you resolve compilation errors faster during project startup.
    Dismiss Notice
  3. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Help Wanted Recognising collisions after a certain time

Discussion in 'Scripting' started by Galathorn72, Aug 2, 2020.

  1. Galathorn72

    Galathorn72

    Joined:
    Jun 3, 2020
    Posts:
    2
    Hiya all,

    I recently started getting into game dev as a hobby (so that means I am a total noob, please be patient with me).

    I am in the process of building a 2nd Level for my online coursework-game and I am trying to achieve the following:

    1) A second platform to appear after X time (which is a public variable). The code is attached to the second platform and it works.

    2) The barrier in front of the second platform to be destructible by shooting at it, but ONLY after the second platform appears. The script is attached to the barrier and it doesn't work. What happens is that the barrier can be destroyed from the moment the game starts, so it seems that the system doesn't check for the other requirement.

    Also I get the following error on the Unity code:
    "UnityException: FindGameObjectWithTag is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead. Called from MonoBehaviour 'DeactivateBarrier'.
    See "Script Serialization" page in the Unity Manual for further details.
    DeactivateBarrier..ctor () (at Assets/Scripts/DeactivateBarrier.cs:9)"

    I have tried a few iterations of the code, trying to get the code to look for the time the second platform appears, or looking for if the platform appears. I also tried to move whatever code has the FindGameObjectWithTag inside the Start class but without any luck.

    Below I have attached two variations of the same code. Any help will be appreciated. Thanks!

    Variation No. 1
    Code (CSharp):
    1. public class DeactivateBarrier : MonoBehaviour
    2. {
    3.     private GameObject movingPlatform = GameObject.FindGameObjectWithTag("MovingPlatform");
    4.  
    5.     public void Update()
    6.     {
    7.         if (movingPlatform == true)
    8.         {
    9.             Invoke("OnCollisionEnter", 0);
    10.         }
    11.      
    12.     }
    13.  
    14.     void OnCollisionEnter(Collision collision)
    15.         {
    16.             if(GameObject.FindGameObjectWithTag("Projectile"))
    17.             {
    18.             Destroy(gameObject, 0);
    19.             }
    20.         }
    21. }
    22.  
    Variation No. 2
    Code (CSharp):
    1. public class DeactivateBarrier : MonoBehaviour
    2. {
    3.     //reference for the time variable from the MoveToNextPlatform Script
    4.     private float timeForDestruction = GameObject.Find("Second Platform").GetComponent<MoveToNextPlatform>().secondsToAppear;
    5.  
    6.     public void Update()
    7.     {
    8.         if (Time.timeSinceLevelLoad >= timeForDestruction)
    9.         {
    10.             Invoke("OnCollisionEnter", 0);
    11.         }
    12.      
    13.     }
    14.  
    15.     void OnCollisionEnter(Collision collision)
    16.         {
    17.             if(GameObject.FindGameObjectWithTag("Projectile"))
    18.             {
    19.             Destroy(gameObject, 0);
    20.             }
    21.         }
    22. }
     
  2. adehm

    adehm

    Joined:
    May 3, 2017
    Posts:
    85
    You are not trying to find a gameobject because you know it is collision.
    collision.tag == "Projectile"?

    Don't call OnCollisionEnter manually. You can flip a switch on collide when it collides instead of calling it manually. Then count time in Update.

    Code (CSharp):
    1. bool collide = false;
    2. float timer = 0;
    3. readonly float duration = 1; //one second
    4. void OnCollisionEnter(Collision collision)
    5. {
    6.    if(!collide && collision.tag == "Projectile")
    7.    collide = true;
    8.    timer = 0;
    9. }
    10. void Update()
    11. {
    12.    if(collide)
    13.    {
    14.      timer+=Time.deltaTime;
    15.      if(timer>=duration)
    16.       {
    17.           //a second has passed so do something
    18.       }
    19.    }
    20. }
     
    Last edited: Aug 2, 2020
  3. Galathorn72

    Galathorn72

    Joined:
    Jun 3, 2020
    Posts:
    2
    Hi adehm, many thanks you for your reply. I would really appreciate if you could clarify the following things

    1) What does the !collide part do

    2) Why did you have to specify a readonly variable and why did it have to be readonly.

    I have pasted your code in a new script in Unity but I get the following error shown in the screenshot.
     

    Attached Files:

  4. adehm

    adehm

    Joined:
    May 3, 2017
    Posts:
    85
    1) collide is a boolean so asking 'if(collide)' would mean bool == true so it means bool != true or bool == false.

    2) If duration is a fixed amount of time there is no need for it not to be readonly but not a requirement.

    You will have to find out how to check the tag of an object; I'm not sure how to but wanted to clarify to you that you are not Finding it because you already know who is colliding with you because "void OnCollisionEnter(Collision collision)" collision is the collider colliding or maybe collision.gameObject.tag would work but I'm not sure.
     
  5. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    2,402

    A good way to check the tag on the object from the collision is like this:

    Code (CSharp):
    1. if (collision.collider.CompareTag("Projectile")) {
    2.   // Whatever you want to do if the tag is "Projectile"
    3. }
     
unityunity