Moving platform causes player to grow

Hello, a quick problem I’m having in my game is that, I followed a youtube tutorial on how to make a moving platform and the platform works, and does everything properly in terms of moving, but when I touch it and move on it, it stretches the player, and I cannot flip on it, as I can in the rest of the level. Here’s the entire Moving Platform Script, and the script that’s supposed to keep the player in place with it as it moves, which I think it also doesn’t do still.

// Moving Platform Script

public Transform movingPlatform;
    public Transform Pos1;
    public Transform Pos2;
    public Vector2 newPosition;
    public string currentState;
    public float smooth;
    public float resetTime;

    // Use this for initialization
    void Start ()
    {
        ChangeTarget();
    }
   
    // Update is called once per frame
    void FixedUpdate ()
    {
        movingPlatform.position = Vector2.Lerp(movingPlatform.position, newPosition, smooth * Time.deltaTime);
    }

    void ChangeTarget()
    {
        if (currentState == "Moving To Position 1")
        {
            currentState = "Moving To Position 2";
            newPosition = Pos2.position;

        }
        else if (currentState == "Moving To Position 2")
        {
            currentState = "Moving To Position 1";
            newPosition = Pos1.position;
        }
        else if(currentState == "")
        {
            currentState = "Moving To Position 2";
            newPosition = Pos2.position;
        }

        Invoke("ChangeTarget", resetTime);
    }
//Hold Character Script

void OnTriggerEnter2D(Collider2D col)
    {
        col.transform.parent = gameObject.transform; // when something collides, making object move with object with parenting
    }

    void OnTriggerExit2D(Collider2D col)
    {
        col.transform.parent = null; // unparent object when exiting collider
    }

This probably is not a good way to handle this, as it is assigning the parent of your character as the platform. This does allow the characters position to move along with the platform as it moves, but creates the issue of warping around values of the characters original transform. I suppose I can’t say for sure what would work without knowing how the character is setup, but what you probably need to do, is instead of changing the parent in ontriggerenter and ontriggerexit, set a bool to true (like _isOnPlatform) within the characterscript, and then set it as false when on trigger exit is called. Then in your characters update, if your on the platform, add the platforms motion on top of whatever motion is already happening. I can’t really share an example script of this, but basically you could calculate the speed your platform, and then manually add or subtract that amount from the position of your character for as long as they are still on the platform.

I did the first part of what you said, but I’m a bit too beginner to do the second part without any code examples. So when you say, “characters update” , do you mean my character controller scripts update function? And do you have any guidance or anything on how I could go about adding the platforms motion, and calculating it and all that? Sorry, I know you said you couldn’t really give an example, but any more guidance could go a long way! Thanks again!

Edit: Would posting my character controller script help?

Yes the characters script, in the update method, keep track of your bool (IDK why today I am using underscores as examples) _isOnPlatform, and if it becomes true, then maybe add just a hardcoded amount to his position. Sorta like this (probably won’t work without modification):

// inside Update method of characters script ***
float platformMoveSpeed = 0.5f; // adjust this until it mostly seems accurate

if(_isOnPlatform) // we are in the trigger zone for the platform! react!
{
// NOTE: your going to have to determine which way the platform is moving, either by keeping track of that in the platform
// script, or literally measuring it through some comparison math, so you can decide to either add or subtract this amount!
  transform.position = Quaternion.Euler(transform.position.x + platformMoveSpeed, transform.position.y, transform.position.z);
// in the above example we are adding to the X position of the character object, and that means we look like we are
// moving to the right, assuming the character moves on his x axis, and the camera faces positive z axis.
}

// then continue the normal update stuff after this check...

Ok I’m sorry, probably very stupid question but, just so I dont get mixed up. Do you mean put it in the character holder script, moving platform script, or (if im right in thinking this) put it in the characters controller script, as in the script that controls his movements and stuff like that? And I’m guessing to use isOnPlatform in that I’d have to create it? I hope you understand, thanks. lol

The _isOnPlatform variable, and the update part in the character “movement” script, whatever you want really that is attached to the character, ideally wherever your doing movement code to begin with.

I suppose you already have the part with the trigger code in the right place, but need to change the lines that make the parent of the characters object the platform object, and instead set _isOnPlatform to true, or to false when leaving the trigger.

I’d suggest that you change your platform update function to something more like this:

void FixedUpdate()
{
    movingPlatform.getComponent<Rigidbody2d>().movePosition(Vector2.Lerp(movingPlatform.position, newPosition, smooth * Time.deltaTime));
}

(Ideally you should store the Rididbody2d variable during the Start() function for better performance, but this is just for demonstration.) Theoretically, moving it using the movePosition function of the rigidbody means that physics will be taken into account, whereas just assigning to the position of the transform means it will ignore physics while moving the object. By having physics taking into account while moving your platform, it should exert some force on your character automatically - depending on what shape and materials the character and platform have (i.e. how much friction there is between them), that may have the desired effect without you needing to do any further work.

Thank you for the help Ferb, trying to put in your code, but it shows an error message at the getComponent and this is the error:

Error CS1061 ‘Transform’ does not contain a definition for ‘getComponent’ and no extension method ‘getComponent’ accepting a first argument of type ‘Transform’ could be found (are you missing a using directive or an assembly reference?) Rectangular Space.CSharp C:\Users\Devon\Documents\Unity Games\Rectangular Space\Assets\Scripts\MovingPlatform.cs 24 Active

Try this:

void FixedUpdate()
{
    movingPlatform.gameObject.getComponent<Rigidbody2d>().movePosition(Vector2.Lerp(movingPlatform.position, newPosition, smooth * Time.deltaTime));
}

MD, now movePosition shows an error : 2513229--173986--upload_2016-2-16_12-30-28.png

    void FixedUpdate()
    {
        movingPlatform.gameObject.GetComponent<Rigidbody2D>().MovePosition(Vector2.Lerp(movingPlatform.position, newPosition, smooth * Time.deltaTime));
    }

That should work, sorry was doing that offhand and didn’t notice capitalization problems!

Hey guys it works, but the platform is super slow and shaky, and wants to move up and down? But kinda also moves to the left? Any ideas?

Maybe change the value of “smooth” and see if higher or lower values change the… smoothness? I didn’t actually try out the code so I’m not sure how it acts, but let’s see what changing the values does…

Oh also make sure gravity doesn’t have an effect on the rigidbody of the platform!

FYI the smooth and delta time part is what dictates how fast it transitions from the current position, to the “lerped” position. If that value comes out higher than 1, it’s one, and if lower than 0, it’s 0. 1 would be very fast, 0 almost not moving.

I’ll just ramble some more… let’s see, you should have an if statement that checks if it’s reached “newPosition” yet, and if so, reverse and go back to the other direction (if you want that). And as you should always do, use debug statements to find problems, like do “Debug.Log (smooth * Time.deltaTime);” to see what it’s coming out as, and you’d put that in right after you actually use the values so you are current.

Ok so, I got it to move and go perfectly, but it won’t go back, and obviously I need an if statement, but I’m a bit confused, my if statement has no errors, but its not doing anything, if you could just help with this last part it’d be a life saver thanks!

if (movingPlatform.position.x == 8.5)
        {
            movingPlatform.gameObject.GetComponent<Rigidbody2D>().MovePosition(Vector2.Lerp(-movingPlatform.position, -newPosition, -smooth / -Time.deltaTime));
        }

I think I see the problem, your checking if the x is exactly equal to 8.5, however, it probably never exactly hits 8.5, so check instead if it’s equal or greater than 8.5 ( use >= instead of == ) and that will probably work! Oh also, 8.5 is a double, while 8.5f is a float, and you should probably use a float! Good luck!

Edit: oh also, you shouldn’t need negative numbers for delta time and stuff, the same positive logic should work both ways… I think… just make sure the “go to” position changes to the opposite direction. Like a way point at the far left and far right of the platforms movement path, maybe called leftNewPosition, and rightNewPosition. Definitely don’t use a negative transform.position for the platform as that’ll give you… strange results…

Example:

 // NOTICE: Non working code! :smile:
        
        if (movingPlatform.position.x >= 8.5f)
        {
            movingPlatform.gameObject.GetComponent<Rigidbody2D>().MovePosition(Vector2.Lerp(movingPlatform.position, newPosition, smooth * Time.deltaTime));
        }
        else if (movingPlatform.position.x <= -8.5f)
        {
            movingPlatform.gameObject.GetComponent<Rigidbody2D>().MovePosition(Vector2.Lerp(movingPlatform.position, otherNewPosition, smooth * Time.deltaTime));
        }

Edit2: and to explain that “Lerp” method further, the first argument is the starting position, the second argument is the destination (go to) position, and the third argument is how fast to get there… so it’s clamped between 0 and 1, with 0 being almost no movement at all, and 1 being very very fast movement, almost instantly. When you use that method in fixedupdate like we’re using it in these examples, where you multiply the last argument with delta time, what that basically does is take the “smooth” value, and multiply it by the fixed time step (because your doing it in fixed update, which happens once every fixed timestamp) and if you did it in the Update method instead, it would be multiplying by how much time has passed since the last frame… it’s hard to explain but basically it’s giving you smooth movement because it’s “lerping” between the actual objects position, and fractionally closer to the destination each frame, eventually reaching (or very close to) the destination.

Edit3: it’s occuring to me I’m thinking about it backwards and that example above won’t work, because it’s trying to move it on above 8.5f or below -8.5f, when in fact we want to “switch” directions once it reaches those positions. Give me a few minutes to run to the store here, and I’ll give you a working example.

Ok thanks so much for your explanation! I really understand now, and it will definitely help in the future with similar problems! Can’t wait to finally have this platform up and running properly! One problem I’ve run into still is it still doesn’t keep the player stuck to it but, I could just make that a game mechanic, but if you had any tips on fixing it, that’d about solve every platform problem I have, thanks again!

Ok, I think this might do the trick:

// these parts at the top of the script
        Vector3 targetPositionLeft;
        Vector3 targetPositionRight;
        bool switchDirection = false;
        Rigidbody2D platformRigidbody;

// this part in the Start() method obviously (just to keep from needing to get this reference every frame)
    void Start()
    {
       platformRigidbody = movingPlatform.gameObject.GetComponent<Rigidbody2D>();
       targetPositionLeft = new Vector3(-5, transform.position.y, transform.position.z); // here you wanna change the -5 value to be your "ending" positions of its movement far left
       targetPositionRight = new Vector3(5, transform.position.y, transform.position.z; // and here it would be the spot far right where you want it to stop
    } // GetComponent is costly performancewise, because it has to go and "find" this rigidbody anytime you call this, so instead lets keep a reference to it like this ^


// these parts inside FixedUpdate() or Update()
        if (movingPlatform.position.x >= targetPositionRight.x && !switchDirection)
        {
            switchDirection = true;
        }
        else if (movingPlatform.position.x <= targetPositionLeft.x && switchDirection)
        {
            switchDirection = false;
        }

        if(switchDirection) // were going to the left!
            platformRigidbody.MovePosition(Vector2.Lerp(movingPlatform.position, targetPositionLeft, smooth * Time.deltaTime));
        else
            platformRigidbody.MovePosition(Vector2.Lerp(movingPlatform.position, targetPositionRight, smooth * Time.deltaTime));

Now as far as moving the character to match… let me think a bit, I might have an idea that could work for that. Let’s see if this part works first.

EDIT: I made some changes to cache a reference to the rigidbody, so make sure your using the latest edit!

I inserted your code but I got this error!

Ooops, my bad, the variables should not be assigned from the top of the script (the target position ones). Instead they have to be assigned once the script is running…

So just make that part end after the name (like “Vector3 targetPositionLeft;”) and then in the Start method, put “targetPositionLeft = …” and the right one as well. My fault - didnt actually test any of that code :stuck_out_tongue:

EDIT: Oh and because your actually using this on the moving platform, you don’t need to use “movingPlatform.position”, but rather just transform.position!

EDIT2: I went ahead and updated the last post with correct code… which… should work :smile:

Ok I inserted your code, and no errors, but it still doesn’t move back.

Edit: would it possibly be the vector3 because Im making a 2D game and use all vector2’s? I don’t think it would since it still has x, and y that can be moved, and it doesn’t matter as long as the z isn’t changed(?)