Search Unity

issue with negatvie scale and colliders on 2d.

Discussion in 'Editor & General Support' started by ziv03, Dec 25, 2013.

  1. ziv03

    ziv03

    Joined:
    Nov 22, 2013
    Posts:
    13
    I'm making a 2d game using unity 4.3
    To explain this problem:
    I have a gameobject called gameObject1 and a child of gameObject1 with the name hand.
    the hand has a sprite and a simple boxcollider2D. Oh, and the hand (the hand gameobject, not gameObject1) is rotated. so this is my normal situation:
    $normal.JPG
    It's tottaly fine, BUT when I set the gameObject1 x scale to -1 (to flip character), the hand collider acts strange and shrinks. you can see it here:
    $bad.JPG
    I don't know if it's a bug or not. But I need to solve this before I can continue developing.

    Any ideas?
     
  2. grindhouse

    grindhouse

    Joined:
    Aug 2, 2013
    Posts:
    7
    I'm having exactly the same problem.
    I don't have a solution, but have some more information about this issue:

    create an empty GameObject (position:0,0,0 rotation:0,0,0, scale:1,1,1)
    then create a cube (position: 0,0,0, rotation: 20,0,0, scale: 0.1, 1, 0.1) so it looks like a stick or leg in 20 degrees rotation.
    add a box collider to the cube.
    and make the cube be a child of the empty GameObject.

    now, scale the empty gameobject to x:-1 and then start changing the cube Z axis... you will see how the cube collider and the cube mesh rotate differently (exactly as it happens on your 2D)

    but... in a 3D scene.. you can get around this problem by using a 180 degrees Y-Axis rotation of the empty gameobject and leaving the scale in 1,1,1.... if you do that, you can rotate the child z axis without issues.

    but, if you do exactly the same thing on a 2D sprite... the workaround of 180 y-axis rotation doesn't work, it behaves different like the -1 scaling, but it still unexpected behaviour.

    I don't have a solution for this issue, but I hope this description helps to describe what''s going on, and how to recreate it.

    a solution or workaround would be nice :)
     
    Last edited: Dec 26, 2013
  3. grindhouse

    grindhouse

    Joined:
    Aug 2, 2013
    Posts:
    7
    Last edited: Dec 26, 2013
  4. ziv03

    ziv03

    Joined:
    Nov 22, 2013
    Posts:
    13
    Thanks, the workaround won't actually work for me because I have rigidbodys attached with the colliders.
    I still didn't decide what to do. If i switch to 3D colliders it will add so much work, so I'm kinda leaving it like this for now, hoping a solution might come..
     
    Last edited: Dec 26, 2013
  5. Graham-Dunnett

    Graham-Dunnett

    Administrator

    Joined:
    Jun 2, 2009
    Posts:
    4,287
    Applying negative scale to an object is guaranteed to mess with your head. Think of a square. The vertices are ordered let's say clockwise. Let's assume that that means the square is facing us. Now start to apply a scale of 0.9, 0.8… 0.2, 0.1. Obviously the square is getting narrower, but it's still facing us. Now apply a scale of 0.0. The square is now infinitely thin. Is it a square any more? Can you collide with an infinitely thin square? Now apply a negative scale, let's choose -1.0 for ease. The square is still a square, but now the order of the vertices have changed. The vertices are now ordered anti clockwise. This means that the square is facing away from us, so we're effectively looking at the back of the square. Depending on how the maths of the collision detection is written, this might mean that collision fails to work as expected. Here's an example:

    A---B
    |...|
    |...|
    D---C

    The vertices are organized A->B->C->D, so that's clockwise. Here's the square with a negative scale:

    B---A
    |...|
    |...|
    C---D


    Now, it's possible that the collision detection routine says that a point to the left of the B->C line is inside the square. Now that we've negatively scaled the square, this line has changed position, and left of the B->C line is now outside the square. Collision detection may now fail.
     
  6. ziv03

    ziv03

    Joined:
    Nov 22, 2013
    Posts:
    13
    Thank's for the explanation! it really helps!
    But unfortunately, I still son't have a solution to my problem :(
    any suggeestion for a solution?
     
  7. grindhouse

    grindhouse

    Joined:
    Aug 2, 2013
    Posts:
    7
    but have you ever tried using negative scale in unity? it works just fine, It's also recommended for flipping 2d sprites in this unity published tutorial : http://unity3d.com/learn/tutorials/modules/beginner/2d/2d-overview

    The bug described in this thread is not related to negative scaling, it's reproducible without even scaling to a negative factor, it's not even tied to 2D colliders, it's just that 2D colliders are more limited than 3D colliders as you can't rotate them around the Y axis

    the funny thing: I just found a solution while writting this post as I tried to verify that Y-Axis rotation statement I just made on 2D colliders (which I also read on another 2d sprite negative-scaling thread).

    Ziv03: try to replicate this and let me know if it works

    I create an emtpy gameObject called Robot with the following components: Animator, Animation, Rigidbody 2D and a script "robotControl" which I made for controlling the robot.

    then I create another empty GameObject called "RobotModel" with no components, and make it child of "Robot".
    Finally, I put all the 2D sprites as childs of RobotModel.

    the tree looks like this:
    PHP:
    Robot 
      
    |__ RobotModel
              
    |__ head
              
    |__ neck
              
    |__ torso
              
    |__ left leg
              
    |__ right leg
              
    |__ left arm
              
    |__ right arm
    Be carefull not to use any Box Collider 2D on those sprites... use only Polygon Collider 2D, and shape them as boxes if you wish, but don't put Box Colliders 2D !!

    now, instead of scaling -1 the "Robot" X-Axis, you just do rotate RobotModel Y-Axis in 180 degrees everytime you want to flip the sprites.

    Note: if the sprites have different Z positions for layering, then you will also have to invert their sign by script so layering is preserved as well.

    voila! it works for me.

    so you can't use box colliders 2D which is more optimized than polygon collider 2d... but .... this is still much better than using 3D colliders in the first place or scripting the colliders position/rotation on each frame as other workaround suggest... and you can still use a rigidbody.

    this is the best solution I came so far...please let me know if you find any limitations on it or if it works fine with you too.

    regards,
     
  8. ziv03

    ziv03

    Joined:
    Nov 22, 2013
    Posts:
    13
    doesn't exactly work for me. the sprites flip correctly. but the colliders doesn't "flip" with the sprites. they stay in the same position.
     
  9. grindhouse

    grindhouse

    Joined:
    Aug 2, 2013
    Posts:
    7
    can you export a unitypackage of that project and upload it so I can check what's wrong with it?
    it works like a charm here.
     
  10. ziv03

    ziv03

    Joined:
    Nov 22, 2013
    Posts:
    13
    I think it will be easier to show you this on skype. sent you a private message.
     
  11. grindhouse

    grindhouse

    Joined:
    Aug 2, 2013
    Posts:
    7
    I just sent you my skype name, lets give it a try...

    EDIT:

    ok, problem fixed... the gameObject being rotated 180 degrees can't be a rigidBody.. that was the problem. And that's what the empty "robotModel" gameObject was created for...so you rotate that gameobject 180 degrees instead.

    There's another issue that didn't occur to me at first: the sprites and colliders flip fine when performing the rotation on unity editor, but if you script the rotation, the sprite rotates and the collider doesn't. This might be why they say colliders 2D don't support rotations on X or Y axis... and we are indeed indirectly rotating their Y axis... so all we have to do to trick the engine into flipping it anyway, is forcing an update... there are many ways to achieve it, like disabling/enabling the collider2D, or changing the sprite position forth and back on the same frame, once you do this... you can rotate the sprite and the collider without any issues, i use the following code to flip the sprite

    PHP:
        void Flip() {
            
    facingRight = !facingRight;
            
    robotModel.localEulerAngles = new Vector3(0robotModel.localEulerAngles.y+1800);

            
    // force all child colliders to update their position by enabling/disabling them
            
    foreach(Collider2D collider in gameObject.GetComponentsInChildren<Collider2D>()) {
                
    collider.enabled=false;
                
    collider.enabled=true;
            }

        }
    remember that I said it didn't happen to me at first... know why? because all my sprites were constantly being moved by my "idle" animation, so in that scenario, you dont even need to enable/disable the colliders on flip.....

    hope it helps to someone.... Ive been searching solutions all these days, and this is my outcome so far.. it works fine, and im happy with it ;)
     
    Last edited: Dec 27, 2013
  12. robzilla2000

    robzilla2000

    Joined:
    Aug 19, 2013
    Posts:
    4
    i'm noticing this in my project too and I found this thread.

    well it's definitely the closest to a solution I got in some time... but I'm still seeing it. I changed my code to rotate the y 180 degrees instead of the x negative, and the colliders don't rotate. And disabling and re-enabling the colliders doesn't help , they stay at the wrong location.

    the parent object is not a ridgid body but the child objects are. not really sure what's wrong
     
  13. grindhouse

    grindhouse

    Joined:
    Aug 2, 2013
    Posts:
    7
    the object you do rotate 180 degrees, does it have a rigid body attached to it?
    please, describe your character hierarchy to get a better idea of all parents/childs involved, which one/ones have rigidbodys, which one you rotate 180, etc.
     
  14. Vonwarr

    Vonwarr

    Joined:
    Jul 19, 2013
    Posts:
    2
    I've had this same issue as well. But good news everyone! Fresh from the 4.5 patch notes, under the Physics Fixes section:

    - Fixed child Collider2D position when rotated under negative scale.

    I have yet to try it but will hopefully have a chance this week.