Changing time scale causing frame loss (I think)

I added this code with timeSlow() being run in Update():

 public  void timeSlow()
{
     if (Input.GetMouseButtonDown(1))
     {
         timeSlowStart();
     }
     if (Input.GetMouseButtonUp(1))
     {
         timeSlowStop();
     }
}

private void timeSlowStart()
{
     Time.timeScale = .5f;
     movementSpeed = movementSpeed / 2f;
     slowDown.Play();
}
private void timeSlowStop()
{
     Time.timeScale = 2f;
     movementSpeed = movementSpeed * 2f;

The problem is, this code seems (I think) to be causing frame loss and continues input from before, leading to the first person camera to fling around when timeSlowStart is called. It only happens sometimes and I have no clue why. This is my first project in c# with unity and I am so lost. Can anyone help me?

EDIT: For anyone reading this in the future, turns out it is not timescale changing and causing frame loss, it is a problem with my camera view and wasd movement script. Still no clue why it’s happening.

What does your camera code look like? I’m having trouble picturing what your problem is too. Maybe draw a picture or upload a video of it as well?

I’m with RadRed… sounds like the discontinuity in framerate may be triggering some instability in the Camera code, perhaps something related to the camera’s smoothing.

And what is slowDown.Play()? Just some audio or an animation? If it’s an animation, does it in any way involve components related to the camera or camera controller?

Camera stuff is pretty tricky… you may wish to consider using Cinemachine from the Unity Package Manager.

There’s even a dedicated forum: https://forum.unity.com/forums/cinemachine.136/

If you insist on making your own camera controller, the simplest way to do it is to think in terms of two Vector3 points in space: where the camera is LOCATED and where the camera is LOOKING.

private Vector3 WhereMyCameraIsLocated;
private Vector3 WhatMyCameraIsLookingAt;

void LateUpdate()
{
  cam.transform.position = WhereMyCameraIsLocated;
  cam.transform.LookAt( WhatMyCameraIsLookingAt);
}

Then you just need to update the above two points based on your GameObjects, no need to fiddle with rotations.

As a follow-up, I think the abrupt change in the timeScale is causing issues, maybe

slowDown.Play() is just a audio.

Here is the camera view code:

    public float mouseSens = 100f;

    public Transform player;

    float xRotation = 0f;

    // Start is called before the first frame update
    void Start()
    {
       
    }

    // Update is called once per frame
    void Update()
    {
        Look();
    }

    public void Look()
    {
        float mouseX = Input.GetAxis("Mouse X") * mouseSens * Time.deltaTime;
        float mouseY = Input.GetAxis("Mouse Y") * mouseSens * Time.deltaTime;

        xRotation -= mouseY;
        xRotation = Mathf.Clamp(xRotation, -90f, 90f);


        transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
        player.Rotate(Vector3.up * mouseX);
    }
}

Also, the slowDown and SpeedUp code is a part of a semi-large script that is running a bunch of other functions at the same time using Update() and FixedUpdate(), could the problem be that the script is somehow over worked (I am quite new to this so I don’t know the limits of scripts and how many resources are being used)?

Did some experimentation, after rethinking I don’t think the problem is the timeSlow script, but my movement script itself. when pressed against another slanted/sloped collider sometimes my rotation will just jump randomly.

Here is my movement function and my sprinting function just incase it has anything to do with those:

    private void wasdMovement()
    {
        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");

        Vector3 move = transform.right * x + transform.forward * z;

        rb.AddForce(move * movementSpeed * 3f, ForceMode.Force);
    }

    private void Sprinting()
    {
        if (Input.GetKeyDown(KeyCode.LeftShift))
        {
            movementSpeed = movementSpeed + movementSpeed / 2f;
        }

        if (Input.GetKeyUp(KeyCode.LeftShift))
        {
            movementSpeed = (2f * movementSpeed) / 3f;
        }
    }

Why not just set the .velocity of the Rigidbody rather than using AddForce?

Also, all physics needs to be called from FixedUpdate() or else you will see some weird scaling distortion effects.

Otherwise, perhaps try some other Rigidbody-based character controllers.

Usually when you change time scales you don’t also change velocity. That’s the point of scaling time.

For setting the velocity, I had read that you shouldn’t use it most cases so I had assumed that I shouldn’t use it for wasdMovement. I will look further into using rb.velocity for this.

wasdMovement() is in FixedUpdate

If I recall correctly the other ways of controlling characters is either changing the rigidbody to Kinematic or adding a Character Controller. I would use a Kinematic rigidbody but I don’t now enough about c# and unity to fully be ready for that. Character Controllers are good, but I am worried that all of my movement script would have to be rewritten.

After I posted the original comment I realized this and got rid of changing the movement speed on timeSlow.

Why not set all this aside and go do a couple Youtube tutorials on implementing slow motion, then drop in a bog-standard character controller and see how it goes? For instance, I know this one doesn’t have any issues with slowing time down because I just tried it:

That one has run, walk, jump, slide, crouch… it’s crazy-nutty!!

Here was my slomo test script:

using UnityEngine;

// @kurtdekker - drop on any GameObject, use key to cycle time speeds

public class slomo : MonoBehaviour
{
    int scaleIndex = 1;

    void Update ()
    {
        if (Input.GetKeyDown( KeyCode.Semicolon))
        {
            scaleIndex++;

            int i = (scaleIndex % 3);

            // cycles 0.5f, 1.0f, 2.0f speeds
            float scale = Mathf.Pow( 2, i) / 2;

            Debug.Log( scale);

            Time.timeScale = scale;
        }    
    }
}

Also why are you multiplying/dividing movement speed by 2? your movement vector should always be multiplied by time.(fixed)deltaTime, which itself is already multiplied by time.timeScale.

I got rid of that awhile ago after I realized I had made a mistake.

1 Like

Here’s a video of the snapping I am talking about:

turns out it has nothing to do with slowing down time, just a coincidence that it happened a few times while slowing down time.