- Home /
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)
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.
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 +
"\t pixels from the center and " +
(int) rectTransform.anchoredPosition.y +
"\t 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!
Are you sure you use the correct camera for the world to screen conversion? It should be the FPS cam. Also make sure your anchors are actually on one point and not spread apart.
Next thing is in which Canvas do you display this marker? You seem to use some tilted GUI stuff on the right side. If you tilted the canvas it doesn't align with the actual screen.
Answer by FortisVenaliter · May 16, 2015 at 03:01 PM
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:
Change the script execution order from project settings so that your tag mover runs after mouselook
Move your update tag position code to LateUpdate(). That's called after all other updates. I use it a lot for transform syncing.
@FortisVenaliter Thanks for the suggestion however it did not work. LateUpdate() doesn't seem to do anything at all. Change scripts execution order help to reduce the lag but there is still the lag that can be noticed :( I adjusted in the order of such: FPSController->$$anonymous$$ouseLook->Tag->TagUI.
However LateUpdate() supposedly should update the position after all other things, but that doesn't even reduce the problem. I wonder what might be the cause..
Answer by pfreese · May 21, 2015 at 01:50 PM
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?