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

Is it possible to freeze the camera image for a second?

Discussion in 'General Discussion' started by Tomnnn, Jun 8, 2014.

  1. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    --edit

    I solved my own problem in quite a short time with some googling, now this post is useless. My problem is solved by momentarily disabling v-sync and then setting the target frame rate to 1, then resetting that after the move. Someone please let me know which version of my re-origin script is better performance wise since they both look the same.

    --edit 2

    Some testing shows there is still a blink.

    --v original post v

    I am developing an endless world survival game set in an infinite ocean. I have a large scaled body of water moving with the player, a boat, some crates and fish floating in the water (and horrors in the depths). I check if the player is below the water level to switch to swimming on a custom character control thing.

    Every 60 seconds, the world saves and re-origins everything around Vector3.zero with the player as the center. I calculate the distance for everything relative to the player, move the player to the origin, then move everything around the player. The issue is that when I do this, there's a half second where you can see everything move and it makes the world appear to flicker.

    Is there a way I can avoid this flicker by moving thing a certain way or freeze the camera for half a second so the player doesn't see the moment where everything flickers? I'll post the code so if you think of something you can tell me where to edit the script.

    I increment a counter, find everything tagged with "reOrigin" which is fish, the boat, the player and the floating crates. If they aren't parented to anything, I calculated their position relative to the player and move them. Then I move the player last. player.transform.getChild(0) is the capsule body on my custom fps controller. It works perfectly, I would just like to know if there's a way to avoid the visual bug by moving things differently or freezing the screen momentarily since it will look the same after the move. Thank you!

    Oh and the save isn't implemented yet. I might even make saves manual since autosave can be pretty unpopular if it's done poorly.

    Code (CSharp):
    1. saveTime += Time.deltaTime;
    2.  
    3.         //save the game & shift the world every 60 seconds
    4.         if(saveTime > worldMoveTick)
    5.         {
    6.             saveTime = 0;
    7.             GameObject[] reCenter = GameObject.FindGameObjectsWithTag("reOrigin");
    8.             Vector3 moved_position;
    9.             for(int i = 0;i < reCenter.Length;i++)
    10.             {
    11.                 if(reCenter[i] != player && reCenter[i].transform.parent == null)
    12.                 {
    13.                     moved_position = reCenter[i].transform.position - player.transform.GetChild(0).position;
    14.                     reCenter[i].transform.position = new Vector3(moved_position.x,
    15.                                                                  reCenter[i].transform.position.y,
    16.                                                                  moved_position.z);
    17.                 }
    18.             }
    19.             player.transform.GetChild(0).position = new Vector3(0, player.transform.GetChild(0).position.y, 0);
    20.         }
    I just tried this. It actually solved some of the visual issue, but there's still a blink / flicker. But now you don't see a ghost image of the previous location. Even if I only move 0.1 meters, everything still disappear for a moment. Could I fix this if I throttle the FPS for a second?

    Code (CSharp):
    1. if(saveTime > worldMoveTick)
    2. {
    3. saveTime = 0;
    4.             GameObject[] reCenter = GameObject.FindGameObjectsWithTag("reOrigin");
    5.             Transform[] parents = new Transform[reCenter.Length];
    6.             for(int i = 0;i < reCenter.Length;i++)
    7.             {
    8.                 if(reCenter[i] != player && reCenter[i].transform.parent == null)
    9.                 {
    10.                     parents[i] = reCenter[i].transform.parent;
    11.                     reCenter[i].transform.parent = player.transform.GetChild(0);
    12.                 }
    13.             }
    14.             player.transform.GetChild(0).position = new Vector3(0, player.transform.GetChild(0).position.y, 0);
    15.             for(int i = 0;i < reCenter.Length;i++)
    16.             {
    17.                 if(reCenter[i] != player && reCenter[i].transform.parent == player.transform.GetChild(0))
    18.                 {
    19.                     reCenter[i].transform.parent = parents[i];
    20.                 }
    21.             }
    22. }
     
    Last edited: Jun 8, 2014
  2. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,789
    I am not quite sure of the game mechanic you are describing but perhaps you should look at Time.timeScale and set it to 0.0??
     
  3. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    I will try that as well. Do you know if adjusting the time scale is better than adjusting the frame rate? I only need to do it once every time the world 'moves' at a configurable time limit.

    --edit

    Time.timescale = 0.0 still showed the flicker.

    --edit2

    Agh, never mind. A little more testing shows the targetFPS isn't working for me either.

    Is there any chance there's just a better way to move everything to not show the visual flicker / jitter / blink?
     
    Last edited: Jun 8, 2014
  4. smd863

    smd863

    Joined:
    Jan 26, 2014
    Posts:
    292
    I would profile your function to make it faster. I imagine you can make it fast enough that the player wouldn't notice.

    If you have lots of objects, maybe you'll drop a frame or two, but simply updating the position of objects is not a heavy task. You are probably spending most of your time finding objects to move so keeping a cache of items you need to move to iterate through would probably be much faster.

    You also don't need to run it every 60 seconds. You can already know how far your character is from the origin, so you only need to rebase your origin if your character drifts substantially. I don't remember exactly what the number is before physics starts getting weird, but it should be thousands of world units. In regular circumstances that is a much greater distance than the player will typically traverse in 60 seconds.
     
  5. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    For the time being, I now have world saving and world shifting completely separated. I'll keep an eye on this post in case anyone can help me, but for now the world will not move everything back to 0,0,0 unless the player moves 2000 units away from it.

    Thanks for any help. I'll record a video of the jitter later if anyone would find that useful.
     
  6. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    My test case is only moving 6 objects, so I don't think it's the find function. I do have references to all of the things being moved, but no matter how I try to implement this, everything disappears for a second when it moves. For now I'm settling for "deal with it" as a solution, and making the save every 60 seconds (might switch to manual) and the 're-origin' will trigger at 2000 units.
     
  7. smd863

    smd863

    Joined:
    Jan 26, 2014
    Posts:
    292
    If it takes a second to move 6 objects, then you really need to profile your function to see what's happening. If it's not "Find" then it's something else, and it's not likely any one is going to be able to glance at your code and give you answers.

    It's going to take a bit of methodical digging.
     
  8. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    My fps is 79-80 and it doesn't dip during the function call. I assume my camera is just rendering too fast. I see the frame where the object is in the process of moving. In my first solution I see a ghost image of the object where it was for a brief moment. And since the player is moved last, in the current solution I see everything move before I do causing a moment where everything disappeared.

    I wanted to basically pause the world and camera until the move finishes so high end computers don't see that, but no matter what I do to the camera I still see it. The idea I came up with now is to hide it lol.

    My game will have storms and takes place outside. It's impossible to not see the lightning flashes. I'm just going to have storms occur naturally and also when the player is near the 2000 meter world border, and make a flash when the player moves to hide the split second jitter.

    That won't work in future projects (if they are endless) so I really would like to have this solved.

    So Captain, what do you propose I do? In a test case, I have a camera that can move and 6 objects. When the function is called, the game gets the relative position of everything to the camera, moves it all to a relative position around vector3.zero and moves the camera to x 0, z 0 and the current y is preserved.

    During the move, I see the objects move before the player moves last. I'm assuming this is because the camera renders faster than the function can execute. How can I figure out what's happening?

    In my second test, I parent everything to the character and then move the character to try to simulate a "move everything at the same time" kind of thing, but I still see the objects or player move first and then the other catch up. The parenting solution works better and doesn't show a ghost image of the last position, but everything still disappears for a second during the move.

    Any direction would be great, I'm sure it will be of use to others who try to do something like this. I can't work on this today, but I'll look into it later. Also.. could it be caused by having multiple update functions running? I have 3 major update functions.

    There's 1 on the camera to capture the X and Y movements, there's another script to capture all keyboard inputs and other things, and there's an environment gameobject with a master script that controls everything else and that third class with an update function is where I called the world move. Could what I'm seeing be caused by how unity handles multiple update functions and the camera having it's own update function?
     
  9. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,398
    That's not possible since all scripts functions for that frame (Update etc.) run, then all the geometry is culled and rendered, and the process repeats. There's never a case where a function is running while the camera renders. I would have to assume that you're moving objects one frame, and then moving the camera in some subsequent frame. You should move everything during the same frame, which will make any visible flickering impossible.

    --Eric
     
  10. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    I posted the script I'm using. I am moving everything at once, I have no idea what's going on. Please tell me if you see anything that might be causing to flicker. More evidence for some kind of intermittent run of another function is that when the world moves, sometimes I fall through the object I'm standing on. The boat I'm standing on is moved to the world origin, my character falls downward a tiny amount, the character moves onto the boat but the capsule is partially into it so it falls through.

    I parent everything to the player, move the player, and reset the parent transform for each moved object. The objects all disappear for a split second and then reappear, it looks glitchy.

    Code (CSharp):
    1. GameObject[] reCenter = GameObject.FindGameObjectsWithTag("reOrigin");
    2.             Transform[] parents = new Transform[reCenter.Length];
    3.             for(int i = 0;i < reCenter.Length;i++)
    4.             {
    5.                 if(reCenter[i] != player && reCenter[i].transform.parent == null)
    6.                 {
    7.                     parents[i] = reCenter[i].transform.parent;
    8.                     reCenter[i].transform.parent = player.transform.GetChild(0);
    9.                 }
    10.             }
    11.             player.transform.GetChild(0).position = new Vector3(0, player.transform.GetChild(0).position.y, 0);
    12.             for(int i = 0;i < reCenter.Length;i++)
    13.             {
    14.                 if(reCenter[i] != player && reCenter[i].transform.parent == player.transform.GetChild(0))
    15.                 {
    16.                     reCenter[i].transform.parent = parents[i];
    17.                 }
    18.             }
     
  11. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,398
    How about making an empty GO that everything is a child of, and moving that when needed?

    --Eric
     
  12. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    How would I do that? I parent everything to the moving body of the player so that the player can be centered on the world zero. I made a short video to demonstrate what's happening. I've also made a temporary rewrite of my scripts so there is only 1 update function. It calls the renamed functions in my other classes.

    To demonstrate the bug, I have the re-origin trigger at 10 units instead of the planned 2000+ (looking for a good known-stable range). The idea is based on a nightmare of mine of being in an endless ocean, so I'd like it to be endless. I just dislike the momentary blink everything has when it moves. If you watch the video you can even see things move sometimes.



    --edit

    I may have solved my issue, not sure. I'm going to move the camera and body together. I just realized my camera isn't using the re-origin tag, I didn't think it would matter since I have something in one of my camera scripts that keeps the camera on top of the capsule body - so that script is executing after the function that moves the world.

    It's confirmed, I'm an idiot :D
     
    Last edited: Jun 9, 2014
  13. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,789
    We all have been that idiot at one point or another. Solving perplexing issues is the thing that turns you from a wannabe script kiddie noob into a pro and gives you a good grasp of the engines characteristics. Glad you resolved your issues ot at least are on the right track.