Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Detect / callback when RectTransform position changes?

Discussion in 'UGUI & TextMesh Pro' started by a436t4ataf, Feb 21, 2020.

  1. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,873
    We have a callback for when the RectTransform *size* changes:

    UIBehaviour.OnRectTransformDimensionsChange()

    ..and when the parent-reference changes:

    UIBehaviour.OnTransformParentChanged() // although this one is officially undocumented :(

    ...but I cannot seem to find anything for detecting when the *position* changes:


    UIBehaviour.On...Oh,ThisMethodDoesn'tExist...WhyNot?()
     
  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,833
    In your particular case, what is causing the changes that you want to detect?
     
  3. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,873
    Custom layout using ILayoutController etc -- I need to know what and when recttransforms are moved around so that I can (selectively, and intelligently) trigger re-layouts (but only of what needs to be changed).

    The workarounds I have so far are:

    1. try to use the DriverRectTransformTracker API - but that is incomplete, and only works for a narrow set of cases (it's hardcoded to fail in any situation where more than one item can influence a RectTransform, for instance)

    2. Hack (that works): most of my cases will only happen when the user has selected a RectTransform. So ... I can secretly monitor the .transform.position on every frame in a custom Inspector OnSceneGUI, and generate a fake OnRectTransformPositionChanged event
     
  4. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,873
    Found this while needing the feature again on new project.

    FYI to future visitors: I did eventually find a workaround. Unity will never fix this (Unity decided to half-write UnityUI then give up and started UIToolkit), but I found I could hack it into place. After a lot of trial and error I 'solved' it for RectTransforms by hooking the SetLayoutHorizontal() callback and then ... detecting every single "OnRectTransform...(something)...Change()", and inferring that if NONE of those others had been called, then it was implicitly "OnRectTransformPositionChange()".

    This has worked well for multiple years across 4 major versions of Unity. It will .. probably? .. continue to work until UnityUI is finally deleted by Unity.
     
    Unifikation likes this.
  5. PeppeDK

    PeppeDK

    Joined:
    Aug 16, 2016
    Posts:
    8
    Can you show us some code please?
     
  6. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,873
    In my current codebase this is about 1,000 lines of code, and requires a minimum of 4 separate classes (child, self, parent, and async listener) - in reality it's more likely to be 8-10 classes if you're using this in a project. I can't paste that into a forum comment, it's a whole library of code.

    If the description isn't clear enough for you, you probably shouldn't be using this approach - it requires a reasonable amount of confidence with delving into the heart of Unity's layout system. I hope someone else finds a solution that needs less code - or, even better, I wish Unity would fix this and add the missing methods!

    I'm happy to give advice/suggestions/feedback if you try it, but unless you dive into the docs and understand how UnityUI layout works I don't think it's going to work for you.

    e.g. SetLayoutHorizontal is only invoked on certain classes, in certain situations - you need to read the Unity docs and understand when/why/how that method gets called, and setup your own classes so that it's being invoked. That whole setup depends a lot on what you're trying to do. It also breaks for player builds, while working for Editor builds, because of bugs in Unity, so unless you've already solved that you'll get into a lot of complexity there too.

    e.g. RectTransform callbacks are invoked *some* on the object *others* on the parent *others* on the children. You'll need to implement all of those cases - parent, child, self - and have them connect together to track what's been invoked.
     
    Unifikation likes this.
  7. Rugbug_Redfern

    Rugbug_Redfern

    Joined:
    Jun 2, 2017
    Posts:
    20
    How do you hook the SetLayoutHorizontal() callback in code? I've seen hooking in stuff like Harmony, but never natively in Unity.
     
  8. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,873
    Look for it in the unity docs - you have to extend a class that has it and/or implement a relevant interface (it's documented reasonably well how to get the callback - although what you do with it is less well documented :) )