I made an animated elevator/platform by creating an animation in Maya and then attached a box collider as a child of the animation so that they move together. However my player uses the CharacterController and it falls thru the box collider (floor) as soon as the elevator starts animating*.
There are a couple of threads on the unity forum (here and here), but one of them is very old and neither of them has current or clear explanations of why the CharacterController has issues with attaching to moving objects and how best to solve the problem.
*note if I keep the player moving while the elevator is in motion, he does not fall thru the floor - he only falls thru when standing still. Also he's more likely to fall thru while the elevator is moving up than down.
The 2D Gameplay Tutorial has a character that can stay perfectly on platforms. The needed code, derived from that tutorial, is below.
This solution is rather flexible.
Note that the below is NOT a complete script. It's only some code fragments needed for making the character stay on platforms. For a complete script, see the 2D Gameplay Tutorial.
The lastPlatformVelocity variable is not used for anything in the code above, but you can use it in the jumping logic to make the jumping speed get the inertia from the moving platform, such that the character is jumping relative to the platform reference and not to the global reference. You could also calculate a lastPlatformRotationalVelocity to get the rotational inertia from the platform when jumping, but for most games this would be overkill and only confuse the user.
Connect a script to the platform that detects if someone is on it, in LateUpdate adjust the y pos to the new y pos of the platform.
EDIT: I added an example implementation that should keep any character controller happily on a platform. It's a bit more complex than just adjusting the y position as it also handles horizontal movement and works with more than one char on the platform (so it maintains a list of all players on the platforms).
The platform probably has already a collider so you can't walk through it and stuff, to use the script, add a child GameNode to the platform, give it a trigger collider that's slightly smaller as the platform and extends a bit above the platform. Add the script and adjust the Vertical Offset var. If you need an example project, let me know.
EDIT2: Made a few modifications to handle jumping :-)
There's several ways to do this of various complexity, depending on what you need. For a simple elevator, you probably want the simplest and easiest way - which would be as follows:
What's happening here is fairly obvious. When anything enters your trigger (like, for example, a CharacterController), it becomes parented to it. Anything parented to the trigger will move when the elevator does. When you step out of the trigger, the parent link is removed. Simple. :)
answered Mar 16, 2010 at 12:59 AM
The CharacterController is very simple in function.
Every FixedUpdate it applies the Move() function to determine where it should go. Typically, gravity is assigned, so it always attempts to move down. The Move() function detects objects between the controllers current and intended positions, and will stop moving when a collision is detected. Of course it's much more complex than that, but that is the idea.
However, if between calls to Move() in FixedUpdate, you move the ground above the current position of the CharacterController, the check the CharacterController performs will say "There is nothing below me" and so it will fall. Makes sense.
Now, onto fixing it.
First, to make things behave well, one trick is to make sure all objects the CharacterController interact with are also being adjusted in FixedUpdate. Animations will run in Update. I would suggest animating the platform in code rather than in Maya, and also in the FixedUpdate loop. While there are ways to make what you suggest work, I think it will be far less complicated in this manner.
Depending on your game logic, there are a few options. Personally I dislike parenting the CharacterController to other objects because it can result in some strange behavior. Instead, create some code to tell the CharacterController when it is interacting with a moving platform, and allow the moving platform to tell the CharacterController how far it should move this frame, and then reposition the CharacterController manually.
answered Nov 24, 2009 at 02:45 AM