Search Unity

How to make a Raycast2D proportional to a CanvasScaler dynamic resizing?

Discussion in 'Scripting' started by Drezus, Feb 17, 2016.

  1. Drezus

    Drezus

    Joined:
    Oct 14, 2013
    Posts:
    13
    I've been doing a puzzle game with a custom collision script for a while. In this project, I do everything inside of canvases in order to achieve to best fit the game pieces identically in all possible mobile resolutions.

    To get the Raycast collisions working, first I retrieve half of the block height and divide it by the default PixelsPerUnit (which is 100):

    Code (CSharp):
    1. blockHeight = (GetComponent<BoxCollider2D>().size.y / 2)/100;
    Then at every Update I just raycast this height down and up to check whenever a block is hitting another from above or below. If it hits, I reposition the block so it won't sink in other blocks. Here's the "below" part:

    Code (CSharp):
    1. RaycastHit2D downHit = Physics2D.Raycast(transform.position, Vector2.down, blockHeight);
    2. if (downHit.collider != null)
    3. {
    4. GetComponent<BlockGravity>().enabled = false;
    5. transform.Translate(Vector2.down * (downHit.distance - blockHeight));
    6. }
    There's a problem whenever I raycast block collisions after changing screen resolutions, however. It seems the regular PixelsPerUnit from Canvas internal systems increase or decrease depending on how the Scaler is dealing with readjusting the screen. In other words, while Image-component blocks still appear and fit perfectly between all resolutions, their raycasted collisions go beyond their original bounds.

    So, under normal circunstances, such as with my Nexus 4 screen resolution, blocks are very tightly aligned:




    But when selecting resolutions such as FWVGA Portrait (480x854), the raycasts bleed out the original sprite bounds and cause issues with fitting blocks inside the screen aswell as making them aligned:



    So, what am I supposed to do in this situation? I've tried a lot of different calculations, in particular involving the Canvas spriteDPI value, which is the one that (seemingly) changes between resolutions, but I can't get to a point where raycasts resize correctly with Image graphics and BoxCollider scales. I need help!

    EDIT: Actually, I just found out my BlockHeight is actually being divided by 127 instead of the usual 100, and somehow that's what made pieces stick pretty close to each other (even though it's just a random number that I have no real source of where it came from). So even when using the default 100, it'll still give me some room between Images, and much more under FWVGA, for instance.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    I would recommend rethinking this so that blocks have a notion of their "home cell" in integer coordinates, and then there is some kind of manager that tracks the grid of objects and makes sure you can fall into place or move to that location, etc. Doing that sort of tight game-depending logic with a raycast2d is a recipe for future disasters, and I would recommend against it.
     
  3. Drezus

    Drezus

    Joined:
    Oct 14, 2013
    Posts:
    13
    Thanks. I've been talking with fellow developers too and they all recomended me this approach. I'm gonna try it this way, and I have some confidence it'll work better. Thanks!
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    The best part of it is that you can easily debug problems because everything that matters is in the code, and Unity is just being used for presentation.

    Have fun... I think you'll like this approach better.