Tooltip updating it's position lags when Cinemachine moves (video)

I’m using a simple Cinemachine Virtual Camera which follows the player with a bit of delay to make it smooth. When holding the mouse over an item, a tooltip shows, and I set it’s position like the code below.

When I move, the tooltip lags after, and is not fixed to the item. I have tried to set this in Update, FixedUpdate and LateUpdate.

The wantedPosition is where it should be if it’s in the middle of the screen, then it sets it so it doesn’t go outside the screen. camera1 is Camera.main, which is the main camera where Cinemachine Brain is.

The tooltip is a UI element in a Screen Space - Overlay Canvas. Should I maybe have the tooltip as a real gameobject instead?

Any clues on what I’m doing wrong?

GrandioseRaggedAracari

// Run in Update, FixedUpdate or LateUpdate (same results)
void SetTooltipPositionItem() {
    var wantedPosition = BlueGoo.Utils.Utils.WorldToUISpace(camera1, canvas, currentPosition) + (Vector3) tooltipOffset;
    gameObject.transform.position = BlueGoo.Utils.Utils.CheckIfRectIsInsideParent(wantedPosition, rect, parentRect);
}

public static Vector3 WorldToUISpace(Camera camera, Canvas parentCanvas, Vector3 worldPos) {
   //Convert the world for screen point so that it can be used with ScreenPointToLocalPointInRectangle function
   Vector3 screenPos = camera.WorldToScreenPoint(worldPos);
   Vector2 movePos;

   //Convert the screenpoint to ui rectangle local point
   RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvas.transform as RectTransform, screenPos, parentCanvas.worldCamera, out movePos);

   //Convert the local point to world point
   return parentCanvas.transform.TransformPoint(movePos);
}

public static Vector3 CheckIfRectIsInsideParent(Vector3 wantedPosition, RectTransform rect, RectTransform parent, float padding = 20) {
   // Set position first, so it can check if it's inside
   rect.position = wantedPosition;

   Vector3[] corners = new Vector3[4];
   Vector3[] parentCorners = new Vector3[4];
   Vector2 diff = Vector2.zero;

   // Get corners
   rect.GetWorldCorners(corners);
   parent.GetWorldCorners(parentCorners);

   // Corner 0 = bottom left, 2 = top right
   // If tooltip is outside, set diff
   if (corners[0].x < parentCorners[0].x + padding) {
      diff.x = parentCorners[0].x - corners[0].x + padding; // Utanför till vänster
   } else if (corners[2].x > parentCorners[2].x - padding) {
      diff.x = parentCorners[2].x - corners[2].x - padding; // Utanför till höger
   }

   if (corners[1].y > parentCorners[2].y - padding) {
      diff.y = parentCorners[2].y - corners[1].y - padding; // Utanför uppåt
   } else if (corners[0].y < parentCorners[0].y + padding) {
      diff.y = parentCorners[0].y - corners[0].y + padding; // Utanför neråt
   }

   return wantedPosition + (Vector3) diff;
}

This is likely a script execution order problem. Camera is positioned in CinemachineBrain.LateUpdate(), and the brain’s script execution order is set to be later than the default, so it will run after all your scripts. That means you are using a stale camera position to calculate the screen position.

Here are two possible solutions:

  1. set your script to run after CinemachineBrain in the script execution order, or
  2. hook into the brain’s Camera Updated event. That’s issued whenever the brain moves the camera. That way you don’t have to worry about execution order
1 Like

Thanks a lot for the quick reply, I’ll try that!

Gregoryl, I have the same issue, how would I go about hooking into the Camera Updated event? I can’t seem to find any info about it anywhere.

Use CinemachineCore.CameraUpdatedEvent.AddListener(MyHandler);

5 Likes

Thanks for pointing this out ‘CinemachineCore.CameraUpdatedEvent.AddListener(MyHandler);’

I was looking in the Brain class as it was described as belonging to it!

this is an old post, but it saved my life…after an unity update my execution order were messed up and i could not find why my world space UI was flickering like crazy, thanks a lot!!

1 Like

Thanks a lot

Thanks a lot this solved my problem. None of other answers which told to use interpolation nor make camera follow another GameObject instead of directly following the character worked previously. I Even was changing the UI Position in LateUpdate and it was not working until I used this approach.

1 Like