Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
14
Question by rocket5tim · Nov 24, 2009 at 01:27 AM · animationphysicscharactercontrollermoving-platformmove-with-moving-platform

CharacterController falls through or slips off moving platforms

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.

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ecameracci · Jul 23, 2015 at 11:17 PM 0
Share

I found this video helpful https://www.youtube.com/watch?v=U1Uk$$anonymous$$w12pQo

avatar image Michiyuki13 · Oct 15, 2015 at 09:45 AM 0
Share

Hey guys, that simple JS parenting script worked in my case, thanks!!! :D

However, I have noticed that it works much better with my animations imported from $$anonymous$$aya (or perhaps it's the mesh itself,and the trigger box generated from that mesh (it's just a duplicate)). The collider is set to convex,otherwise it wouldn't let me check 'is trigger' box.

Another moving platform was created with a Unity's cube and the trigger cube was done the same way,uses animations created with $$anonymous$$echanim, and whenever my character steps inside the trigger zone, its feet start sinking in a bit... I'm using that standard Ethan char to run around the level.

$$anonymous$$aybe this observation can help somebody out with the similar issue. I guess I need to test with another object imported from $$anonymous$$aya.

A programmer friend is going to help me with this in the next couple of days,I know parenting is not the best solution,but the other ones are too complicated for me (game artist here xD). If he does something cool,I'll post it here!

9 Replies

· Add your reply
  • Sort: 
avatar image
24
Best Answer

Answer by runevision · Nov 24, 2009 at 10:37 AM

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.

  • It supports moving in any direction (vertically, horizontally, diagonally, you name it).

  • It works no matter if the platforms are moving through scripting, or through animation. If done by animation, the Animation component of the platform must have the checkbox "Animate Physics" turned on to avoid glitches.

  • I have enhanced it here so that it also supports rotating platforms, but you can leave out that part if you don't need or want it.

  • It does not rely on making the platform a parent to the character, as that can have certain disadvantages.

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.

// Moving platform support private var activePlatform : Transform; private var activeLocalPlatformPoint : Vector3; private var activeGlobalPlatformPoint : Vector3; private var lastPlatformVelocity : Vector3;

// If you want to support moving platform rotation as well: private var activeLocalPlatformRotation : Quaternion; private var activeGlobalPlatformRotation : Quaternion;

function Update () {

 // Perform gravity and jumping calculations here
 ...

 // Moving platform support
 if (activePlatform != null) {
     var newGlobalPlatformPoint = activePlatform.TransformPoint(activeLocalPlatformPoint);
     var moveDistance = (newGlobalPlatformPoint - activeGlobalPlatformPoint);
     if (moveDistance != Vector3.zero)
             controller.Move(moveDistance);
     lastPlatformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.deltaTime;

     // If you want to support moving platform rotation as well:
     var newGlobalPlatformRotation = activePlatform.rotation * activeLocalPlatformRotation;
     var rotationDiff = newGlobalPlatformRotation * Quaternion.Inverse(activeGlobalPlatformRotation);

     // Prevent rotation of the local up vector
     rotationDiff = Quaternion.FromToRotation(rotationDiff * transform.up, transform.up) * rotationDiff;

     transform.rotation = rotationDiff * transform.rotation;
 }
 else {
     lastPlatformVelocity = Vector3.zero;
 }

 activePlatform = null;

 // Actual movement logic here
 ...
 collisionFlags = myCharacterController.Move (calculatedMovement);
 ...

 // Moving platforms support
 if (activePlatform != null) {
     activeGlobalPlatformPoint = transform.position;
     activeLocalPlatformPoint = activePlatform.InverseTransformPoint (transform.position);

     // If you want to support moving platform rotation as well:
     activeGlobalPlatformRotation = transform.rotation;
     activeLocalPlatformRotation = Quaternion.Inverse(activePlatform.rotation) * transform.rotation; 
 }

}

function OnControllerColliderHit (hit : ControllerColliderHit) { // Make sure we are really standing on a straight platform // Not on the underside of one and not falling down from it either! if (hit.moveDirection.y < -0.9 && hit.normal.y > 0.5) { activePlatform = hit.collider.transform;
} }

Notes:

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.

Comment
Add comment · Show 14 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image rocket5tim · Nov 24, 2009 at 05:07 PM 0
Share

I added the code from above, and so far I'm still falling thru the platform - same result as without the code. I also tried a code driven platform (moving the transform in FixedUpdate) but he falls thru that too exactly the same.

Perhaps there's a problem with the way my platform is setup? In both setups, I'm simply using a Box Collider for collision (the player collides just fine so long as the box isn't moving).

Or perhaps the code is fighting with my gravity code?

if (!controller.isGrounded) moveDirection.y -= gravity * Time.deltaTime;

avatar image rocket5tim · Nov 25, 2009 at 04:48 AM 0
Share

So after working on this for several hours today, I finally tried commenting out the activePlatform = null; line. And would you believe, without that line my character no longer falls thru the platform? I can't understand it -- that line is clearly in the 2D Gameplay Tutorial in the same location as where I had it. Weird.

avatar image runevision ♦♦ · Nov 25, 2009 at 09:01 AM 0
Share

It's hard to say why it doesn't work in your case. All I can say is that it is very important that the .$$anonymous$$ove function on the CharacterController is called in the location shown in the code above. That is, after activePlatform is set to null and before the last code block with the $$anonymous$$oving Platform Support comment.

avatar image rocket5tim · Nov 25, 2009 at 07:05 PM 0
Share

Well, like I said, it works fine if I remove the activePlatform = null; line. $$anonymous$$aybe someone can chime in on what purpose that line has in the script? In any case, this appears to be the most useable solution at this point.

avatar image runevision ♦♦ · Nov 26, 2009 at 09:03 AM 0
Share

If you don't set activePlatform = null; then the character should still be affected by the platform movement after having jumped off it, until you land on a new surface.

Show more comments
avatar image
7
Best Answer

Answer by Jaap Kreijkamp · Nov 24, 2009 at 07:33 AM

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 :-)

using UnityEngine; using System.Collections;

/** Helps keeping charactercontroller entities nicely on the platform Needs a Collider set as trigger in the gameobject this script is added to works best if collider is bit smaller as platform but extends quite a lot (say .5m or so) above the platform, As the platform possibly already has a normal collider the easiest way is to add a GameObject to the platform, give it a trigger collider and add this script. The yOffset is the vertical offset the character should have above the platform (a good value to start with is half the y value of the Collider size). */ public class JKeepCharOnPlatform : MonoBehaviour {

 // helper struct to contain the transform of the player and the
 // vertical offset of the player (how high the center of the
 // charcontroller must be above the center of the platform)
 public struct Data {
     public Data(CharacterController ctrl, Transform t, float yOffset) {
         this.ctrl = ctrl;
         this.t = t;
         this.yOffset = yOffset;
     }
     public CharacterController ctrl; // the char controller
     public Transform t; // transform of char
     public float yOffset; // y offset of char above platform center
 };

 public float verticalOffset = 0.25f; // height above the center of object the char must be kept

 // store all playercontrollers currently on platform
 private Hashtable onPlatform = new Hashtable();

 // used to calculate horizontal movement
 private Vector3 lastPos;

 void OnTriggerEnter(Collider other) {
     CharacterController ctrl = other.GetComponent(typeof(CharacterController)) as CharacterController;

     // make sure we only move objects that are rigidbodies or charactercontrollers.
     // this to prevent we move elements of the level itself
     if (ctrl == null) return;

     Transform t = other.transform; // transform of character

     // we calculate the yOffset from the character height and center
     float yOffset = ctrl.height / 2f - ctrl.center.y + verticalOffset;

     Data data = new Data(ctrl, t, yOffset);

     // add it to table of characters on this platform
     // we use the transform as key
     onPlatform.Add(other.transform, data);
 }

 void OnTriggerExit(Collider other) {
     // remove (if in table) the uncollided transform
     onPlatform.Remove(other.transform);
 }

 void Start() {
     lastPos = transform.position;
 }

 void Update () {
     Vector3 curPos = transform.position;
     float y = curPos.y; // current y pos of platform

     // we calculate the delta
     Vector3 delta = curPos - lastPos;
     float yVelocity = delta.y;

     // remove y component of delta (as we use delta only for correcting
     // horizontal movement now...
     delta.y = 0f;

     lastPos =curPos;

     // let's loop over all characters in the table
     foreach (DictionaryEntry d in onPlatform) {
         Data data = (Data) d.Value; // get the data
         float charYVelocity = data.ctrl.velocity.y;

         // check if char seems to be jumping
         if ((charYVelocity &lt;= 0f) || (charYVelocity &lt;= yVelocity)) {
             // no, lets do our trick!
             Vector3 pos = data.t.position; // current charactercontroller position
             pos.y = y + data.yOffset; // adjust to new platform height
             pos += delta; // adjust to horizontal movement
             data.t.position = pos; // and write it back!
         }
     }
 }

}

Comment
Add comment · Show 9 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image rocket5tim · Nov 24, 2009 at 05:09 PM 0
Share

This sounds like a promising solution, but could you provide a more detailed example? Even some psudo code would be helpful.

avatar image rocket5tim · Nov 25, 2009 at 04:14 PM 0
Share

This works great for keeping the player from falling thru an animated platform (I haven't tried it with a code driven platform yet). I had to find the right balance between the verticalOffset, gravity, and even the height of the trigger to keep the player from bouncing as the platform moved up/down. Thanks!

avatar image rocket5tim · Nov 25, 2009 at 06:37 PM 0
Share

While it does keep the player from falling thru, there's an issue: If I adjust the verticalOffset so that the character doesn't "bounce" when the platform is moving UP, then he cannot jump from the platform. $$anonymous$$y jump button checks to see if isGrounded = true, if it's not then he can't jump. There's something about being pinned exactly to the center of the trigger that makes the character think it's not grounded. $$anonymous$$aybe the collider is being pulled slightly thru the elevator collision? If I set verticalOffset so that the character "bounces" a little when the platform is moving he can jump off.

avatar image Jaap Kreijkamp · Nov 26, 2009 at 01:43 AM 2
Share

Ah, you want to jump! How eighties! winks at DragonAge where your char can't even jump a 10 cm ledge. Edited the code in my post to handle jumping, just copy/paste over old code and it should work. Note that the y offset must be high enough that the char's collider isn't through the platform, but preferably low enough that the colliders skin is. So try adding a cm of 2 if jumping doesn't work when platform is going up.

avatar image Fubiou · Aug 06, 2011 at 02:12 PM 0
Share

Hi, I am using a script based on ThirdPersonController script, I tried to add this solution but failed miserably, something worked but the character appeared in a place that wasnt the place I seted, and he was sliding the platform. $$anonymous$$y original solution was to parent it, worked very well but I am afraid of the physical consequences of such act. Please, can you give me a hand? to improve the ThirdPersonController with this platform solution?

Sorry about my noobish and my terrible english!

Show more comments
avatar image
9

Answer by Codayus · Mar 16, 2010 at 12:59 AM

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:

  • Create a new cube game object which is a child of your elevator platform.
  • Give the cube a collider component and set it as a trigger
  • Adjust the size of the cube so that it more-or-less covers the entire floor of your elevator. Y-axis doesn't much matter, but it's important that anyone standing on the platform must be inside the trigger.
  • Disable the mesh renderer component.
  • Create a new .js script with the following code in it and add it to the trigger collider:

    function OnTriggerEnter (other : Collider) { other.transform.parent = gameObject.transform; } function OnTriggerExit (other : Collider) { other.transform.parent = null; }

    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. :)

    Comment
    Add comment · Show 11 · Share
    10 |3000 characters needed characters left characters exceeded
    ▼
    • Viewable by all users
    • Viewable by moderators
    • Viewable by moderators and the original poster
    • Advanced visibility
    Viewable by all users
    avatar image Deise · May 12, 2010 at 01:32 PM 0
    Share

    thank you! This way is simple but very effective. It is ideal for me because I did not have to change anything else.

    avatar image 0V3RWR173D · May 29, 2010 at 04:57 AM 0
    Share

    Thank you very much for the advise, ALTHOUGH I have encountered a problem. I'm not sure if you are an expert at unity3d but I have a firstpersonplayer with weapons. The weapons are attached to the main camera but when I step on the platform, it does not move correctly with the camera. It will not stay in an exact position relative to the camera. Do you have any ways of fixing this kind of problem?

    avatar image James 2 · Jul 27, 2010 at 10:52 PM 0
    Share

    I looked forever to find how to do this!!! You made it so simple! Thanks!

    avatar image munaeem · Nov 10, 2012 at 09:36 PM 0
    Share

    problem !! my 3d player looks liked he has been just came out from toilet or been squeezed but a roller truck.

    avatar image moinchdog · Nov 11, 2012 at 01:23 AM 1
    Share

    in the script make sure you reset the players transform.localScale to 1,1,1 or else it will be squished

    Show more comments
    avatar image
    7

    Answer by Brian-Kehrer · Nov 24, 2009 at 02:45 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.

    Comment
    Add comment · Show 2 · Share
    10 |3000 characters needed characters left characters exceeded
    ▼
    • Viewable by all users
    • Viewable by moderators
    • Viewable by moderators and the original poster
    • Advanced visibility
    Viewable by all users
    avatar image Jessy · May 15, 2010 at 04:09 AM 0
    Share

    I have code that moves a Character Controller to another place on the map, and it may be inside of a collider that it should ins$$anonymous$$d be walking on, afterwards, so it can then fall through. The teleportation happens in OnTriggerStay(), so I don't think there's anything to be helped in terms of FixedUpdate(). Any tips? You think the solution is an OnTriggerStay() in the floors that it can teleport into, which pushes the Controller out far enough so that it's on top again?

    avatar image Brian-Kehrer · May 17, 2010 at 04:30 PM 0
    Share

    Is OnTriggerStay even being called? If you teleport in, it might get messed up. What I finally ended up doing was very complicated. I used a dummy rigidbody specifically to catch that case. Obviously if you are very far off, it will still fail, but it might catch close cases.

    avatar image
    1

    Answer by venkspower · May 04, 2012 at 04:17 AM

    Why don't you just make the CharacterController as the child to the floor of the elevator. That solves it. Simple!

    Comment
    Add comment · Show 1 · Share
    10 |3000 characters needed characters left characters exceeded
    ▼
    • Viewable by all users
    • Viewable by moderators
    • Viewable by moderators and the original poster
    • Advanced visibility
    Viewable by all users
    avatar image WhendricSo · Nov 10, 2016 at 09:08 AM 0
    Share

    No, it doesn't. Perhaps actually testing your solution ins$$anonymous$$d of blurting out the first thing that pops into your head would be more useful.

    • 1
    • 2
    • ›

    Your answer

    Hint: You can notify a user about this post by typing @username

    Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

    Follow this Question

    Answers Answers and Comments

    23 People are following this question.

    avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

    Related Questions

    Character Contoller with Ragdoll 1 Answer

    Make a Platform push a character controller? 2 Answers

    how can i make my character run up ramps like in sonic, fancy pants or even line rider? 1 Answer

    Character Controller + Animation Not Working As It Should 0 Answers

    What is the easiest way to push a character controller with a moving platform? 0 Answers


    Enterprise
    Social Q&A

    Social
    Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

    Footer

    • Purchase
      • Products
      • Subscription
      • Asset Store
      • Unity Gear
      • Resellers
    • Education
      • Students
      • Educators
      • Certification
      • Learn
      • Center of Excellence
    • Download
      • Unity
      • Beta Program
    • Unity Labs
      • Labs
      • Publications
    • Resources
      • Learn platform
      • Community
      • Documentation
      • Unity QA
      • FAQ
      • Services Status
      • Connect
    • About Unity
      • About Us
      • Blog
      • Events
      • Careers
      • Contact
      • Press
      • Partners
      • Affiliates
      • Security
    Copyright © 2020 Unity Technologies
    • Legal
    • Privacy Policy
    • Cookies
    • Do Not Sell My Personal Information
    • Cookies Settings
    "Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
    • Anonymous
    • Sign in
    • Create
    • Ask a question
    • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Explore
    • Topics
    • Questions
    • Users
    • Badges