Search Unity

  1. Check out the Unite LA keynote for updates on the Visual Effect Editor, the FPS Sample, ECS, Unity for Film and more! Watch it now!
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Canvas Scaler and moving 2D items with touch

Discussion in 'Unity UI & TextMesh Pro' started by Rosenumber14, Feb 6, 2015.

  1. Rosenumber14

    Rosenumber14

    Joined:
    Feb 5, 2015
    Posts:
    5
    Hello,
    I am developing a game and built my own infinite scroller that would lock onto a touch and follow the user's finger. It worked great until we added a canvas scaler to help scale some of our difficult UI elements for all devices. Here are the settings for the Canvas Scaler:

    UI Scale Mode: Scale With Screen Size
    Reference Resolution: x: 750 y:1334
    Screen Match Mode: Match width Or height
    Match: 0.5
    Reference pixels per unit: 100

    What i'm struggling with is trying to get an item that is within the canvas to follow your finger with every screen size. I have a panel inside the canvas that detects your touch using 'OnDrag' and i am setting the item's position inside the panel to eventdata.position. On the IPhone tall it seems to move slower then my finger, yet it works great on the IPhone5. Here is a little snippet of my code:

    public void OnDrag(PointerEventData eventData)
    {
    _item.transform.position = eventData.position;
    }

    This bug can be seen in the editor and on the phone. Please help!
     
  2. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,607
    I've seen this a bit. There does appear to be a certain amount of lag between user / pointer input and Canvas Drawing.
    Might be worth logging with an example project
     
  3. Rosenumber14

    Rosenumber14

    Joined:
    Feb 5, 2015
    Posts:
    5
    Thanks for the response. Without the Canvas Scaler though, it works great, there does not seem to be any lagging and the app seems to be fully responsive. In my editor I can change the preset to the different phone sizes and depending on the size it scrolls faster or slower then my finger or perfectly if the phone is the same size as the Canvas Scaler's Reference Resolution: I think it has to do with the scaling of the UI that the canvas scaler does on 'Scale With Screen Size' mode. Any other ideas?
     
  4. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,607
    Interesting, I've not seen any cases where the Canvas Scaler would cause performance issues.
    Any idea @phil-Unity @Adam Buckner ?
     
  5. Rosenumber14

    Rosenumber14

    Joined:
    Feb 5, 2015
    Posts:
    5
    Here is an example project if this helps. If its not already, change to IOS in your build settings and set the screen size to iPhone Tall. I am currently in Unity 4.6.1 to see it just click on the button to begin dragging and drag it up and down you will see your mouse pass it up because its moving slower. Then try iphone 5 and you can see it move with your mouse. Maybe i need to compensate for something?
     

    Attached Files:

    Last edited: Feb 6, 2015
  6. rakkarage

    rakkarage

    Joined:
    Feb 3, 2014
    Posts:
    660
    Code (CSharp):
    1. _scaler = GetComponentInParent<CanvasScaler>();
    2. ...
    3. if (_scaler != null)
    4.     Drag(e.delta.x * _scaler.referenceResolution.x / Screen.width);
    5. else
    6.     Drag(e.delta.x);
     
    Rosenumber14 likes this.
  7. Rosenumber14

    Rosenumber14

    Joined:
    Feb 5, 2015
    Posts:
    5
    Hi, Thank you soo much rakkarage!! It works great!
     
    rakkarage likes this.
  8. BoaNeo

    BoaNeo

    Joined:
    Feb 21, 2013
    Posts:
    34
    The above is not entirely correct - it assumes that the reference resolution is matched to the actual screen by linear scaling in both directions which, depending on the MatchMode and Match width/height slider, may not be true.

    If you wish to avoid the headache of figuring that out, Unity has already done if for you in the Canvas transforms' "localScale" property (What I don't understand is why Unity doesn't do this before sending the event in the first place but it's just one of those things, I guess...)

    float dx = event.delta.x/_scaler.transform.localScale.x;
    float dy = event.delta.y/_scaler.transform.localScale.y;
     
    rakkarage and Harinezumi like this.
  9. Bezzy

    Bezzy

    Joined:
    Apr 1, 2009
    Posts:
    75
    I found that in some cases, using localScale wasn't working, and frustratingly the problem only turned up on the target platform.

    Code (CSharp):
    1.  
    2. CanvasScaler _canvasScaler;
    3. ...
    4. void Awake()
    5. {
    6. _canvasScaler = GetComponent<CanvasScaler>() ?? GetComponentInParent<CanvasScaler>();//anyone know if ?? is redundant here?
    7. }
    8. ...
    9. public Vector3 UnscaleEventDelta(Vector3 vec)
    10.     {
    11.         Vector2 referenceResolution = _canvasScaler.referenceResolution;
    12.         Vector2 currentResolution = new Vector2(Screen.width, Screen.height);
    13.  
    14.         float widthRatio = currentResolution.x / referenceResolution.x;
    15.         float heightRatio = currentResolution.y / referenceResolution.y;
    16.         float ratio = Mathf.Lerp(widthRatio, heightRatio, _CanvasScaler.matchWidthOrHeight);
    17.  
    18.         return vec /ratio;
    19.     }
    This code takes into account the "Match" slider as well.
     
  10. Vatio

    Vatio

    Joined:
    Sep 26, 2012
    Posts:
    9