In a level of a 3D FPS I'm making, I have several floating pillars that move up and down (the x and z positions are always the same). When the player stands on one of the pillars, the motion is incredibly jerky going up, but smooth going down. I think the player is sinking into the pillar slightly and then catching up.

I've tried different colliders, all sorts of combinations with rigidbodys and character controllers. I've tried setting the pillar as a parent of the character and then having the player hover slightly. I've just hit a brick wall and would appreciate an outside perspective. Here's my code just in case the issue is in there.

Player movement

 public float walkSpeed = 6.0F;
 public float runSpeed = 10.0F;
 public float jumpSpeed = 8.0F;
 public float gravity = 20.0F;
 private Vector3 moveDirection = Vector3.zero;

 void FixedUpdate(){
     CharacterController controller = GetComponent<CharacterController>();

         moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
         moveDirection = transform.TransformDirection(moveDirection);
         moveDirection *= walkSpeed;
         if (Input.GetButtonDown("Jump")){
             moveDirection.y = jumpSpeed;

         if (Input.GetButton("Sprint")){
             walkSpeed = runSpeed;
             walkSpeed = 6.0F;

     moveDirection.y -= gravity * Time.deltaTime;
     controller.Move(moveDirection * Time.deltaTime);

 void OnCollisionStay(Collision hit) {
     if (hit.gameObject.tag == "Column") {
         transform.parent = hit.transform;
     } else {
         transform.parent = null;

Pillar movement

 float height;
 float speed;
 Vector3 start;
 Vector3 end;
 Vector3 startOrEnd;
 void Start(){
     speed = 0.01F;
     start = new Vector3(gameObject.transform.position.x, gameObject.transform.position.y, gameObject.transform.position.z);

 void Update () {

 float randomNumber(float min, float max){
     float number = Random.Range(min, max);
     return number;

 void motionControl(float speed){
     if (gameObject.transform.position == start) {
         end = new Vector3(gameObject.transform.position.x, randomNumber(0, 10), gameObject.transform.position.z);
         startOrEnd = end;
     }else if (gameObject.transform.position == end) {
         startOrEnd = start;
     gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, startOrEnd, speed);
  • \$\begingroup\$ Some basic stuff : Did you set your Rigidbody collision detection to continuous? \$\endgroup\$
    – TobiasW
    Feb 1, 2017 at 9:12

2 Answers 2


My suggestion is to have a variable in your character class that holds a reference to whatever object the character is on and then have all of the characters movement be relative to that object as long as he is on that surface.


From the code it looks like you're probably right: The player is sinking into the collider and then bouncing back up again. It looks like this may be because you're moving the player too far down when you set you're moveDirection.y.

Instead, I'd use RayCasting to determine whether or not to move the player down (and by how far). Something like this should do it (I'm not in a position to test at the moment)

float distance = gravity * Time.deltaTime;
RaycastHit hit;
if (Physics.Raycast(new Vector3(transform.position.x, controller.bounds.min.y, transform.position.z), -Vector3.up, out hit, distance)) {
     distance = hit.distance;
moveDirection.y -= distance;
  • \$\begingroup\$ Sorry for not replying sooner, I'll give it a shot as soon as I can, thanks :) \$\endgroup\$ Feb 4, 2017 at 0:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .