Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Fritter · Feb 08, 2016 at 09:33 PM · collisioncollider2dbooleanif-statementswhile

How do you trigger a collider to become enabled after the player collider isn't touching it anymore?

So I'm having my character spawn a bomb under his feet, after the bomb spawns it should have no collision, until the character steps off the bomb, rather than push him out of the way when it get's instantiated. I tried to have two colliders (One to be a trigger, and another to be the actual collision) but I'm having a bit of trouble. Here is my code, the game crashes upon instantiating. I had an old build that would not crash, but when walking back onto the bomb and the "IsTouching" activated like it should, but did not collide as I thought it would. I want a way to check "IsTouching" on Start, then after a bool is triggered checking if the player is on or off the bomb, the "IsTouching" never get's used again in the script.

 void Start () { 
         rend = transform.GetComponent<SpriteRenderer>();
         collision = transform.GetComponent<BoxCollider2D>();
         newcollision = transform.GetComponent<BoxCollider2D>();
         player = GameObject.FindWithTag("Player");
         playercollision = player.GetComponent<CircleCollider2D>();
 
         while(playercollision.IsTouching(collision))  
         {
             underPlayer = true;
             newcollision.isTrigger = true;
         }
         while (underPlayer == true)
         {
             collision.isTrigger = true;
         }
         while (playercollision.IsTouching(collision)==false)
         {
             underPlayer = false;
             newcollision.isTrigger = false;
         }
         while (underPlayer == false)
         {
             newcollision.isTrigger = false;
         }
     }
     
     IEnumerator detonationTime(){
     yield return new WaitForSeconds(3);
         collision.isTrigger = true;
         newcollision.isTrigger = true;
         rend.enabled = false;
         isActive = false;
             
 
 }
 

I used to have "if" statements, but when troubleshooting I tried changing it to "while", but it didn't change anything, any help or criticism would be greatly appreciated.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

4 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by allenallenallen · Feb 08, 2016 at 09:41 PM

That's really really bad code. You shouldn't put while loops inside of Start. Instead you want them to check every frame so you should put pretty much all of your code inside of Update.

Your code is a bit all over the place so I don't really want to fix it line by line. Instead, I'll just explain to you how you can fix the collision problem.

First of all, your logic behind using a trigger and a collider is nice. However, what you didn't know is that when you instantiate an object with a trigger that's already touching/inside of the player, the trigger won't know it's there nor will the trigger know when it leaves. (It's a secret Unity feature you will never know unless you tried to do what you just did.)

So instead of a trigger, you should just use a simple distance comparison. If the player is at least X distance away from the bomb, activate the bomb's collider. Simple.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
2

Answer by JoshuaMcKenzie · Feb 09, 2016 at 01:37 AM

easiest way to do it is to spawn the object outside the spawner's collision, set any needed variables and then place the spawned object where it needs to be. all in the same call. I recommend to have this done statically and inside the bombscript. this way the bomb script can have direct control over how its getting spawned. however this isn't important for this to work

 public class BombScript : MonoBehaviour
 {
     // this boolean only allows the bomb to go boom when its armed
     private bool bombIsArmed = false; 
     // If the bomb leaves this collider it will arm
     private Collider armingTrigger;   
 
 
 
     //here I make the bombscript responsible for instantiating itself properly.
     // doing so simplifies the playerscript and possibly any other script that might want to 
     // spawn a bomb too
     public static GameObject BombPrefab; //prefab reference to the bomb that can spawn
     public static GameObject SpawnBomb(Collider armingCollider)
     {
         // lazy load the bomb prefab "Bomb" from the resources folder
         // for this to  work your bomb prefab must be in Assets/Resources and 
         // be named "Bomb"
         if(BombPrefab == null)
             BombPrefab = Resources.Load("Bomb");
 
         // first spawn the bomb OUTSIDE the collider! Preferbly someplace that is never seen
         Vector3 spawnlocation = armingCollider.transform.position + Vector3.down*10000;
         GameObject bomb = 
             GameObject.Instantiate(BombPrefab,spawnlocation,armingCollider.transform.rotation);
         
         //assign the bomb's arming trigger to the collider that was passed in
         bomb.GetComponent<BombScript>().armingTrigger = armingCollider;
         
         //then set it to the exact spot you wanted. the collisions will trigger correctly!
         bomb.transform.position = transform.position;
     }
 
 
 
     void Boom(Collider target)
     {
         //if bomb isn't armed then it can't boom
         if(!bombIsArmed)
         {
             return;
         }
         //place your boom logic here
         Debug.Log("Bomb go boom");
 
         GameObject.Destroy(gameObject);
     }
 
 
 
     void OnTriggerEnter(Collider other)
     {
         Boom(other);
     }
 
 
 
     void OnTriggerExit(Collider other)
     {
         // arm the bomb as soon as it leave's the armingTrigger
         if(other == armingTrigger)
         {
             bombIsArmed = true;
         }
     }
 }

but don't worry the bomb won't explode when it's pushed back into the player's trigger. since our bomb is spawned while not armed, and will only arm once the bomb leaves the player's trigger. Plus now that we have the BombSpcript controlling how its spawned, all that code is managed there which makes the playerscript simpler and allowing it to just directly manage actions and movement on the player itself.

 public class PlayerScript: MonoBehaviour
 {
     // variables that can be read from other scripts
     //  but can only be changed by this script, also
     //  they won't clutter the inspector by default
     public CircleCollider2D armingCollider {get;private set}
 
     void Awake()
     {
         armingCollider = GetComponent<CircleCollider2D>();
     }
 
     void Update()
     {
         if(Input.GetButtonUp("Fire"))
         {
             SpawnBomb();
         }
     }
 
     void SpawnBomb()
     {
         //I make the BombScript responsible for instanitating itself properly
         // it keeps this class simple, lets other classes reuse the 
         // code for spawning bombs, and the Bombscript class has more
         // control over itself
         BombScript.SpawnBomb(armingCollider);
     }
 
 }

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by cbjunior · Feb 09, 2016 at 05:10 PM

You definitely shouldn't be using while loops in the Start method. That is the most likely reason for your game crashing, because if any of the loops' statements evaluate to true, the game will be stuck in an infinite loop during the beginning of that frame. What you want to do instead is take the same type of code you are using in the loops and placing it into if statements in the Update() method. This will allow for the game to continue running while checking the conditions you set every frame.

As for the colliders not working properly, it probably has something to do with placing one collider on top of another. You should instead try to destroy the first collider in the script and then create the second in its place afterwards.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Cathair · Apr 11 at 03:49 PM

In 2021, I solved this problem by the following logic (this article helped):

  1. When Instantiating an object, enable isTrigger property of the BoxCollider2D

  2. Then "re-disable" it again when leaving the trigger area.

      // Your "bomb" prefab
         void Awake()
         {
             this.boxCollider = GetComponent<BoxCollider2D>();
             this.boxCollider.isTrigger = true;
         }
     
         // Just stop overlapping a collider 2D
         private void OnTriggerExit2D(Collider2D collision)
         {
             this.boxCollider.isTrigger = false;
         }
    
    
    
    
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

7 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Changing localScale on Collision2D 2 Answers

Is there a way to make the camera collide with specific objects - 2D 1 Answer

Collecting Array items in order 1 Answer

2D collision won't work? 2 Answers

BoxCollider2D failling verification when Instantiate (Fixed, Cause: big derp) 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges