Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

CharacterController help with moving platforms

Discussion in 'Scripting' started by antenna-tree, Dec 24, 2005.

  1. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    I'd love some suggestions for how to use CharacterController in a third person platformer. I've spent most of the week creating a third person controller script for a platforming portion of my game and I've hit a wall trying to deal with moving platforms. I want the player to be able to jump onto a moving platform and then move with the platform. Right now the platform just slips right out from under the player as it moves in XZ, and the player falls right through if moving in Y.

    I'm guessing I can solve my problem with some OnControllerColliderHit mechanism having the player snap to the contact.point, but I'm completely out of my depth trying to get it to work (and I mean completely, I can't get anything to trigger with this function).

    PS - Is it be possible to use any collider shape for CharacterController instead of the default capsule?

    PPS - I forgot to ask if there could be a better description of how "motion" works in CharacterController.Move. I got it to finally work properly , and it might be obvious to more seasoned programmers, but I'm still scratching my head over how to use it any other way than what is used in the FPSWalker example...transform.TransformDirection * Time.deltaTime.
     
  2. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    There seems to be a bug in the Controller hit callbacks, where it sometimes doesn't get called.

    So instead i made you a package that is using another trigger as the child of the first person controller to track collision with platforms.
    See the attached package, it contains two scripts and an example scene.


    You might want to change the OnTriggerEnter/Exit functions to filter what objects may be platforms.

    A couple of notes:
    1. Make moving platforms move at fixed framerate. If you are using animations there is a checkbox called Play fixed framerate, which you should check.

    Regarding your questions:
    OnControllerColliderHit seems buggy at the moment. Sorry we didn't catch this in the beta test. We will fix this soon.

    There is no way to change to another type of collider.
    The CharacterController is very specialized for first person controllers at the moment. We might support more shapes later on but that might take a while.

    Basically the Move function just carries out a movement you give it.
    The movement is given in world space. The Controller only constrains the carried out motion by collisions and slides on the sides of walls etc like in your standard quake 3 fps controls. And does stair stepping.

    Merry christmas.
     

    Attached Files:

  3. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    Wow! Thank you so much for that excellent Christmas present :D

    It worked like a charm once I properly spliced it into my script. It doesn't work for platforms moving up and down though (more precisely up) as the player still falls through, but I'm going to try a workaround where the player is placed a very small amount above the platform so the collision will still trigger as the platform moves upward.

    [Edit] I just noticed that if you keep the player continuously moving on the platform it will not fall through. Weird, I can't figure out what is triggering differently to make this happen, but if I can I don't have to do my cheesy workaround :wink:

    Thanks again Joachim and Merry Christmas.
     
  4. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Hmm. Could be that your script continously tries switching between being airborne and not. Or maybe you have set the min Move distance in the controller to something else than zero.
     
  5. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    Sorry, I should've mentioned that this happens with the scene/scripts that you created unchanged if you add a platform that moves up and down.
     
  6. harold@shosho

    harold@shosho

    Joined:
    Dec 30, 2005
    Posts:
    4
    Hi Joachim, could you repost the file as a .zip, the current download doesn't seem to be understood correctly by Safari / Firefox / OSX10.4. The downloaded file opens up 3 folders without meaningful content and 'random' filenames. (I remember reading a post somewhere else on the forum with a question why .zip was used since the unitypackage was essentialy the same, so maybe i'm missing something?)

    thanks in advance

    PS since this is my first post as a new user, just wanted to say I'm very impressed by Unity and hope to use it as a prototype / storytelling tool. I've always worked in Macromedia Director so I'm trying to learn C# asap and the topic of this thread was exactly the problem I was trying to solve in my first scene.
     
  7. NicholasFrancis

    NicholasFrancis

    Joined:
    Apr 8, 2005
    Posts:
    1,587
    Hmm... From safari, try right-clicking, select Download Linked File.

    This will give you 'fps_platforms_181.unitypackage.txt'. Get Info on the file, and in the 'Name and Extension' remove the .txt (so it ends in UnityPackage).

    The from Unity, do an Assets->Import Package to get it into your current project.

    Welcome aboard. Hope you like our tool!
     
  8. harold@shosho

    harold@shosho

    Joined:
    Dec 30, 2005
    Posts:
    4
    Thank you nicholas, this works. (I tried unzipping before importing).
     
  9. freid

    freid

    Joined:
    Mar 31, 2007
    Posts:
    60
    Hi guys,

    I'm trying that exemple and it doesn't seem to work anymore. The character is just falling, the platforms are moving, but the character isn't.
    Is it me or what ? (I'm using pro 1.62f1)

    Freid
     
  10. dacloo

    dacloo

    Joined:
    Jun 30, 2005
    Posts:
    469
    I don't know either, I was looking for this functionality!

    the onTriggerEnter seems to fire, but the position isn't taken from the platform so it seems.
     
  11. Jonathan Czeck

    Jonathan Czeck

    Joined:
    Mar 17, 2005
    Posts:
    1,713
    For all interested, I just found that kicking up characterController.stepOffset fixes that. That obviously has side effects, though, and I haven't gotten a solution going quite yet.

    -Jon
     
  12. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    Wow, what an old thread! It's surprising to me that no one has come up with a rock solid solution yet to 3rd person characters interacting with moving up/down platforms. I thought Dacloo's parenting solution was pretty good, but he mentioned some weird transformation skewing. A little bird told me that there's a 3D platformer tutrorial in the works... hopefully this issue will be addressed there?
     
  13. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,777
    Here's a thought: Create a trigger collider that goes just above the platform. Anytime an object with either a rigidbody or charactercontroller overlaps it, move it by the same amount that the platform is moving that frame.
     
  14. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Is there seriously no better solution for this "moving platform" problem yet?

    This solution really wont work nicely with what I am doing.
     
  15. Jonathan Czeck

    Jonathan Czeck

    Joined:
    Mar 17, 2005
    Posts:
    1,713
    Here's one. First, add these vars to your character script:

    Code (csharp):
    1. private var activePlatform : Transform;
    2. private var activeLocalPlatformPoint : Vector3;
    3. private var activeGlobalPlatformPoint : Vector3;
    4. private var lastPlatformVelocity : Vector3;
    Then add this code right before you Move() on your character controller inside of Update():

    Code (csharp):
    1.     if (activePlatform != null) {
    2.         var newGlobalPlatformPoint = activePlatform.TransformPoint(activeLocalPlatformPoint);
    3.         var moveDistance = (newGlobalPlatformPoint - activeGlobalPlatformPoint);
    4.         transform.position = transform.position + moveDistance;
    5.         lastPlatformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.deltaTime;
    6.     }
    7.     else {
    8.         lastPlatformVelocity = Vector3.zero;   
    9.     }
    10.    
    11.     activePlatform = null;
    12.  
    Then put this code right after you call Move() :
    Code (csharp):
    1.     if (activePlatform != null) {
    2.         activeGlobalPlatformPoint = transform.position;
    3.         activeLocalPlatformPoint = activePlatform.InverseTransformPoint(transform.position);
    4.     }
    5.  
    Then add this OnControllerColliderHit function, that will get called on a collision when Move() was called:

    Code (csharp):
    1. function OnControllerColliderHit (hit : ControllerColliderHit)
    2. {
    3.     if (hit.moveDirection.y > 0.01)
    4.         return;
    5.    
    6.     // Make sure we are really standing on a straight platform
    7.     // Not on the underside of one and not falling down from it either!
    8.     if (hit.moveDirection.y < -0.9  hit.normal.y > 0.9)
    9.     {
    10.         activePlatform = hit.collider.transform;   
    11.     }
    12. }
    (Or if you already have OnControllerColliderHit, add the code within to the end of it, or whatever makes sense for the situation.

    That should be it, in theory. :) This will get explained better in a different venue in the future.

    -Jon
     
  16. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Thanks Jon... but again this wont work... as i am using physics to control my object.... force and velocity, so I cant see how inot nicely. Will totally disturbe my objects movement.
     
  17. Jonathan Czeck

    Jonathan Czeck

    Joined:
    Mar 17, 2005
    Posts:
    1,713
    Ahh, well the topic has been about the CharacterController, not Rigidbodies, so I only assumed. I haven't done moving platforms for rigidbody characters, but I'm sure it's doable, and I'd guess more straightforward than CharacterController.

    Cheers,
    -Jon
     
  18. Ethan

    Ethan

    Joined:
    Jan 2, 2008
    Posts:
    501
    i solved it that way too, but anyway i dont know if it works on low fps machines ... anyone has better solutions for that problem?

    i also tried to put a rigidbody on the platforms and take oncollisionenter, but my player just has an charactercontroller and it doesnt work at all.
    the other thing is that theres a force added to the platform.rigidbody on collision = very bad.

    Code (csharp):
    1. function Update()
    2. {
    3.     moveSpeed = speed*Time.deltaTime;
    4.     moveDelta = moveVector * moveSpeed;
    5.  
    6.     if(goUp)
    7.     {
    8.         transform.position+=moveDelta;
    9.         curDist+=moveSpeed;
    10.         if(playerStandsOnMe)
    11.             player.position+=moveDelta;
    12.     }
    13.     else
    14.     {
    15.         transform.position-=moveDelta;
    16.         curDist-=moveSpeed;
    17.         if(playerStandsOnMe)
    18.             player.position-=moveDelta;
    19.     }
    20.        
    21.    
    22.        
    23.     if(curDist<0.0)
    24.         goUp=true;
    25.     if(curDist>distance)
    26.         goUp=false;
    27. }
    28.  
    29. function OnTriggerEnter()
    30. {
    31.     playerStandsOnMe=true;
    32. }
    33. function OnTriggerExit()
    34. {
    35.     playerStandsOnMe=false;
    36. }
     
  19. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    If you use rigidbodies this is as simple as making the platform be a kinematic rigidbody and turning the animation component's animate physics flag on. If you move it from code you just need to use rigidbody.MovePosition and rigidbody.MoveRotation from FixedUpdate instead of transform.position. This way the kinematic rigidbody will apply friction and velocity to rigidbodies sitting on top of it.


    If you are using the character controller, the third person tutorial has a script that handles platforms perfectly fine.
     
  20. Ethan

    Ethan

    Joined:
    Jan 2, 2008
    Posts:
    501
    you mean the "3D Platform Game" lerpz?
    i hope i didnt miss that one, but i cant find moving platforms in there.
    what is the scripts name?
     
  21. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    The Third Person Controller.js script takes care of it. You just need to set a special tag on a animated surface.
     
  22. tone

    tone

    Joined:
    Aug 26, 2005
    Posts:
    26
    The old unitypackage offered here gave a simple "bonk" sound when I tried to import it into 2.5.0

    Is it not possible to have the first person controller interact with a physic material to obtain a desired friction?

    Should I also be using a Rigidbody?

    IMO, these behaviors are fairly core. I want to be able to walk around a ship that is moving, and a natural treatment of this that doesn't impose a greater burden on authoring than assigning a Physic Material to deck and shoe sole would be wonderful.

    tone