Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Blocked moving platform still makes passenger move!?

Discussion in 'Physics' started by FeastSC2, Jul 13, 2019.

  1. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    978
    In this example, I have a character and platform that's moving towards a wall.

    The platform is given a velocity that goes towards the wall and it makes the player move by that same velocity.
    So far that's what a moving platform should do.
    However once the platform reaches the wall it still makes the player move with its velocity!
    But the platform itself stops moving towards the wall because it is blocked by the wall.
    Watch a gif showing the problem: https://giphy.com/gifs/QtjTPezmayvNXz81s4

    I want the player/passenger to move as much as the platform moves and to stop moving when the platform is blocked.

    How can I know how much a platform will have moved before the physics update is called?
    Or if you have another solution to make the passenger move exactly the same amount as the platform I'm all ears!





    I'm using a custom controller for both the platform and the passengers but the overall idea is really simple: I'm using rigidbody.velocity to move the character / platform.
    Unfortunately this also means I cannot predict if my controller is going to be blocked by anything BEFORE moving. So I must somehow figure this problem out without knowing this beforehand.
     
    Last edited: Jul 13, 2019
  2. konsic

    konsic

    Joined:
    Oct 19, 2015
    Posts:
    995
    Did you try to parent player with platform ?
     
  3. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    978
    the rigidbody is not kinematic so it doesn't move with the parent transform
     
  4. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hello @FeastSC2 , you can measure the position delta and apply that as a velocity, or directly move the rigidbody via MovePosition or Rigidbody.position.

    I would recommend you to update the platform first (using the ExecutionOrder settings, put your platform script before the character movement script), then in your character movement script do something like this:

    Code (CSharp):
    1. bool isOnPlatform = false;
    2.  
    3. Rigidbody platform = null;
    4.  
    5. Vector3 currentPlatformPos = Vector3.zero;
    6. Vector3 previousPlatformPos = Vector3.zero;
    7.  
    8. ....
    9.  
    10. void FixedUpdate()
    11. {
    12.  
    13. // Do platform movement ---------------------------------------------------------------------
    14.  
    15. // First you must detect the platform somehow, frame by frame, via trigger, raycast, spherecast, etc... then set the platform reference with the Rigidbody of the platform.
    16.  
    17. if( platform != null )
    18. {
    19.          currentPlatformPos = platform.position;
    20.  
    21.          // First contact
    22.          if( !isOnPlatform )
    23.          {
    24.                  //Just set the flag, nothing else
    25.                  isOnPlatform = true;
    26.           }
    27.           else
    28.           {
    29.                        //Calculate the delta and apply the movement
    30.                    
    31.                         Vector3 deltaPos = currentPlatformPos - previousPlatformPos;
    32.  
    33.                          rb.MovePosition( rb.position + deltaPos );
    34.                          // or translate the delta into a velocity (velocity = deltaPos / FixedDeltaTime ), and add that velocity to the rb.velocity
    35.  
    36.            }
    37.            
    38.            //Update the previous position with the current (delta = 0)
    39.            previousPlatformPos = currentPlatformPos;
    40. }
    41. else
    42. {
    43.            //Reset the flag
    44.            isOnPlatform = false;
    45. }
    46.  
    47.  
    48.  
    49. // Do normal movement  ---------------------------------------------------------------------
    50. // ...
    51.  
    52. }
    53. ...
    I wrote the code in a hurry :) it could be wrong, but the idea is there, if you want independence between character and platform this will do (at least is worked for me).
     
    FeastSC2 likes this.
  5. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    978
    1) The platform no longer moves the passenger when it's blocked, thanks @lightbug14!
    By using the previous frame's moving platform displacement, it fixed my problem @lightbug14. Thank you!


    2) Another problem creeped up when stacking moving platforms on top of each other, but there's a way to fix for anyone that uses Unity Physics to move the platforms:
    I had another problem when stacking platforms on top of each other. I used boxes that my player can move as moving platforms. These boxes can be stacked on each other to make a tower of boxes.

    So each box has to move the box that's above it (it is passenger of the box below).

    However, I had some problems with the boxes on top being moved more than the box below it. But this is actually due to the physics of Unity, the 2 boxes were interacting together and it was creating issues.
    I have now fixed this by detecting when the passenger is being moved by the box underneath and disabling the collisions between the platform and the passenger.

    Code (CSharp):
    1.     protected override void Awake()
    2.     {
    3.         Controller.OnEnterPlatform += OnNewPlatform;
    4.         Controller.OnExitPlatform += OnExitPlatform;
    5.     }
    6.  
    7.     private void OnNewPlatform(MovingPlatform _platform)
    8.     {
    9.         Physics.IgnoreCollision(_platform.Col, this.Col, true);
    10.     }
    11.     private void OnExitPlatform(MovingPlatform _platform)
    12.     {
    13.         Physics.IgnoreCollision(_platform.Col, this.Col, false);
    14.     }

    3) There is one last issue that I have BUT I don't know how to fix it yet:



    The video shows that when a single box is moving, the movement is fluid.
    And when boxes are stacked on top of that box, the movement is stuttered.


    The movement of the passengers (the boxes that are stacked) is very blocky, stuttery.
    This seems like a problem related to the Rigidbody.interpolation setting. I tried to change it to all the options but it doesn't make a difference.
    In my code I change their position by using both Rigidbody.position and Rigidbody.MovePosition but it also doesn't make a difference, the graphics still look stuttery.

    What might be the reason for this?
     
  6. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Maybe that movement is due to a mix between interpolation and the execution order (i don't know how exactly you moved those boxes). Test the following: put a zero friction physic material to the boxes, remove all interpolation ( i think MovePosition should work as Rigidbody.position ), look at the boxes from the side, if the movement is done right you should see it frame by frame (well at 50 fps by default). I did this for my moving platforms using my gif recorder (ScreenToGif ... great tool!), and yes interpolation sometimes gives me that delay effect, which is understandable, but without interpolation everything works fine.
     
  7. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    978
    EDIT: Whenever I use Rigidbody.velocity instead of Rigibody.MovePosition or Rigidbody.position I get a smooth movement out of all the stacked boxes. Thanks for the help @lightbug14


    The way I move the boxes in terms of order of operations:

    Frame 1: I move the box 1
    Frame 2: I move the box 2 and its passengers by the movement of box 1's previous frame, I move the box 3 and its passengers by the movement of box 1's previous frame. Lastly, I move the box 1.

    What I know is that whenever the box 1 doesn't have passengers, its movement stutters unless I activate interpolation.
    It is only the moment that I stack boxes on top of each other that they exhibit this stuttery movement behaviour.

    Adding more boxes on the tower of boxes doesn't seem to make the stuttering bigger. It's just about equal.

    My physics material has 0 dynamic/static friction.

    I tried without interpolation, but the result is very similar.
     
    Last edited: Jul 15, 2019