Search Unity

Resolved Collision && Input to rotate something, issues.

Discussion in 'Scripting' started by GladisAd, May 15, 2023.

  1. GladisAd

    GladisAd

    Joined:
    Oct 5, 2014
    Posts:
    28
    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:
    Code (CSharp):
    1. [SerializeField] GameObject Player;
    2.     [SerializeField] Transform objectToRotate;
    3.     public float rotateSpeed;
    4.    
    5.     private void OnCollisionStay(Collision other)
    6.     {
    7.         if(other.gameObject == Player && Input.GetButton("Jump"))
    8.         {  
    9.             Player.transform.parent = objectToRotate.transform.parent;
    10.             objectToRotate.GetComponent<RotateObject>().enabled = true;
    11.             objectToRotate.GetComponent<RotateObject>().zAngle = rotateSpeed;
    12.         }  
    13.     }
    14.     private void OnCollisionExit(Collision other)
    15.     {
    16.         Player.transform.parent = null;
    17.         objectToRotate.GetComponent<RotateObject>().enabled = false;
    18.         objectToRotate.GetComponent<RotateObject>().zAngle = rotateSpeed;
    19.     }

    Object Rotation Code:
    Code (CSharp):
    1. [SerializeField] public float xAngle = 0f;
    2.     [SerializeField] public float yAngle = 0f;
    3.     [SerializeField] public float zAngle = 0f;
    4.  
    5.     void Update()
    6.     {
    7.         transform.Rotate(xAngle *Time.deltaTime, yAngle *Time.deltaTime, zAngle * Time.deltaTime);
    8.     }
    Any help would be much appreciated.
     
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,930
    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.
     
  3. GladisAd

    GladisAd

    Joined:
    Oct 5, 2014
    Posts:
    28
    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:
    Code (CSharp):
    1.     [SerializeField] GameObject Player;
    2.     [SerializeField] Transform objectToRotate;
    3.     public float rotateSpeed;
    4.     public float stopSpeed;
    5.     bool isTouching = false;
    6.      
    7.     private void Update()
    8.     {
    9.         if(Input.GetButton("Jump"))  
    10.         {
    11.             isTouching = true;
    12.         }
    13.         else
    14.         {
    15.             isTouching = false;
    16.         }
    17.     }
    18.  
    19.     private void OnCollisionStay(Collision other)
    20.     {
    21.         if(other.gameObject == Player && isTouching == true)
    22.         {              
    23.             objectToRotate.GetComponent<RotateObject>().enabled = true;
    24.             objectToRotate.GetComponent<RotateObject>().zAngle = rotateSpeed;
    25.         }
    26.         else if(isTouching == false)
    27.         {
    28.             objectToRotate.GetComponent<RotateObject>().enabled = false;
    29.             objectToRotate.GetComponent<RotateObject>().zAngle = stopSpeed;
    30.         }  
    31.     }
    32.     private void OnCollisionExit(Collision other)
    33.     {      
    34.         objectToRotate.GetComponent<RotateObject>().enabled = false;
    35.         objectToRotate.GetComponent<RotateObject>().zAngle = stopSpeed;
    36.     }
    Rotation Script:
    Code (CSharp):
    1.     [SerializeField] public float xAngle = 0f;
    2.     [SerializeField] public float yAngle = 0f;
    3.     [SerializeField] public float zAngle = 0f;
    4.  
    5.     void FixedUpdate()
    6.     {
    7.         transform.Rotate(xAngle *Time.deltaTime, yAngle *Time.deltaTime, zAngle * Time.deltaTime);
    8.     }