Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question VR Table Tennis Physics

Discussion in 'Physics' started by DbDib, May 3, 2024.

  1. DbDib

    DbDib

    Joined:
    May 23, 2015
    Posts:
    15
    Currently creating a VR table tennis game for Quest, but I'm struggling a bit with a few issues, mostly at the moment ensuring that the rigidbody paddle follows the player's hand and the collision response of the ball hitting the paddle. Any help or suggestions would be appreciated! Here's my current approach, :

    • Running on Quest so I set the fixed timestep to 1/72
    • The ball is a rigidbody (continuous dynamic collision detection, movement is set to interpolate), and I'm manually controlling the movement of the ball by setting the rigidbody's velocity (rb.velocity = ballVelocity), applying gravity manually each frame (ballVelocity.y -= grav * Time.deltaTime). That bit seems to work well.
    • When ball collides with paddle (OnCollisionEnter()), ball will reflect off of the paddle with Vector3.reflect(ballVelocity.normalized,hitFaceNormal) using the ball's direction (normalized velocity) as the input and the paddle's normal for the face that was hit.
    • We then set the magnitude of the reflection vector based on the ball's speed, added to the paddle's movement vector (using Vector3.Dot to see how much of the paddle's current velocity is aligned with the direction the ball was reflected)
    There's a bit more to it than that, but that's the basic idea for now, and it works mostly well. But I'm struggling with a couple of issues.

    First major issue... the paddle needs to follow the player's hand INSTANTLY in VR every frame. The paddle must be able to detect collisions with the rigidbody ball, so the paddle needs to also be a rigidbody. But, I'm not sure of any way to make the rigidbody paddle follow without lag.

    • Making a separate paddle rigidbody collider object that follows around the paddle by setting, in FixedUpdate(), the rb.velocity = (paddle.transform.position - rb.position) * 100 can lead to lag or the rigidbody overshooting the position and settling in over the course of a couple frames.
    • Making a separate paddle rigidbody collider object and using a physics fixed joint to connect it to a child transform of the real non-rigidbody paddle works, but also introduces lag, where the rigidbody lags behind the actual position of the paddle.
    What happens is that, when I hit the ball, the rigidbody collider that follows behind my paddle can be so offset sometimes, still catching up, that you can instantly notice that the ball didn't visually collide with your paddle, or goes right through your paddle for a couple frames or so, it feels loose and sloppy, and I'm pulling my hair out coming up with a solution. I considered a custom raycasting approach where the ball will spherecast, and the paddle can boxcast, and doing away with this whole physics and fixed timestep but... since you can rotate and swing your paddle that way too, I'm struggling with boxcasting for rotations rather than just positions (eg. paddle is facing this direction, then wants to rotate to a new direction without physically moving, then you can boxcast but which orientation? the current orientation, or the desired orientation that it's rotating to? etc.).

    Any help, direction, resources, etc. would be amazing, thanks!!
     
  2. DbDib

    DbDib

    Joined:
    May 23, 2015
    Posts:
    15
    Wanted to update! Any additional relevant updates to my original question that would help others, I'll just edit this post right here rather than making a new post (unless someone comments).

    So, I did make some progress on the issue, and so far, it's definitely a big step in the right direction! Apologies if all this seems obvious - I'm not new to Unity, but definitely have a lot to learn about Unity's physics.

    My pc wasn't hitting a consistent 72 fps while testing inside the unity editor and the quest simultaneously, something I hadn't noticed, which was causing quite a bit of desync. But a standalone Quest build hits 72 fps just fine. Also, rather than making the paddle and its collider (as a separate rigidbody gameobject) completely separate, I experimented with making the paddle gameobject itself a rigidbody that's NOT a child of the player's hand. But it needs to follow the player's hand 1:1, right? And we can't make the paddle a child of the player's hand, so instead, in FixedUpdate(), I'm using MovePosition and MoveRotation to move it towards the player's hand every fixed update, and since fixed update should be called 72 times a second (timestep of 1/72f), and the Quest updates 72 times a second, then theoretically the paddle's rigidbody movement should look completely smooth with no positional/rotational lag since it's updating every frame in the Quest. That works!

    I made the paddle kinematic, continuous dynamic collision, and set to interpolate. I'm now able to have the rigidbody paddle locked exactly to my player's hand with no visible lag, and able to get collision callbacks (OnCollisionEnter()) so I can have complete control over the ball's response when hit by the paddle.

    One other question pertaining to the ball physics - when the ball hits the paddle, we can just reflect off of the paddle's face normal that was hit, and a bit more math to figure out an appropriate force to apply the ball. But, in a situation where the ball and the paddle's face normal are facing the same direction (eg. ball is falling downwards, and you slam the paddle down to hit the ball down to the ground even faster), we wouldn't reflect, as the ball would reflect at an odd angle. I've been experimenting with using the dot product to check if the paddle's face normal and ball's movement vector are pointing in the same general direction, and if so, the ball will just use the paddle's face normal as the direction to be hit at, but that... doesn't seem right. Any suggestions?
     
  3. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    1,054
    Now that you've improved your bat's movement have you tried letting Unity handle the ball's velocity and the collisions between the bat and ball?. Try setting the ball's mass to 0.1 and adding a very bouncy physics material to the ball.
     
  4. DbDib

    DbDib

    Joined:
    May 23, 2015
    Posts:
    15
    Thanks zulo, coincidentally that's actually exactly what I tried a bit after I posted - decided to let Unity's physics handle it and added a bouncy physics material to the ball with a bounce of 0.75. It feels tons better and no weird reflection angles or anything, everything just seems to work incredibly smoothly now. In the end, I actually ended up not even having to write any code (except for updating the position of the paddle to the player's hand, and a couple lines to limit the ball's velocity because sometimes even a flick of the wrist would cause insanely high forces against the ball and send it flying halfway across the world).

    At some point, I'll need to modify the ball's velocity right after it's hit though, for certain powerups (like lightning balls that move faster and ice balls that move slower). I was originally attempting it in OnCollisionEnter() without much luck - I'm assuming that if you're swinging fast enough and at the correct angle, the ball might actually remain attached on your paddle for a few frames, so maybe I need to modify the ball's final hit velocity in OnCollisionExit() when the ball leaves the paddle? I'll have to experiment some more!
     
  5. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    1,054
    You can set the drag setting on the ball's rigidbody to limit the ball's speed and switch to another physics material during game play to change its behavior.

    When the bat and ball are moving at a high velocity you could switch the bat's collider to a single flattened box collider to help keep the collision detection as simple as possible.