UI render doesn't sync with Camera movement

Hi there,

I’m trying to make make a FPS where there is a tag on the top of a enemy indicating where it is (similar to the objective/follow tag in battlefield/COD). It’s is a 3D position (top of the enemy) that’s been projected into 2D space using camera.WorldToScreenPoint. I have a 2D UI image whose position (anchored position on rect transform) is set to that converted 2D coordinates, the 2D position is set in the Update() method per frame.

It sorta worked. However when I move the camera rapidly there is going to be a moment the that the tag position is not sync with the actual enemy position, like a lag, leaving distance between the tag and the actual position. The tag itself however will follow up shortly but when I move the tag just appears to be jaggy and unstable. I have tried many steps to fix it but it didn’t work. I have tried to put it in fixed update and it didn’t work either.

Here is the screenshot for the problem:

The tag is at correct position when camera holds still. Not that all coordinates are the same (debug text, actual UI position, UI rect transform)
alt text

The tag is NOT at the correct position when the camera moves rapidly, creating a lag, the tag will eventually adjust to the right position but it is still annoying. One bizarre thing to note is that the rect transform position on the right is different from both the debug text and the actual rendered UI position! I have no idea why that happens.

alt text

Here is the code:

This is the UI part where the UI tag request converted anchored position per frame, the rectTransform is that of the tag (marker)

void Update () {
    rectTransform.anchoredPosition = marker.requestingAnchoredPos();
    DebugText.Log("UITarget is " + (int) rectTransform.anchoredPosition.x + 
	             "	 pixels from the center and " + 
	             (int) rectTransform.anchoredPosition.y + 
	             "	 pixels from the center" );

This is the actual tag hovering on top of the enemy, where the screen position is requested from camera and converted to anchored position upon calling the function, these two scripts show follow immediately.

public Vector2 requestingAnchoredPos () {
	// screen coordinates
	screenPos = camera.WorldToScreenPoint(target.position);
	// convert to anchored position
	anchoredPos.x = screenPos.x - width/2;
	anchoredPos.y = screenPos.y - height/2;
	return anchoredPos;

The result is as above. I suspect this to be a sync issue of unity since I have no control over when what things gets rendered. Please help. Thanks!

So, I don’t think it’s a problem with the order things are rendered, but rather a problem with the order they are updated. I’d be willing to bet that each frame, your mouselook is being called after your tag positioning, which means the tag positioning would have a frame of lag at all times.

I can suggest two fixes for that, if that is the correct diagnosis:

  1. Change the script execution order from project settings so that your tag mover runs after mouselook
  2. Move your update tag position code to LateUpdate(). That’s called after all other updates. I use it a lot for transform syncing.

The best place to synchronize the UI object with the 3D position of the target is in LateUpdate(); make sure you are not also moving the camera or objects in LateUpdate().

How is your canvas set up for your UI element and how is it anchored? Do you have any layout components in the hierarchy?