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

Player stick to moving platform [Two ways solution]

Discussion in 'Scripting' started by NulledVector, Aug 2, 2015.

  1. NulledVector

    NulledVector

    Joined:
    Feb 7, 2015
    Posts:
    3
    Hello,

    I have been stuck for a couple of days and unable to make a clean script that would move my player along with the platform he is standing on (moving platform) while sustaining the player's local scale and control to exit or enter the platform.

    The first methodology i tried was the one which uses the parent-child relationship (where you set the player as child of the moving platform, consequently the player's position automatically gets adjusted based on its parent). However, this methodology tends to have have plenty of disadvantages that i might face in the future, in the meantime its only that the Scale of a child always have to be equal to its parent, so if i have a moving platform with scale of 2,2,2, once the player becomes its child, the player will automatically have the scale of 2,2,2 (which is bad).

    The second methodology seems to have a higher potential at the beginning, but it does however have one issue. Well, simply do a Raycast from the player's to his down side, check if the ray collides with the moving platform or not, if it does, then set the flag of the onPlatform = true, and consquently adjust the player position based on the moving platform. Well, it all looks good at this point, but here comes the issue where as long as you are updating the player position based on the moving platform's position , you will not be able to exit the zone of moving platform, your player is basically STICKING forever to that platform.

    See script for the 2nd methodology below:


    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class TestMovingPlatform : MonoBehaviour {
    6.  
    7.  
    8.     private bool isOnMovingPlatform;
    9.  
    10.     public Transform player;
    11.     public Transform sightStart, sightEnd;
    12.  
    13.     private void Update()
    14.     {
    15.  
    16.         RaycastHit2D hit;      
    17.         hit = Physics2D.Linecast(sightStart.transform.position, sightEnd.transform.position);
    18.         Debug.DrawLine(sightStart.transform.position, sightEnd.transform.position, Color.red);
    19.  
    20.         if (hit.transform == null)
    21.         {
    22.             Debug.Log("Returning");
    23.             return;
    24.         }
    25.            
    26.  
    27.             if (hit.transform.tag == ("MovingPlatform"))
    28.             {
    29.                 Debug.Log("hit.transform = MovingPlatform:" );
    30.                 Transform movingPlatform = hit.collider.transform;
    31.                 isOnMovingPlatform = true;
    32.             }
    33.  
    34.             else
    35.             {
    36.                 Debug.Log("not moving platform but: " + hit.transform.tag);
    37.                 isOnMovingPlatform = false;
    38.             }
    39.  
    40.             if (isOnMovingPlatform)
    41.             {
    42.                 Debug.Log("Adjusting player pos");
    43.                 player.position = new Vector3(hit.transform.position.x, hit.transform.position.y + offsetToKeepPlayerAbovePlatform, 0);
    44.    
    45.             }
    46.        
    47.     }
    48.  
    49. }
    Any suggestions on how to improve above idea or even a new idea to make a moving platform script that is scale-able and independent?
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    The optional second parameter of SetParent() should resolve all of your issues with scaling.

    worldPositionStays - If true, the parent-relative position, scale and rotation is modified such that the object keeps the same world space position, rotation and scale as before.
     
    NulledVector likes this.
  3. NulledVector

    NulledVector

    Joined:
    Feb 7, 2015
    Posts:
    3
    I think that would work for the first solution, I didn't have the chance to notice the second parameter of SetParent tho. Anyway, i still think that the 2nd methodology (which uses RayCast) is way more efficient and works way more independently.

    I have got help from someone and managed to get it working. The idea behind moving the player while standing on the platform while sustaining player's control to exit or re-enter the platform was to simply let the player behave exactly as the platform while standing on it, i.e take a destination and start moving towards that destination with the same acceleration of the platform, that way you get the feeling that they are synchronized.

    Basically, I had to pass some data about the destination of the moving platform along with its velocity (the speed it moves by) to the player's controller script, and from there i made a small method that uses these data to move the player in the same direction, with same velocity of the moving platform.

    Here is my script which detects whether or not the player is standing on the moving platform and decides whether or not to start moving the player.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class MovePlayerOnPlatform : MonoBehaviour {
    5.  
    6.     public Transform player;
    7.     public Transform sightStart, sightEnd;
    8.  
    9.     private bool isOnMovingPlatform;
    10.     private PlayerController playerController;
    11.  
    12.  
    13.     void Awake()
    14.     {
    15.         playerController = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>();
    16.     }
    17.  
    18.     private void FixedUpdate()
    19.     {
    20.  
    21.         RaycastHit2D hit;
    22.         hit = Physics2D.Linecast(sightStart.transform.position, sightEnd.transform.position);
    23.  
    24.         Debug.DrawLine(sightStart.transform.position, sightEnd.transform.position, Color.red);
    25.  
    26.         if (hit.transform == null)
    27.             return;
    28.          
    29.  
    30.             if (hit.transform.tag == ("MovingPlatform"))
    31.             {
    32.                 Transform movingPlatform = hit.collider.transform;
    33.                 playerController.SetPlayerOnPlatform(true);
    34.                 playerController.MovePlayerOnPlatform();
    35.             }
    36.  
    37.             else
    38.             {
    39.                 playerController.SetPlayerOnPlatform(false);
    40.             }
    41.  
    42.    
    43.      
    44.     }
    45.  
    46. }

    And here is the MovePlayerOnPlatform method from the player's controller.


    Code (CSharp):
    1.     public void MovePlayerOnPlatform()
    2.     {
    3.         Vector3 destination;
    4.         float movingSpeed;
    5.  
    6.         destination = platformObject.GetDestination();
    7.         movingSpeed = platformObject.GetPlatformSpeed();
    8.  
    9.         if(IsPlayerOnPlatform())
    10.         {
    11.             playerTransform.position = Vector3.MoveTowards(playerTransform.position, destination, Time.deltaTime * movingSpeed);
    12.         }
    13.     }
    I hope above code / explanation would solve somebody's problem as it did for me.
     
    Alexx019 likes this.
  4. GameDevBijian

    GameDevBijian

    Joined:
    Mar 13, 2018
    Posts:
    2
    Good solution. I used your solution as well, thanks
     
  5. Davidshm

    Davidshm

    Joined:
    Oct 3, 2020
    Posts:
    6
    Do both code bodies work on their own or do you have to use them together?
     
    zajonzmateusz likes this.
  6. Davidshm

    Davidshm

    Joined:
    Oct 3, 2020
    Posts:
    6
    also could you use this system with simple collisions instead of raycasts?