Search Unity

C# OnTrigger2DEnter Triggers Multiple Times in Procedural Grid

Discussion in 'Scripting' started by kenaochreous, Jul 22, 2016.

  1. kenaochreous

    kenaochreous

    Joined:
    Sep 7, 2012
    Posts:
    395
    I've been working on this procedural grid for my 2D game. Basically how it works is there are 9 grid pieces(1 parent 8 children). The parent is located in the center of the grid and each child will move the parent to their location if the player has entered said child's 2Dcollider. Both the parent and the children instantiate a generator which randomly generates prefabs within it's 2Dcollider.These prefabs are then parented to the generator. The parent only instantiates a generator once on start since that's all it needs to do whereas the children move the parent to it's position and then instantiates the generator at the parent's position. Once the player has exited the generator's 2Dcollider all prefabs parented to it are disabled and when the player re-enters the generator a check occurs to determine if there's already a generator there and then if there is all prefabs parented to that generator are re-enabled.

    Now somehow the OntriggerEnter2D function in the MoveParentInstantiate script attached to the childGrids is occuring more then once even though it shouldn't. I ran a debug log and somehow the PlayerSquare is being detected multiple times even though it only has one collider. I've also tried using a bool to make sure instantiate only occurs once but it OntriggerEnter2D still triggered multiple times. All the gameobjects only have one collider each and the PlayerSquare isn't set to trigger. Some sort of overlapping is occurring I just can't figure out what is overlapping. Are there anything else I could check for that may be causing this?
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class MoveParentInstantiate : MonoBehaviour {
    5. public GameObject generator;
    6.     void OnTriggerEnter2D(Collider2D other) {
    7.         Debug.Log(other.gameObject.name);
    8.         if(other.gameObject.tag == "Player"){
    9.             if(transform.parent != null){
    10.                 transform.parent.position = transform.position;
    11.                 Instantiate(generator, transform.parent.position, Quaternion.identity);
    12.             }
    13.         }
    14.     }
    15. }
    16.  
     

    Attached Files:

  2. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    ...I'm lost forever, could you please make the whole story shorter/easier, and/or order it in a list?
     
  3. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    It sounds like the short version is "the OnTriggerEnter2D() is being called twice when the players enters the collider".

    I would wonder, do many "triggers" exist close to each other? Is it possible the player is triggering this method to be called on two separate triggers, but because they happen so closely it appears to be just one calling it twice? That's my best guess anyway.
     
  4. kenaochreous

    kenaochreous

    Joined:
    Sep 7, 2012
    Posts:
    395
    There are 9 gameobjects(1 parent 8 children) in a 3x3 grid. When the player triggers a child's 2D collider the parent's position moves to that child's position and instantiates a generator. That generator then randomly instantiates gameobjects from an array within it's bounds. I apologize if that wasn't clear.
    I believe so, I think I figured out what is happening. The child opposite to triggered child is getting triggered too and that's why I'm getting more than one generator when the player transitions. I'm not really sure how I could fix this because the children have to stay where they are in order for my procedural generation to work. One other thing I noticed is that if I let the scene run for a bit the grid fixes itself. I'm not really sure why but it does.

    Edit: I tried creating an array for all the children's sibling's 2D colliders, disabled them at the start of OnTriggerEnter2D and then re-enabled them after the instantiation but it didn't work. the child opposite to the child being triggered is still being triggered and instantiating another generator.
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class MoveParentInstantiate : MonoBehaviour {
    5. public Collider2D[] siblingColliders;
    6. public GameObject generator;
    7.     void OnTriggerEnter2D(Collider2D other) {
    8.         Debug.Log(other.gameObject.name);
    9.         if(other.gameObject.tag == "Player"){
    10.             for(int i = 0; i < siblingColliders.Length; i++)
    11.             {
    12.             siblingColliders[i].enabled = false;  
    13.             }
    14.             if(transform.parent != null){
    15.                 transform.parent.position = transform.position;
    16.                 Instantiate(generator, transform.parent.position, Quaternion.identity);
    17.             for(int i = 0; i < siblingColliders.Length; i++)
    18.             {
    19.             siblingColliders[i].enabled = true;  
    20.             }
    21.             }
    22.         }
    23.     }
    24. }
    25.  
     
    Last edited: Jul 22, 2016
  5. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    Maybe reduce the size of the triggers very slightly, so there's a bit of a gap between, might make it work...
     
  6. kenaochreous

    kenaochreous

    Joined:
    Sep 7, 2012
    Posts:
    395
    Yep that was it, I included an extra bit of code which adds the playerSquare's collider size to the childgrids' positions. It works perfectly
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class MoveParentInstantiate : MonoBehaviour {
    5. public BoxCollider2D playerCollider;
    6. public bool xIsNegative;
    7. public bool yIsNegative;
    8. public GameObject generator;
    9.     void Awake()
    10.     {
    11.         if(!xIsNegative && !yIsNegative){
    12.         transform.position = new Vector3(transform.position.x + playerCollider.size.x,transform.position.y + playerCollider.size.y,transform.position.z);
    13.         }
    14.         else if(xIsNegative){
    15.         transform.position = new Vector3(transform.position.x - playerCollider.size.x,transform.position.y + playerCollider.size.y,transform.position.z);
    16.         }
    17.         else if(yIsNegative){
    18.         transform.position = new Vector3(transform.position.x + playerCollider.size.x,transform.position.y - playerCollider.size.y,transform.position.z);
    19.         }
    20.         else if(xIsNegative && yIsNegative){
    21.         transform.position = new Vector3(transform.position.x - playerCollider.size.x,transform.position.y - playerCollider.size.y,transform.position.z);
    22.         }
    23.     }
    24.     void OnTriggerEnter2D(Collider2D other) {
    25.         Debug.Log(other.gameObject.name);
    26.         if(other.gameObject.tag == "Player"){
    27.             if(transform.parent != null){
    28.                 transform.parent.position = transform.position;
    29.                 Instantiate(generator, transform.parent.position, Quaternion.identity);
    30.             }
    31.         }
    32.     }
    33. }
    34.  
     
  7. gouthammannuru

    gouthammannuru

    Joined:
    Sep 9, 2015
    Posts:
    16
    Nope
     
  8. xjjon

    xjjon

    Joined:
    Apr 15, 2016
    Posts:
    612
    You could check a bool before instantiating, to prevent it from running twice?
     
  9. kenaochreous

    kenaochreous

    Joined:
    Sep 7, 2012
    Posts:
    395
    Okay so now I need to make sure that if I move the player back to a position that previously had a generator on it doesn't instantiate another generator. I've created a vector3 list which adds the generators' positions and then I ran a for loop to see if(pastGeneratorPositions != transform.position) however the generators are still instantiating.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3. public class MoveParentInstantiate : MonoBehaviour {
    4. public BoxCollider2D playerCollider;
    5. public bool xIsNegative;
    6. public bool yIsNegative;
    7. public GameObject generator;
    8. public List<Vector3> previousGeneratorPositions = new List<Vector3>();
    9.     void Awake()
    10.     {
    11.         if(!xIsNegative && !yIsNegative){
    12.         transform.position = new Vector3(transform.position.x + playerCollider.size.x,transform.position.y + playerCollider.size.y,transform.position.z);
    13.         }
    14.         else if(xIsNegative){
    15.         transform.position = new Vector3(transform.position.x - playerCollider.size.x,transform.position.y + playerCollider.size.y,transform.position.z);
    16.         }
    17.         else if(yIsNegative){
    18.         transform.position = new Vector3(transform.position.x + playerCollider.size.x,transform.position.y - playerCollider.size.y,transform.position.z);
    19.         }
    20.         else if(xIsNegative && yIsNegative){
    21.         transform.position = new Vector3(transform.position.x - playerCollider.size.x,transform.position.y - playerCollider.size.y,transform.position.z);
    22.         }
    23.     }
    24.      void OnTriggerEnter2D(Collider2D other) {
    25.         if(other.gameObject.tag == "Player"){
    26.             if(transform.parent != null){
    27.                 transform.parent.position = transform.position;
    28.                 for(int i = 0; i < previousGeneratorPositions.Count; i++){
    29.                     if(previousGeneratorPositions[i] != transform.position){
    30.                     Instantiate(generator, transform.parent.position, Quaternion.identity);
    31.                     }
    32.                 }
    33.             }
    34.         }
    35.     }
    36. }
     
  10. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    Hmm?
     
  11. gouthammannuru

    gouthammannuru

    Joined:
    Sep 9, 2015
    Posts:
    16
    he did choose one action (void OnTriggerEnter2D(Collider2D other))
    refers to a single 2DCollider Only
     
  12. kenaochreous

    kenaochreous

    Joined:
    Sep 7, 2012
    Posts:
    395
    It's fine, as I previously stated my problem has been fixed and I've moved on to my current issue. I need to make sure that only one generator is instantiated per position so that I don't have multiple generators sitting on top of each other when the player moves back to a previously instantiated position. I've added the generators to a list but I'm not sure how I'm going to compare them since my for loop and if statement are being bypassed.
    Code (CSharp):
    1.                 for(int i = 0; i < previousGeneratorPositions.Count; i++){
    2.                     if(previousGeneratorPositions[i] != transform.position){
     
  13. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    Oh I thought that was possible, my mistake.
     
  14. gouthammannuru

    gouthammannuru

    Joined:
    Sep 9, 2015
    Posts:
    16
    Nothing serious bro..... Just letting you know one of the least things i Know...LOL:)
     
  15. gouthammannuru

    gouthammannuru

    Joined:
    Sep 9, 2015
    Posts:
    16
    Are you trying to call 2 logic generations at the same time