Collision && Input to rotate something, issues.

Hey,

I’m trying to rotate something when a physics player touches an object. I need to check that 1. there’s collision and 2. that a button is being pressed at the same time. The issue I’m having is that rotation is slow because the frames/collision don’t match up, if I increase the speed of the rotation the player bounces on the object, if I reduce the rotation speed it’s too slow. Is there a way to smooth the rotation to match the collision frames, or something else I could do?

Collision Code:

[SerializeField] GameObject Player;
    [SerializeField] Transform objectToRotate;
    public float rotateSpeed;
   
    private void OnCollisionStay(Collision other)
    {
        if(other.gameObject == Player && Input.GetButton("Jump"))
        {  
            Player.transform.parent = objectToRotate.transform.parent;
            objectToRotate.GetComponent<RotateObject>().enabled = true;
            objectToRotate.GetComponent<RotateObject>().zAngle = rotateSpeed;
        }   
    }
    private void OnCollisionExit(Collision other)
    {
        Player.transform.parent = null;
        objectToRotate.GetComponent<RotateObject>().enabled = false;
        objectToRotate.GetComponent<RotateObject>().zAngle = rotateSpeed;
    }

Object Rotation Code:

[SerializeField] public float xAngle = 0f;
    [SerializeField] public float yAngle = 0f;
    [SerializeField] public float zAngle = 0f;

    void Update()
    {
        transform.Rotate(xAngle *Time.deltaTime, yAngle *Time.deltaTime, zAngle * Time.deltaTime);
    }

Any help would be much appreciated.

If physics is at play here, then your rotation code should be happening in FixedUpdate, and be rotating the platform’s kinematic rigidbody via RigidBody.MoveRotation().

I also would not be polling input in InCollisionStay, as that happens in the physics loop as well. I would use OnCollisionEnter/Exit to enable and disable the component, and poll input as you would normally in Update.

Many thanks @spiney199 for the feedback. My setup for the platform is slightly more complex (parent with child blocks set out in circular shape around parent. 1 of those blocks, when touched, rotates the parent so no rigidbody on parent. Player touches the 1 block and rotates the whole thing). Nevertheless, I tried what you suggested and I just couldn’t get it to work. I lost all collision with the blocks and nothing seemed to work. I’m still learning C#, so my understanding is still quite minimal.

However, I did change the rotation to FixedUpdate, which worked, and had to solve the rest using an Update function:

Collision Script:

    [SerializeField] GameObject Player;
    [SerializeField] Transform objectToRotate;
    public float rotateSpeed;
    public float stopSpeed;
    bool isTouching = false;
     
    private void Update()
    {
        if(Input.GetButton("Jump"))   
        {
            isTouching = true;
        }
        else
        {
            isTouching = false;
        }
    }

    private void OnCollisionStay(Collision other)
    {
        if(other.gameObject == Player && isTouching == true)
        {              
            objectToRotate.GetComponent<RotateObject>().enabled = true;
            objectToRotate.GetComponent<RotateObject>().zAngle = rotateSpeed;
        }
        else if(isTouching == false)
        {
            objectToRotate.GetComponent<RotateObject>().enabled = false;
            objectToRotate.GetComponent<RotateObject>().zAngle = stopSpeed;
        }   
    }
    private void OnCollisionExit(Collision other)
    {       
        objectToRotate.GetComponent<RotateObject>().enabled = false;
        objectToRotate.GetComponent<RotateObject>().zAngle = stopSpeed;
    }

Rotation Script:

    [SerializeField] public float xAngle = 0f;
    [SerializeField] public float yAngle = 0f;
    [SerializeField] public float zAngle = 0f;

    void FixedUpdate()
    {
        transform.Rotate(xAngle *Time.deltaTime, yAngle *Time.deltaTime, zAngle * Time.deltaTime);
    }