# Question CharacterController movement with platform

Discussion in 'Physics' started by mancj, Oct 3, 2023.

1. ### mancj

Joined:
Aug 2, 2015
Posts:
1
Hello everyone.
I'm using asset library for character's movement. It uses Character Controller component for the player movement.
Now i want to add to my game some moving platforms, so that player will be able to jump to that platforms and move.
I tried two approaches
The first one is to make player's game object child of moving platform, but it doesn't work, i guess it's because Character Controller's position is changing in Update method.
The second approach is to add platform's velocity to the Character Controller's calculated velocity, but now it moves faster than platform. I know that there are some conditions related to the calculation logic, but my knowledge of mathematics is not enough to fix this.
Please help me to understand how to properly calculate and mix that two velocities, so the player will move along with the platform

This is the code, that reads user input and calculates movement velocity:
Code (CSharp):
1.  public void Move(Vector2 moveInput, float targetSpeed, Quaternion cameraRotation, bool rotateCharacter = true)
2.         {
3.             // note: Vector2's == operator uses approximation so is not floating point error prone, and is cheaper than magnitude
4.             // if there is no input, set the target speed to 0
5.             if (moveInput == Vector2.zero) targetSpeed = 0.0f;
6.
7.             // a reference to the players current horizontal velocity
8.             float currentHorizontalSpeed = new Vector3(_controller.velocity.x, 0.0f, _controller.velocity.z).magnitude;
9.
10.             float speedOffset = 0.1f;
11.             float inputMagnitude = moveInput.magnitude; // _input.analogMovement ? _input.move.magnitude : 1f;
12.
13.             if (inputMagnitude > 1)
14.                 inputMagnitude = 1f;
15.
16.             // accelerate or decelerate to target speed
17.             if (currentHorizontalSpeed < targetSpeed - speedOffset ||
18.                 currentHorizontalSpeed > targetSpeed + speedOffset)
19.             {
20.                 // creates curved result rather than a linear one giving a more organic speed change
21.                 // note T in Lerp is clamped, so we don't need to clamp our speed
22.                 _speed = Mathf.Lerp(currentHorizontalSpeed, targetSpeed * inputMagnitude,
23.                     Time.deltaTime * SpeedChangeRate);
24.
25.                 // round speed to 3 decimal places
26.                 _speed = Mathf.Round(_speed * 1000f) / 1000f;
27.             }
28.             else
29.             {
30.                 _speed = targetSpeed * inputMagnitude;
31.             }
32.
33.             _animationBlend = Mathf.Lerp(_animationBlend, targetSpeed * inputMagnitude,
34.                 Time.deltaTime * SpeedChangeRate);
35.
36.             // normalise input direction
37.             Vector3 inputDirection = new Vector3(moveInput.x, 0.0f, moveInput.y).normalized;
38.
39.             // note: Vector2's != operator uses approximation so is not floating point error prone, and is cheaper than magnitude
40.             // if there is a move input rotate player when the player is moving
41.             if (moveInput != Vector2.zero)
42.             {
43.                 _targetRotation = Mathf.Atan2(inputDirection.x, inputDirection.z) * Mathf.Rad2Deg +
44.                                   (_useCameraOrientation ? cameraRotation.eulerAngles.y : 0);
45.                 float rotation = Mathf.SmoothDampAngle(transform.eulerAngles.y, _targetRotation, ref _rotationVelocity,
46.                     RotationSmoothTime);
47.
48.                 // rotate to face input direction relative to camera position
49.                 if (rotateCharacter)
50.                     transform.rotation = Quaternion.Euler(0.0f, rotation, 0.0f);
51.             }
52.
53.             // update animator if using character
54.             if (_hasAnimator)
55.             {
56.                 _animator.SetFloat(_animIDSpeed, _animationBlend);
57.                 _animator.SetFloat(_animIDMotionSpeed, inputMagnitude);
58.             }
59.
60.             Vector3 targetDirection = Quaternion.Euler(0.0f, _targetRotation, 0.0f) * Vector3.forward;
61.             _velocity = targetDirection.normalized * _speed + new Vector3(0.0f, _velocity.y, 0.0f);
62.             _timeoutToResetVars = 0.5f;
63.         }
64.
This is Update function:
Code (CSharp):
1. private void Update()
2.         {
3.             GravityControl();
4.             GroundedCheck();
5.
6.             if (_timeoutToResetVars <= 0)
7.             {
8.                 _speed = 0;
9.                 _animationBlend = 0;
10.                 _animator.SetFloat(_animIDSpeed, 0);
11.                 _timeoutToResetVars = 0;
12.             }
13.             else
14.                 _timeoutToResetVars -= Time.deltaTime;
15.
16.             if (_useRootMotion)
17.                 return;
18.
19.             if (!_controller.enabled) return;
20.
21.             _controller.Move(_velocity * Time.deltaTime);
22.         }

2. ### zulo3d

Joined:
Feb 18, 2023
Posts:
758
I've not tried in 2D but simulating platforms in 3D with a character controller can be very problematic. You may have a much easier time using a rigibody for your character. The physics engine will then take care of everything for you.