Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Feedback Fix for Scene View Camera Lag (Script provided)

Discussion in 'Editor & General Support' started by John_Leorid, Jun 22, 2020.

  1. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    657
    The problem should be pretty common, I guess. When moving the scene view camera with the right mouse button and WASD keys in a quite detailed scene with lots of objects, the camera keeps moving for a long time after letting go of every button (including the right mouse button).
    So you end up somewhere in the void with the camera and have to focus something, to get back, only to see the same issue happening again after a few seconds.

    It is impossible to work this way, so I'd rewrite the scene view camera with a frame checker or something - if the framerate gets to low, just stop any movement - this should fix the issue.
    We can't make the scene simpler, because it's an HDRP 3D game with a lot of high detailed models, it works in the build, so this is only an issue in the edior.

    I just thought before trying to rewrite the whole editor camera, I should ask if there is already any solution.
    Turning lights/animated materials/isometric view/post processing/skybox on or off didn't help, and pretty much everyone I know has these issues with detailed scenes in unity - lag would be ok, if the camera would just freeze, instead of going off into the void every single time the editor framerate drops.

    So back to the original question: Is there any fix to the scene view camera?

    EDIT: Here is the script to fix this behaviour
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System.Diagnostics;
    4. using System;
    5.  
    6. namespace JL
    7. {
    8.     public class SceneViewCameraFix : Editor
    9.     {
    10.         [InitializeOnLoadMethod]
    11.         static void FixIt()
    12.         {
    13.             SceneView.beforeSceneGui -= OnScene;
    14.             SceneView.beforeSceneGui += OnScene;
    15.         }
    16.  
    17.         static Vector3 lastCamPosition;
    18.  
    19.         static bool wKey;
    20.         static bool aKey;
    21.         static bool sKey;
    22.         static bool dKey;
    23.         static bool qKey;
    24.         static bool eKey;
    25.  
    26.         private static void OnScene(SceneView scene)
    27.         {
    28.             Event e = Event.current;
    29.  
    30.             if (e.isKey && e.type == EventType.KeyDown)
    31.             {
    32.                 if (e.keyCode == KeyCode.W) wKey = true;
    33.                 if (e.keyCode == KeyCode.A) aKey = true;
    34.                 if (e.keyCode == KeyCode.S) sKey = true;
    35.                 if (e.keyCode == KeyCode.D) dKey = true;
    36.                 if (e.keyCode == KeyCode.Q) qKey = true;
    37.                 if (e.keyCode == KeyCode.E) eKey = true;
    38.             }
    39.             bool hadKey = wKey || aKey || sKey || dKey || qKey || eKey;
    40.  
    41.             if (e.isKey && e.type == EventType.KeyUp)
    42.             {
    43.                 if (e.keyCode == KeyCode.W) wKey = false;
    44.                 if (e.keyCode == KeyCode.A) aKey = false;
    45.                 if (e.keyCode == KeyCode.S) sKey = false;
    46.                 if (e.keyCode == KeyCode.D) dKey = false;
    47.                 if (e.keyCode == KeyCode.Q) qKey = false;
    48.                 if (e.keyCode == KeyCode.E) eKey = false;
    49.             }
    50.  
    51.             bool reset = hadKey && !(wKey || aKey || sKey || dKey || qKey || eKey);
    52.  
    53.             if (reset)
    54.             {
    55.                 scene.pivot = lastCamPosition;
    56.             }
    57.  
    58.             lastCamPosition = scene.pivot;
    59.         }
    60.     }
    61. }
    62.  
     
    Last edited: Jun 22, 2020
  2. AFAIK not really. You can somewhat help the situation if you turn off some easing and stuff in the camera setting though, also helps if you take up the habit to move the camera in small portions and if you start with the focus function on an object close to your target position. I know it sucks. Another possibility is to organize your scene into subscenes and turn on and off the not used parts. That speeds up the things. They edited the Mega City demo with those, it is powerful.
    answer.png
    But maybe others will have better ideas.
     
  3. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    657
    Nevermind, I fixed it exactly as I said ... turning the options off helps too, because the movement just feels better, but this script I just wrote handles the framedrops and resets the camera position. I just played around with it and the only visible effect seems to be, that the camera does not fly off into the void.

    But if the "deltaTime > 7" is set to a too small value, e.g. "deltaTime > 2", rotations feel extremly weird for some reason? Idk. It works well with "7" - not perfect, but it prevents the worst.

    I'd still like to know if there are better solutions than my one and also recommend Unity to impliment this behaviour by default. No one likes to watch the scene view camera flying off on its own for seconds.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System.Diagnostics;
    4. using System;
    5.  
    6. public class SceneViewCameraFix : Editor
    7. {
    8.     static Stopwatch sw;
    9.     static TimeSpan timeSpan;
    10.  
    11.     [InitializeOnLoadMethod]
    12.     static void FixIt()
    13.     {
    14.         SceneView.beforeSceneGui -= OnScene;
    15.         SceneView.beforeSceneGui += OnScene;
    16.         sw = new Stopwatch();
    17.         sw.Start();
    18.         timeSpan = new TimeSpan(0, 0, 0);
    19.     }
    20.  
    21.     static Vector3 lastCamPosition;
    22.  
    23.     private static void OnScene(SceneView scene)
    24.     {
    25.         var tempTimespan = sw.Elapsed;
    26.  
    27.         float deltaTime = (tempTimespan - timeSpan).Milliseconds;
    28.         timeSpan = tempTimespan;
    29.  
    30.         if(deltaTime > 7 && lastCamPosition != Vector3.zero)
    31.         {
    32.             scene.pivot = lastCamPosition;
    33.         }
    34.  
    35.         lastCamPosition = scene.pivot;
    36.     }
    37. }
    38.  
    Edit: I measured the captured "deltaTime" and got values of 2-3 ms when the cam was controllable and values of 23-38 ms when it went off on its own. So it is easy to detect those extreme spikes and act against it.
     
  4. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    657
    Ok, there was a way more obvious way. When acceleration is turned on, it causes a very small stutter, but when acceleration and easing are turned off, the following script results in very precise movement and does not depend on the framerate at all.
    This is how the Editor should behave. Basically it implements exactly the wanted behaviour "don't move the camera if I am not pressing any buttons".

    Feel free to use it, no warranty given (MIT licence) , as always ^^

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEditor;
    4. using System.Diagnostics;
    5. using System;
    6. namespace JL
    7. {
    8.     public class SceneViewCameraFix : Editor
    9.     {
    10.         [InitializeOnLoadMethod]
    11.         static void FixIt()
    12.         {
    13.             SceneView.beforeSceneGui -= OnScene;
    14.             SceneView.beforeSceneGui += OnScene;
    15.         }
    16.         static Vector3 lastCamPosition;
    17.         static bool wKey;
    18.         static bool aKey;
    19.         static bool sKey;
    20.         static bool dKey;
    21.         static bool qKey;
    22.         static bool eKey;
    23.         private static void OnScene(SceneView scene)
    24.         {
    25.             Event e = Event.current;
    26.             if (e.isKey && e.type == EventType.KeyDown)
    27.             {
    28.                 if (e.keyCode == KeyCode.W) wKey = true;
    29.                 if (e.keyCode == KeyCode.A) aKey = true;
    30.                 if (e.keyCode == KeyCode.S) sKey = true;
    31.                 if (e.keyCode == KeyCode.D) dKey = true;
    32.                 if (e.keyCode == KeyCode.Q) qKey = true;
    33.                 if (e.keyCode == KeyCode.E) eKey = true;
    34.             }
    35.             bool hadKey = wKey || aKey || sKey || dKey || qKey || eKey;
    36.             if (e.isKey && e.type == EventType.KeyUp)
    37.             {
    38.                 if (e.keyCode == KeyCode.W) wKey = false;
    39.                 if (e.keyCode == KeyCode.A) aKey = false;
    40.                 if (e.keyCode == KeyCode.S) sKey = false;
    41.                 if (e.keyCode == KeyCode.D) dKey = false;
    42.                 if (e.keyCode == KeyCode.Q) qKey = false;
    43.                 if (e.keyCode == KeyCode.E) eKey = false;
    44.             }
    45.             bool reset = hadKey && !(wKey || aKey || sKey || dKey || qKey || eKey);
    46.             if (reset)
    47.             {
    48.                 scene.pivot = lastCamPosition;
    49.             }
    50.             lastCamPosition = scene.pivot;
    51.         }
    52.     }
    53. }
    54.  
     
    Last edited: Jun 22, 2020
    oxysofts and Lurking-Ninja like this.
  5. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
  6. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    657
  7. oxysofts

    oxysofts

    Joined:
    Dec 17, 2015
    Posts:
    124
    The simplest solutions are often the best!
     
    Werti100 likes this.