Search Unity

  1. Get all the Unite Berlin 2018 news on the blog.
    Dismiss Notice
  2. Unity 2018.2 has arrived! Read about it here.
    Dismiss Notice
  3. We're looking for your feedback on the platforms you use and how you use them. Let us know!
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Learn more.
    Dismiss Notice
  5. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  6. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  7. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Colliders at wrong position after building the game?

Discussion in '2D' started by gsmpcgame, Aug 10, 2018 at 10:17 AM.

  1. gsmpcgame

    gsmpcgame

    Joined:
    Friday
    Posts:
    6
    Hi everyone! Currently I'm working on my first Unity game and I've ran into some weird stuff, and I wasn't able to find a solution on my own.
    So.. the game is a 2D endless runner, there's a character who can jump over or slide under the obstacles. In the editor, all collisions are working fine, but when I'm trying to build the game, the colliders are in wrong position.
    For example: there's an item, with an X position: 25. I can jump over it, everything's fine.
    But when I'm testing the built version (no matter if it's on Windows or on Android) I'm running into an invisible wall at position ~20 (I don't know exactly, but before the item). I can't jump over it, I can't slide under it, nothing.
    After disabling that item's collider, I can run past it in the built version too. What can be the problem?
    Thanks in advance for your answers!
     
  2. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    198
    That´s indeed weird.
    Could we see some code? Perhaps the part that handles the jump
     
  3. gsmpcgame

    gsmpcgame

    Joined:
    Friday
    Posts:
    6
    That part is really basic, in the character's Update function I'm using:

    Code (CSharp):
    1. if (isDead == false) {
    2.     if (Input.GetMouseButtonDown (0) && AnimatorIsPlaying ("CharRun")) {
    3.         anim.Play ("CharJump");
    4.     }
    5. }
    AnimatorIsPlaying is a function that returns true, if "anim.GetCurrentAnimatorStateInfo (0).IsName (stateName)" returns true (and false if it returns false).
    I'm not using AddForce or anything else to modify the character's Y position, because the animation comes from a png image sequence, where the character jumps and leaves the floor. So when I'm playing the animation, it looks fine.
    To check collisions, I'm using a script which creates a PolygonCollider2D in every frame, so it follows the character's movement.
    And as I've said, when I'm testing the game in the editor, the colliders are working fine. If I'm not jumping, then I'm running into the enemy, and I'm dead. But when I'm jumping over it, it's fine. But after building and running the game I'm running into walls which I can't get past, no matter if I'm running, jumping or sliding.
    I'm not sure if these informations will help you or not.
     
  4. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    198
    There must be something wrong somewhere in your code. Let´s try to find it together. :)

    How do you apply x speed to your character?

    I believe the problem might be that If you are generating a new PolygonCollider2D in every frame the one which gets generated when you are about to collide with the wall is different (in each device or mode) because it is frame dependent.

    For instance if your game is running at 60fps at a certain time you will get a collider that´s different than if it were running at 30fps.The collider that is colliding at 60 fps would be generated 30 frames later if the game were running at 30fps.
    Do you see where I am trying to get?

    The solution would be to move the PolygonCollider2D generation code from Update() to FixedUpdate() which will make it frame independent and constant (every 0.02s by default), furthermore everything related to physics should be inside FixedUpdate(), and being PolygonCollider2D a physics thing thats his place :D

    Let me now if this has helped you
     
    Last edited: Aug 11, 2018 at 9:54 PM
  5. gsmpcgame

    gsmpcgame

    Joined:
    Friday
    Posts:
    6
    Technically, my character is standing (so I'm not moving it's X position). I'm moving the background and the obstacles with this script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class ScrollingObject : MonoBehaviour {
    6.  
    7.     private Rigidbody2D rb2d;
    8.  
    9.     void Start ()
    10.     {
    11.         rb2d = GetComponent<Rigidbody2D> ();
    12.     }
    13.    
    14.     void Update ()
    15.     {
    16.         if (GameControl.instance.gameOver == true)
    17.         {
    18.             rb2d.velocity = Vector2.zero;
    19.         }
    20.         else if (!Hero.AnimatorIsPlaying ("CharStandUp")) {
    21.             rb2d.velocity = new Vector2 (GameControl.instance.scrollSpeed, 0);
    22.         }
    23.     }
    24. }
    And I'm generating the PolygonCollider2D with this script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class CreateCollider : MonoBehaviour {
    6.  
    7.     public bool iStrigger ;
    8.  
    9.     private SpriteRenderer spriteRenderer;
    10.     private List<Sprite> spritesList;
    11.     private Dictionary<int, PolygonCollider2D> spriteColliders;
    12.     private bool _processing ;
    13.  
    14.     private int _frame ;
    15.     public int Frame {
    16.         get { return _frame; }
    17.         set {
    18.             if (value != _frame) {
    19.                 if (value > -1) {
    20.                     spriteColliders [_frame].enabled = false;
    21.                     _frame = value;
    22.                     spriteColliders [_frame].enabled = true;
    23.                 } else {
    24.                     _processing = true;
    25.                     StartCoroutine (AddSpriteCollider (spriteRenderer.sprite));
    26.                 }
    27.             }
    28.         }
    29.     }
    30.  
    31.     private IEnumerator AddSpriteCollider (Sprite sprite)
    32.     {
    33.         spritesList.Add (sprite);
    34.         int index = spritesList.IndexOf (sprite);
    35.         PolygonCollider2D spriteCollider = gameObject.AddComponent<PolygonCollider2D> ();
    36.         spriteCollider.isTrigger = iStrigger;
    37.         spriteColliders.Add (index, spriteCollider);
    38.         yield return new WaitForEndOfFrame ();
    39.         Frame = index;
    40.         _processing = false;
    41.     }
    42.  
    43.     private void OnEnable ()
    44.     {
    45.         spriteColliders [Frame].enabled = true;
    46.     }
    47.  
    48.     private void OnDisable ()
    49.     {
    50.         spriteColliders [Frame].enabled = false;
    51.     }
    52.  
    53.     private void Awake ()
    54.     {
    55.         spriteRenderer = this.GetComponent<SpriteRenderer> ();
    56.  
    57.         spritesList = new List<Sprite> ();
    58.  
    59.         spriteColliders = new Dictionary<int, PolygonCollider2D> ();
    60.  
    61.         Frame = spritesList.IndexOf (spriteRenderer.sprite);
    62.     }
    63.  
    64.     private void LateUpdate ()
    65.     {
    66.         if (!_processing)
    67.             Frame = spritesList.IndexOf (spriteRenderer.sprite);
    68.     }
    69.  
    70. }
    Changing the LateUpdate to FixedUpdate doesn't seem to help.
     
  6. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    198
    It does not matter whether you are moving the character or the obstacles. I am still pretty sure it is what I told you.
    This piece of code should also be on FixedUpdate.

    Code (CSharp):
    1.    void Update ()
    2.     {
    3.         if (GameControl.instance.gameOver == true)
    4.         {
    5.             rb2d.velocity = Vector2.zero;
    6.         }
    7.         else if (!Hero.AnimatorIsPlaying ("CharStandUp")) {
    8.             rb2d.velocity = new Vector2 (GameControl.instance.scrollSpeed, 0);
    9.         }
    10.     }
    There you set the objects x speed to the given scrolling speed, but if there have been n physics steps between two consequent frame the speed will have slowed down because physics work that way ( friction, gravity...).

    As I stated above everything related to physics should be placed in FixedUpdate.

    Anyways @jeffreyschoch is the Jon Skeet of Unity´s 2D forum, so if he can confirm this would be really thankful :)
     
  7. gsmpcgame

    gsmpcgame

    Joined:
    Friday
    Posts:
    6
    I've tried it, but still no success.
     
  8. gsmpcgame

    gsmpcgame

    Joined:
    Friday
    Posts:
    6
    Now I've tried to limit FPS to 30, but it didn't help either.
     
  9. jeffreyschoch

    jeffreyschoch

    Joined:
    Jan 21, 2015
    Posts:
    2,277
    That is the highest praise I've ever received lol.

    Yeah in general it's best to put physics updates in FixedUpdate to stay synced with the physics step, but it only really becomes problematic when your function compounds, things like AddForce, because that can build up over multiple iterations. In the case of setting velocity, it would just set it many times to the same value, which doesn't really hurt anything but isn't necessary. Consistency and organization is important.

    @gsmpcgame your implementation is a bit counter-intuitive to how Unity is used in most cases, so it's difficult to tell where the problem lies just from reading your descriptions.

    Traditionally the world and obstacles stay still while your player moves through it, which means you only have to worry about one object having velocity and constant simulation. You may be making things harder for yourself by going this route.

    What is the reason to generate new colliders at runtime? Do they really need to be polygon colliders, and not a single capsule or something?

    Could you create them at edit time and have a list of sprites and a list of colliders, with a single index to access both lists?

    Suggestions aside, you should start at the root of your problem to make sure you're following the right trail.

    You said that you're hitting an invisible wall? Could you add some kind of visual representation to your colliders so that you can see them in the editor and build? Maybe upload a gif or video of the problem happening?
     
    Last edited: Aug 13, 2018 at 7:52 PM
    jc-drile77 likes this.
  10. gsmpcgame

    gsmpcgame

    Joined:
    Friday
    Posts:
    6
    As I've said, I'm brand new to the world of Unity. I followed a tutorial from Unity's Youtube channel and this was the way he solved the movement.
    But I think it's practical for me, because there will be 3 layers of background: a distant one, a not too distant one and a close one. I'm adding the modified ScrollingObject script to them (with a different scrollSpeed), so the distant things will move slower than the closer things. If I'd move only my character and not the world, how could I achieve this?

    I have about 100 frames of animation, so creating the colliders for them one by one manually would be inconvenient for me.

    I've made two videos to show you what I'm talking about. One from the editor, and one after building the game.
    I guess it won't help you identifying the problem, but you'll see it in action.
    If it's possible, I'm willing to send you the project folder, maybe it would be easier to find the mistake I've made.


     
  11. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    198
    The other way is using a perspective camera.
    Here you can see how it works (and review your method too)

    It´s quite common to just use a CapsuleCollider2D because at the bottom its smooth as a circle but can be as tall as needed. Generating so many colliders and destroying them in such a small time might affect performance in the bad way.

    Having said that let´s see if jeffrey can spot something in your videos because I cannot. :(