Player staying on Trains/Moving platforms? [SOLVED]

For the game I’ve been working on, we’d like to have a small train/trolly type platform that the player should be able to get on and off of on will, and be able to walk around inside it while it’s moving.

For a basic, one-direction train, this is pretty easy. I simply issued a Transform.Translate to both train and player, and it worked flawlessly. Along with a trigger box to keep track of if the player was inside or not. If the player is inside, the player moves with the platform. If the player jumps off, the platform goes on ahead, and the player gets left behind.

But, we need the trolley to be able to go up hills and around corners. Since the player is in direct control of where the trolley turns, and how fast it’s going, we decided to go with some triggers… a trigger at key points on turns to tell the trolley when to turn and by how much. The trolley itself moves just fine up the test hill we have, but we’re having problems keeping the player on top of the platform.

One of the main issues is that the trolley uses a local move command (to simply move forward or backward) to simplify it. However, since the player is able to walk around on the trolley, this can’t be given to the player, so we’ve tried two different things:

1: We tried to give the player global move commands in an attempt to have him keep up with the trolley. This would work fine if we could get the math to work for us. The idea was to take the angle the trolley was facing and give the player move commands based on that angle. However, I’m unsure of how to do the math. I have a basic script that works (works as in, taking the angle of the trolley and giving the player a direction and speed based on that angle), but since the math is wrong, the player gets left behind each time the trolley goes up the hill.

2: A parent/child relationship that’s maintained so long as the player is boarded on the trolley. This works, except that since the trolley’s direction is changing depending on where in the level it is, the player will almost always rotate to face the direction the trolley is facing the moment he touches the trolley. I don’t mind if the player rotates with the trolley afterward (if anything, that’d be kind of nice), but the player suddenly rotating in this manner at the very instant of entry is unforgivable (makes it very difficult to board the trolley, if nothing else).

I’d like to make note that we plan on there being multiple trolleys that the player should be able to get on and off throughout the level, so a permanent parent/child relationship would be out of the question (I’d think so, anyway).

What I’d like to ask, is if there are any suggestions on how to make either of these ideas work, or if there are suggestions on other ideas.

If there’s a way to basically overwrite the very first frame of rotation, upon entering a parent/child relationship, that would be grand. I’ve looked around on the forums, but couldn’t find what I was looking for. I don’t want to stop the player from rotating with the trolley entirely, simply to not cause the player to instantly rotate to face the front of the trolley whenever he tries to board it.

Both my partner and I feel like we’re missing something really basic. Could anyone help point us in the right direction?

Use parenting but instead of modifying his localRotation, modify his rotation.

This will override the parenting settings and allow him to maintain a custom rotation but move with a localPosition so he moves with the trolley still.

(maybe make him slowly LERP to desired rotation)

You can also add/remove parenting with tranform.parent. So that you can swap it from null (it’s on it’s own) to any particular trolley it gets on.

You could use BoxCollider triggers to change parenting on enter/exit for each trolley.

I -tried- this, maybe I got the syntax wrong. I’ll do a little more research on this and try it again.

Yup, I already have it set up this way. This part actually works pretty good.

Thanks for the response, I’ll try your suggestion.

One thing that could be causing the pop is that rotation may not update on parenting like position does.

Try:

Vector3 rotation = transform.eulerAngles;
transform.parent = trolley.transform;
transform.eulerAngles = rotation;

Or something along those lines.
That way you can enforce that rotation remains unchanged upon parenting.

Can you explain this line to me, please?

I understand the concept behind the lines you provided, but this line returns a “Expected ; at end of line” error upon compile, even though a semicolon is provided. I know transform.eulerAngles, but Vector3 rotation is new to me.

It’s C# code.

you would probably want

var rotation : Vector3 = transform.eulerAngles;

if you are using Unityscript.

Okay, thanks for clarifying.

Unfortunately, it doesn’t seem to work. The player continues to rotate whenever he touches the trolley. I’ve noticed that he rotates exactly 90 degrees to the left, with or without the script you provided.

I set up a print to make sure the variable was being set in the first place, and it is.

Does any script reference:
localRotation
localEulerAngles

of the Player class(either setting the value, or getting it as a reference)?

It could be that your control scripts in other places are manipulating it after you try to set it.

Also is the value you checked if eulerAngles, 1 frame after you set it’s parent, is still what you set it to when you parented it?

It could also be that some of the Character Controller scripts are manipulating local and not global rotations.

I checked to make sure the player controller wasn’t using any local commands, and it was not.

I then checked the player rotation before and after the parenting, and the values return the same. This agrees with the inspector view, which states that the player rotation does not change. The inspector view also says that the player rotation does not change even before the script, even though the player rotates 90 degrees to the left.

This makes it seem like the script works, but isn’t working as intended.

Perhaps if I caused the player to simply rotate 90 degrees to the right? it would seem to work in this particular situation, but I have no idea if the 90 degrees to the left would change if the trolley were further down the track and rotated itself…

The Inspector should actually change.

If the Player is at 90 degrees before parenting and the train is at 45 degrees, then the Player after parenting at the same angle should read (90 - 45) or 45 degrees.

This is because the Inspector displays local values.

This seems odd, then… because no matter what angle I approach the train from, the player rotates 90 degrees to the left, and the inspector view states that the angle is the same.

I tried forcing the player to rotate 90 degrees to the right… Doing a print for the player’s eulerAngles tells me that the player’s angles changed, but other than that, there is no difference: inspector view still states the player rotation did not change, and a rotation 90 degrees to the left is made.

I -believe- I fixed it.

I remembered you mentioned looking for instances of localRotation in the script, and I searched the player controller for it… but I had forgotten about the mouseLook script.

At first, I remove all instances of localRotation and replaced them with just rotation, and it seemed to kind of/sort of work. The player itself rotated, and touched the trolley fine, but the camera behaved oddly.

I returned the very last instance of rotation to its original localRotation, and it -seems- to work, now.

This -somehow- fixed a ‘drifting’ issue where the player gravity took over on the hill, causing the player to drift a little forward when going up the hill; however, the player stays right where he’s supposed to, now.

Thanks for your help.