- Home /
Motion over sloped terrain
Note: There are quite a few posts like this one. I have yet to find the answer I am looking for.
I'm working on a first person shooter prototype build, and have been closely cloning HaloCE physics for the process. I enjoy the simplicity of the older version and think it would be suitable for a baseline. I am not directly copying any assets or values, and am coding the controller from scratch. Target platform is mobile devices (android first) with a controller as the primary source.
In HaloCE, there seems to be acceleration, and momentum factors present. I have done my best to clone speed, jump height, and fall speeed. One of the conflicts I have been running into is movement down sloped terrain. By default, the player will 'bounce' down the hill, as gravity starts when the player is no longer grounded. I need to keep the player grounded until such scenarios require otherwise (jump, fall off ledge, thrown by grenade, etc).
Solution 1: The most accurate, and sturdy solution is to add a default amount of fallspeed to a portion of gravity. Preferably, the amount of gravity per second. This allows for smooth movement over all sorts of terrain that you would normally be able to walk across. Checks can then be provided for sharp slopes (sliding effect). Jumping works more consistantly in this scenario because you are always grounded when on the ground (supposing force was added before the end of the Update loop). A Con to this method is walking off cliffs. Gravity has already been applied to your character, and can cause you to fall a distance before !Grounded checks can reset the gravity. I need gravity to start at 0 when walking off a cliff for the proper physics.
Solution 2: Less accurate, and causing a LOT of undesired effects, is sloped calculations, or predictions. By vector-casting based on Time.deltaTime, and then raycasting for ground-checks, you can get the coordinate of where you should be next frame, and move your character accordingly. This can provide you with zero-gravity terrain moving over slopes, but can cause weird slow-downs on various slopes. I cannot have this, and have yet to figure out a solution here that would provide smoother movement.
Vector3 MoveDirection() {
// Get desired direction with accelleration modifiers
//Vector3 input = new Vector3(Input.GetAxis("Vertical"), 0, Input.GetAxis("Horizontal"));
float vert = (input.MoveForward.getValue()-input.MoveBack.getValue());
float horiz = (input.MoveRight.getValue()-input.MoveLeft.getValue());
Vector3 _input = new Vector3(vert, 0, horiz);
// Direction Translators
Vector3 forward = cam.forward;//Camera.main.transform.TransformDirection(Vector3.forward);
forward.y = 0; forward = forward.normalized;
Vector3 right = new Vector3(forward.z, 0, -forward.x);
// calculate horizontal acceleration
Vector3 movement = (_input.z * right + _input.x * forward);
Vector3 nextpos = movement * MoveSpeed;
if (nextpos.magnitude > MoveSpeed)
nextpos = Vector3.ClampMagnitude (nextpos, MoveSpeed);
if (cc.isGrounded && Momentum.y < 0) {
RaycastHit hit;
// TODO: change future point to account for frame spikes
if (Physics.Raycast(transform.position + nextpos * Time.deltaTime, -Vector3.up, out hit)){ // is over ground
//movement = movement - Vector3.Dot(movement, hit.normal) * hit.normal;
Vector3 dest = hit.point + Vector3.up*0.02f;
if ( Vector3.Distance(transform.position,dest) < (MoveSpeed)*Time.deltaTime+Gravity) // TODO: change to proper slope height
{
movement = Vector3.ClampMagnitude((dest - transform.position).normalized, movement.magnitude);
}
}
}
movement = movement * MoveSpeed;
if (movement.magnitude > MoveSpeed)
movement = Vector3.ClampMagnitude(movement, MoveSpeed);
// clamp only when too high
if (movement.magnitude > MoveSpeed)
movement = Vector3.ClampMagnitude(movement, MoveSpeed);
return movement;
}
void Update() {
//...
if (!cc.isGrounded) {
Momentum.y -= Gravity;
FallTime += Time.deltaTime;
} else {
if (Mathf.Abs(Momentum.y) != 1)
Debug.Log("Fall Time: "+FallTime);
FallTime = 0;
Momentum.y = -1;
if (input.Jump.isPressed())
Momentum.y = JumpHeight;
}
cc.Move((MoveDirection()+Momentum)*Time.deltaTime);
//...
}
Are there any other movement scripting methods to help me mimic these conditions better?
Your answer
Follow this Question
Related Questions
Character floating after walking up higher terrain/object 1 Answer
CharacterController doesn't work with collider 1 Answer
Can someone help me with my TPS Controller/Camera? 1 Answer
How to make a bug (ant) with a CharacterController align to any surface? 1 Answer
Adding gravity to character and grounded checks are not working? 0 Answers