Search code examples
c#unity-game-enginepause

How to pause a Ridigbody2D in unity?


I would like to know how I can pause a rigidbody2D and resume it. I have tried a number of different ways and none have worked. I think the main issue is that when the game is paused, my rigidbody2D will be moving so I need to be able to pause the rigidbody2D, and when un - paused the rigidbody2D should continue moving as before.

This is the code I have so far:

using UnityEngine;
using System.Collections;

public class Pause : MonoBehaviour {


    private Rigidbody _rigidBody;
    void Awake () 
    {
        _rigidBody = Ball.GetComponent<Rigidbody>();
    }

    private Vector3 _pausedVelocity;
    private Vector3 _pausedAngularVelocity;

    public void OnMouseEnter() 
    {
        Debug.Log("Pause with velocity=" + _rigidBody.velocity + " & angularVelocity=" + _rigidBody.angularVelocity);
        _pausedVelocity = _rigidBody.velocity;
        _pausedAngularVelocity = _rigidBody.angularVelocity;
        _rigidBody.isKinematic = true;
    }

    public void OnMouseExit() 
    {
        _rigidBody.isKinematic = false;
        _rigidBody.velocity = _pausedVelocity;
        _rigidBody.angularVelocity = _pausedAngularVelocity;
        Debug.Log("Resume with velocity=" + _rigidBody.velocity + " & angularVelocity=" + _rigidBody.angularVelocity);
    }
}

Basically this code is attached to an empty with a collision2D component and when the mouse hovers over it, it prints pause, and when the mouse moves away, it prints play. So that all works, I just need to figure out how I can pause the rigidbody2D!

Thanks in advance!


Solution

  • If you want to pause all gameobjects You could just set Time.timeScale to 0

    If you want to pause just one gameobject, on Pause you store the velocity and angular velocity and set Rigidbody.isKinematic to true and on Resume restore the original values.

    public class PausableRigidbody : MonoBehaviour {
    
        private Rigidbody _rigidBody;
        void Awake () 
        {
            _rigidBody = this.GetComponent<Rigidbody>();
        }
    
        private Vector3 _pausedVelocity;
        private Vector3 _pausedAngularVelocity;
    
        public void Pause() 
        {
            Debug.Log("Pause with velocity=" + _rigidBody.velocity + " & angularVelocity=" + _rigidBody.angularVelocity);
            _pausedVelocity = _rigidBody.velocity;
            _pausedAngularVelocity = _rigidBody.angularVelocity;
            _rigidBody.isKinematic = true;
        }
    
        public void Resume() 
        {
            _rigidBody.isKinematic = false;
            _rigidBody.velocity = _pausedVelocity;
            _rigidBody.angularVelocity = _pausedAngularVelocity;
            Debug.Log("Resume with velocity=" + _rigidBody.velocity + " & angularVelocity=" + _rigidBody.angularVelocity);
        }
    }
    

    UPDATE 1

    A PausableRigidbody instance can be called by a reference over a SerializeField, which can be filled by selecting a PausingView in the Unity Inspector and drag the Ball with the Script PausableRigidbody into Inspector, so that it looks like this:

    Unity Editor PausingView with serialized field PausableRigidbody

    public class PausingView : MonoBehaviour {
    
        [SerializeField]
        private PausableRigidbody _pausableRigidbody;
    
        public void OnMouseEnter() 
        {
            _pausableRigidbody.Pause();
        }
    
        public void OnMouseExit() 
        {
            _pausableRigidbody.Resume();
        }
    }