Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Toggle Box Collider off/on on other objects

Discussion in 'Scripting' started by DarkTulip, Mar 22, 2016.

  1. DarkTulip

    DarkTulip

    Joined:
    Oct 21, 2014
    Posts:
    74
    Hi all,

    I have 9 objects with on every object a Box Collider and the same C# script. When I click on an object in Game mode it moves to a position on the Z axis and when I press the object again it returns to it's original Z coordinate. The next thing I want is when 1 object is moved the other objects can't be clicked on until the moved object is back on it's original position.

    I think I can do this by turning off the Box Colliders of all the cubes which aren't clicked on.

    How can I do this? Is it possible in the same script or should all 9 cubes have a different script?

    This is my script so far.
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class BoxBehavior : MonoBehaviour
    5. {
    6.     public bool boxOut = false;
    7.     public bool rotateMode = false;
    8.  
    9.  
    10.     void Update()
    11.     {
    12.         //When boxOut == true, rotateMode = true
    13.  
    14.         //When rotateMode == true, it's possible to rotate object -90 or 90 degrees.
    15.     }
    16.  
    17.  
    18.     void OnMouseDown()
    19.     {
    20.         //Switch boxOut in or out
    21.         boxOut = !boxOut;
    22.  
    23.         //Move the pressed GameObject on Z axis
    24.         float X = transform.position.x;
    25.         float Y = transform.position.y;
    26.  
    27.         if (boxOut == true)
    28.             transform.position = new Vector3 (X, Y, -6.2f);
    29.         else
    30.             transform.position = new Vector3 (X, Y, -5);
    31.     }
    32. }
     
  2. zhuchun

    zhuchun

    Joined:
    Aug 11, 2012
    Posts:
    423
    Put all BoxCollider under a same root in the hierarchy with a controller script attach on it. So at first, you can use:
    Code (csharp):
    1. BoxCollider[] colliders= GetComponentsInChildren<BoxCollider>();
    Then once you click on a box, disable the reset of them as you said. Is that what you want?
     
  3. DarkTulip

    DarkTulip

    Joined:
    Oct 21, 2014
    Posts:
    74
    I'm sorry, I'm a noob. I don't get it. Can you please be more specific?
     
  4. zhuchun

    zhuchun

    Joined:
    Aug 11, 2012
    Posts:
    423
    OK. Forget about it, let's make it easier :)
    First give your objects a tag say "Box". No idea? Click here and you can see an "Add Tag" option.
    tags.png
    Then add these lines in your BoxBehaviour.OnMouseDown().
    Code (CSharp):
    1.  GameObject[] boxes= GameObject.FindGameObjectsWithTag("Box"); //your tag name here
    2.         foreach (var item in boxes)
    3.         {
    4.             if (item!=this.gameObject) //for others
    5.             {
    6.                 item.GetComponent<BoxCollider>().enabled = false;
    7.             }
    8.         }
     
    bengoodhart16 likes this.
  5. DarkTulip

    DarkTulip

    Joined:
    Oct 21, 2014
    Posts:
    74
    That's great. Thank you. Only one thing left. When I click the box with BoxCollider again all other BoxColliders should turn on again. Can you please tell me how?
     
  6. zhuchun

    zhuchun

    Joined:
    Aug 11, 2012
    Posts:
    423
    Then you should use another script say "BoxColliderController" to store what has been clicked and how to deal with it. The key is your objects should "share" something like a bool or state, so they can know what to do next.
     
  7. DarkTulip

    DarkTulip

    Joined:
    Oct 21, 2014
    Posts:
    74
    Isn't it possible to put something in this script like this?
    (to put it in noob code)
    Code (csharp):
    1.  if (All game objects with tag "Box" are at Z axis -5)
    2.  all boxColliders enabled = true;
     
  8. zhuchun

    zhuchun

    Joined:
    Aug 11, 2012
    Posts:
    423
    No doubt it's ok, C# is a language designed for multiple approach. However, we always considering scalability while designing games. So we prefer to use state to represent things, after all, most games are state-machines. In your case, you can feel free to hard-code the state like 'Z axis equals -5' until you feel the boundary. BTW it's totally fine and normal, so don't worry, just try more. :)
     
  9. DarkTulip

    DarkTulip

    Joined:
    Oct 21, 2014
    Posts:
    74
    I tried a lot of different code to make my noob code to work. Obviously I don't know what I'm doing. The following doesn't work. I've tried to reuse your code for the new part. Your code works perfectly. mine doesn't work at all. What am I doing wrong?
    Code (CSharp):
    1. //Makes sure the other boxes can't be selected when 1 box is out
    2.         GameObject[] boxes = GameObject.FindGameObjectsWithTag("Box");
    3.         foreach (var item in boxes)
    4.         {
    5.             if (item!=this.gameObject) //for others
    6.             {
    7.                 item.GetComponent<BoxCollider>().enabled = false;
    8.             }
    9.         }
    10.  
    11.         //Make all boxes selectable again
    12.  
    13.         //if (All game objects with tag "Box" are at Z axis -5)
    14.         //    all boxColliders enabled = true;
    15.         GameObject[] allBoxes = GameObject.FindGameObjectsWithTag("Box");
    16.         foreach (var box in allBoxes)
    17.         {
    18.             if (allBoxes.position.z == -5)
    19.             {
    20.                 item.GetComponent<BoxCollider> ().enabled = true;
    21.             }
    22.         }
    Thank you for all your replies.
     
  10. zhuchun

    zhuchun

    Joined:
    Aug 11, 2012
    Posts:
    423
    1. Any events similar to OnClick() will NOT be triggered if there wasn't any Collider attached or Collider.enabled==false.
    2. I don't like to use float compare as criteria, so I'm not sure whether it works or not. But if it doesn't work, it may relate to float precision issue. Say you set box.position.z=5 now, then go back to the inspector you may find position.z is something like 4.99999x10^13, strictly speaking it's not 5.
    So I would suggest you to use
    Code (csharp):
    1. bool IsMoved=false
    instead of any kinds of hard-code number as criteria.
     
  11. alexw21

    alexw21

    Joined:
    Jun 26, 2017
    Posts:
    3
    MissingComponentException: There is no 'BoxCollider' attached to the "Cube" game object, but a script is trying to access it.
    You probably need to add a BoxCollider to the game object "Cube". Or your script needs to check if the component is attached before using it.
    PlayerController.Update () (at Assets/Script/PlayerController.cs:52)

    i got error how do i Fix
     
  12. alexw21

    alexw21

    Joined:
    Jun 26, 2017
    Posts:
    3
    PlayerController.Update () (at Assets/Script/PlayerController.cs:52)

    GameObject[] Obstacles = GameObject.FindGameObjectsWithTag("Obstacle");
    foreach (var respawn in Obstacles)
    {
    if (respawn != this.gameObject)
    {
    respawn.GetComponent<BoxCollider>().enabled = false;
    }
    }
     
  13. zhuchun

    zhuchun

    Joined:
    Aug 11, 2012
    Posts:
    423
    Hi, this is a different question so please start a new topic next time. Regarding the error you met, it was caused by this line.
    Code (CSharp):
    1. respawn.GetComponent<BoxCollider>().enabled = false;
    It assumed that it could 100% got a BoxCollider component from 'respawn', but actually it was not, so there's no way it could set that enabled property.
    Code (CSharp):
    1. var collider = respawn.GetComponent<BoxCollider>();
    2. collider?.enabled = false;
    This should ignore your problem temporarily, however, you need to check WHY there's gameObject without a component it should have by design, maybe you forgot to add a BoxCollider to its prefab?