Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Rigidbody rotation causing collision issues

Discussion in 'Scripting' started by UnTrust-Development, Jul 26, 2023.

  1. UnTrust-Development

    UnTrust-Development

    Joined:
    Jul 14, 2023
    Posts:
    3
    Hello guys, first thread I've ever posted in regards to coding, I'm still very new to this so forgive any formatting etc...

    I am currently making a super monkey ball clone as I thought it would be a fun test of my knowledge off the back end of a long course I have just finished on Unity.

    The code provided below is how I am currently controlling the level rotation. I am aware it is a not particularly efficient method for producing the result I'm looking for but it works very well for the time being and I will better update it once I've ironed out this issue. This is in a limited test environment so its currently the only script active.


    Code (CSharp):
    1. using JetBrains.Annotations;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using Unity.VisualScripting;
    5. using UnityEngine;
    6.  
    7. public class LevelTilt : MonoBehaviour
    8. {
    9.     public Quaternion startTransform;
    10.     public float verticalTilt;
    11.     public float horizontalTilt;
    12.     public float tiltSpeed = 2f;
    13.     public Rigidbody Rb;
    14.     Quaternion startPos = Quaternion.Euler(0f, 0f, 0f);
    15.    
    16.  
    17.     // Start is called before the first frame update
    18.     void Start()
    19.     {
    20.         startTransform = startPos;
    21.         Rb.useGravity = false;
    22.     }
    23.  
    24.     // Update is called once per frame
    25.     void Update()
    26.     {
    27.         verticalTilt = Input.GetAxis("Vertical");
    28.         horizontalTilt = Input.GetAxis("Horizontal");
    29.  
    30.         if (verticalTilt != 0f || horizontalTilt != 0f)
    31.         {
    32.             Rb.angularVelocity += new Vector3(verticalTilt * tiltSpeed * Time.deltaTime, 0, -horizontalTilt * tiltSpeed * Time.deltaTime);
    33.            
    34.         }
    35.        
    36.                
    37.     }
    38.     private void FixedUpdate()
    39.     {      
    40.         if (verticalTilt == 0f && horizontalTilt == 0f)
    41.         {
    42.             Rb.angularVelocity = Vector3.zero;
    43.             Rb.MoveRotation(Quaternion.RotateTowards(Rb.rotation, startPos, 7 * Time.time * Time.deltaTime));
    44.         }
    45.     }
    46.  
    47. }

    The issue is that when the level is rotating the collisions are getting ignored between the player and the level. If I don't move the level, the collisions work just fine.

    I see no reason as to why these rotations would cause issues with the colliders as I used a rigid body to control the rotations to make sure this wouldn't happen.

    Here's a list of the few things I have tried:

    re wrote the code using many different methods like Slerp and also tried to just use torque to test if it was the code and it seems no matter how I write it the issue still persists.

    Changed interpolation settings on both the level and player to all options.

    Changed collision detections between options continuous and continuous dynamic.

    Changed Timestep in project settings as well as many other suggested physics options that did nothing.

    Changed all mass and drag settings for both player and level.

    Made a limited test environment with simple colliders and shapes, issue still persists.

    I've done many other things and cant remember them all so if someone mentions something Ill add it to the list.

    I really cant see any reason as to why the collisions are messing up.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    You'll probably have a better experience not tilting the world but rather faking it.

    It's easy enough to fake too:

    - tilt the camera rig (centered on the player's ball)

    - change the gravity to the tilted "down" axis of the camera.

    This makes the physics engine not even aware that anything is tilting at all.
     
  3. UnTrust-Development

    UnTrust-Development

    Joined:
    Jul 14, 2023
    Posts:
    3
    I understand this from the perspective your coming from but when you play monkeyball its very evident that the player controls the level, how exactly would I fake the level moving, its very evident you see parts rise and fall as you tilt the joystick.
     
  4. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    510
    Line 43 looks a little broken. Especially where it does Time.time * Time.deltaTime. RB.MoveRotation is also probably messing things up.

    Try doing everything in FixedUpdate().

    Code (CSharp):
    1.     void FixedUpdate()
    2.     {
    3.         Vector3 dir=new Vector3(Input.GetAxis("Vertical"),0,-Input.GetAxis("Horizontal"));
    4.         rb.angularVelocity+=dir;
    5.         if (dir.x==0 && dir.z==0)
    6.         {
    7.             rb.angularDrag=10;
    8.             var rot=Quaternion.RotateTowards(rb.transform.rotation,startPos,1);
    9.             rb.AddTorque(new Vector3(-rot.x, -rot.y, -rot.z)*4f,ForceMode.VelocityChange);
    10.         }
    11.     }
     
  5. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,630
    Visually there's *no difference at all* between moving the camera and moving the level. Eg: rotating the camera downwards 45º degrees, is the same as tilting the level upwards 45º.

    In fact this is how the concept of "camera" works internally in graphics: graphics APIs can only draw content inside a cube centered on the screen. So to render things as if viewed from a specific camera, all objects in the scene are drawn at a position/rotation that's the exact opposite of the current camera's. For instance if the camera is at X = 5, Y = 2, Z = 0, you'd just offset everything you draw -5 units in the X axis and -2 units in the Y axis.

    Once you get into shaders and how render pipelines work, you'll come across the term "MVP" or "model view projection" a lot. This is how object vertices are transformed to draw them on the screen, roughly goes like this:
    • Vertices of the mesh are moved to the position/rotation of the object in the world. This is the "model" transform.
    • Then they are moved by the negative position/rotation of the current camera. This is the "view" transform.
    • Then they are projected from 3D to 2D coordinates on the screen. This is the "projection" transform.

    That's how you go from mesh vertices to actually drawing stuff on a flat screen from a specific point of view. So in Monkeyball's case, you could say there's no "model" transform since the level stays still, all movement goes into the view transform (the camera).
     
    Last edited: Jul 27, 2023
    Kurt-Dekker likes this.