how do i slow down time without slowing down the player as when i tried to implement my own version

using System;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;

namespace UnityStandardAssets.Characters.FirstPerson
{
    [RequireComponent(typeof(Rigidbody))]
    [RequireComponent(typeof(CapsuleCollider))]
    public class JumpingPhysics : MonoBehaviour
    {
        [Serializable]
        public class AdvancedSettings
        {
            public float groundCheckDistance = 0.01f; // distance for checking if the controller is grounded ( 0.01f seems to work best for this )
            public float stickToGroundHelperDistance = 0.5f; // stops the character
            public float slowDownRate = 20f; // rate at which the controller comes to a stop when there is no input
            public bool airControl; // can the user control the direction that is being moved in the air
            [Tooltip("set it to 0.1 or more if you get stuck in wall")]
            public float shellOffset; //reduce the radius by that ratio to avoid getting stuck in wall (a value of 0.1f is nice)
        }

        private float m_YRotation;

        private Rigidbody m_RigidBody;
        public bool m_PreviouslyGrounded, m_IsGrounded;
        public Vector3 m_GroundContactNormal;
        private CapsuleCollider m_Capsule;
        public AdvancedSettings advancedSettings = new AdvancedSettings();
        public float verticalVelocity = 0f;
        public float gravity = 9.80665f;
        public float jumpForce = 20.0f;
        public float MovementSpeed;
        public float MovementSpeedDefault = 10f;
        public float forces = 10.0f;
        public float drag = 10.0f;
        public CharacterController controller;
        public float slowdownFactor = 0.005f;
        public float Matrix_Time = 0;
        public float Time_Original = 0;
        public bool Matrix = false;
        public bool Matrix_Instant_Time = true;
        public int Matrix_State = 0;

        public void DoSlowmotion()
        {
            Matrix_State = 2;
            Matrix_Time = slowdownFactor;
            Time.timeScale = Matrix_Time;
        }

        public void DoSpeedUp()
        {
            Matrix_State = 3;
            Matrix_Time += (1f / 1f) * Time.unscaledDeltaTime;
            Matrix_Time = Mathf.Clamp(Matrix_Time, 0f, 1f);
            Time.timeScale = Matrix_Time;
            if (Matrix_Time >= Time_Original) Matrix_State = 0;
        }

        public void DoSlowDown()
        {
            Matrix_Time -= (1f / 1f) * Time.unscaledDeltaTime;
            Matrix_Time = Mathf.Clamp(Matrix_Time, 0f, 1f);
            Time.timeScale = Matrix_Time;
            if (Matrix_Time < slowdownFactor) Matrix_State = 1;
        }

        public void Start()
        {
            if (Matrix_Time == 0) Matrix_Time = Time.timeScale;
            if (Time_Original == 0) Time_Original = Time.timeScale;
            MovementSpeed = MovementSpeedDefault;
            m_RigidBody = GetComponent<Rigidbody>();
            m_Capsule = GetComponent<CapsuleCollider>();
            controller = GetComponent<CharacterController>();
        }

        private Vector3 moveDirection = Vector3.zero;

        private void Update()
        {
            Update1();
        }

        private void Update1()
        {
            GroundCheck();
            InteractRaycast();
            if (controller.isGrounded)
            {
                moveDirection = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));
                moveDirection = transform.TransformDirection(moveDirection);
                moveDirection *= MovementSpeed;
                if (Input.GetButton("Jump")) moveDirection.y = jumpForce / Matrix_Time;
                MovementSpeed = MovementSpeedDefault / Matrix_Time;
            }
            else
            {
                moveDirection.y -= (gravity * Time.fixedUnscaledDeltaTime) / Matrix_Time;
            }
            verticalVelocity = moveDirection.y;
            controller.Move(moveDirection * Time.fixedDeltaTime);
            if (Input.GetButtonDown("Matrix")) Matrix = !Matrix;

            if (Matrix)
            {
                if (Matrix_Instant_Time)
                {
                    if (Matrix_State == 0) DoSlowmotion();
                }
                else
                {
                    if (Matrix_State == 0 || Matrix_State == 3) DoSlowDown();
                    if (Matrix_State == 1) DoSlowmotion();
                }
            }
            else
            {
                if (Matrix_Instant_Time)
                {
                    Matrix_Time = Time_Original;
                    Time.timeScale = Matrix_Time;
                    Matrix_State = 0;
                }
                else DoSpeedUp();
            }
            Time.fixedDeltaTime = Time.timeScale * .02f;
        }

        private Vector2 GetInput()
        {
            Vector2 input = new Vector2
            {
                x = CrossPlatformInputManager.GetAxis("Horizontal"),
                y = CrossPlatformInputManager.GetAxis("Vertical")
            };
            return input;
        }

        /// sphere cast down just beyond the bottom of the capsule to see if the capsule is colliding round the bottom
        private void GroundCheck()
        {
            RaycastHit hitInfo;
            if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f - advancedSettings.shellOffset), Vector3.down, out hitInfo,
                                ((m_Capsule.height / 2f) - m_Capsule.radius) + advancedSettings.groundCheckDistance, Physics.AllLayers, QueryTriggerInteraction.Ignore))
            {
                m_IsGrounded = true;
                m_GroundContactNormal = hitInfo.normal;
            }
            else
            {
                m_IsGrounded = false;
                m_GroundContactNormal = Vector3.up;
            }
        }

        void InteractRaycast()
        {
            Vector3 playerPosition = transform.position;
            Vector3 forwardDirection = transform.forward;
            Ray InteractionRay = new Ray(playerPosition, forwardDirection);
            RaycastHit InteractionRayHit;
            float InteractionRayLength = 5.0f;

            Vector3 InteractionRayEndpoint = forwardDirection * InteractionRayLength;
            Debug.DrawLine(playerPosition, InteractionRayEndpoint);

            bool hitfound = Physics.Raycast(InteractionRay, out InteractionRayHit, InteractionRayLength);
            if (hitfound)
            {
                GameObject hitGameObject = InteractionRayHit.transform.gameObject;
                string hitFeedBack = hitGameObject.name;
                printfTools.Tools.fprintf(Debug.Log, "FPRINTF raycast hit object with name %s", hitFeedBack);
            }
        }
    }
}

i encounter the following bugs

when jumping then slowing down time, my character jumps at a lower height, due to the jumpforce not scaling with timescale

when jumping then speeding up time my character jumps WAY higher than normal

when falling and slowing down time my character slows down then speeds back up to normal

when falling and speeding up time my character falls WAY faster than it normally should

when moving and speeding up time my character zooms forward for a bit then moves normally

when slowing down time beyond 0.005, eg 0.004, the movement code that balances the player speed with the time scale becomes unreliable as the player will move faster than they are supposed to, which should not happen

these bugs should not be happening yet they are and i do not know how i would fix them

  • I have not had a chance to play the latest spider-man game or read your post yet. But based on the title, Time.timeScale may be what you are looking for: docs.unity3d.com/ScriptReference/Time-timeScale.html – Evorlor Dec 4 at 21:29
  • im already using that – PSP CODER Dec 4 at 23:06
  • 1
    Try shortening up the question. You have posted a lot to read, and many of us are only able to be on StackExchange while compiling and such, and have limited time. – Evorlor Dec 5 at 2:09
  • i will try when my video's upload (Spider Man 3 Reflex Time comparison against Enemies, and Spider Man 3 Reflex Time comparison against Train ) as the videos can probably explain this ALOT better than i can – PSP CODER Dec 5 at 4:06
  • 2
    slow down the game time and increase player speed. – Manoj Balaji M Dec 5 at 5:23

You could setup a table of delta time multipliers and have your objects read off those based on their assigned groups.

So you'd have something like

mySpeed = velocity * Time.delta

but instead do

mySpeed = velocity * TimeTable.get(PlayerTimer);

PlayerTimer would then be an enum of some sorts.

The get function would be something like:

float get(myEnumType group){
     return Time.delta * timetable[group];
}

where timetable is a map<myEnumType, float>;

float set(myEnumType group, float multiplier){
     timetable[group] = multiplier;
}

Downside of course is it's a bit more management. Unless you only have a few groups it should be fine.

  • 1
    and how would that work with the physics? – PSP CODER Dec 5 at 12:38
  • Ah yes pretty much an oversight of mine. Google search shows you could playaround with the fixedDeltaTime and timeScale. Or you should directly manipulate the velocity/mass based on those scaling factors. – Sidar Dec 5 at 12:51
  • increasing the rate at which physics occur tenfold then slowing that down to emulate Reflex Time would not work would it? – PSP CODER Dec 6 at 7:25

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.