- Home /
[Complex] How to move the player similar to character controller while also applying rigidbody physics vectors
I am making a 2D platformer that involves the player being manipulated by gravitational spheres of influence. These gravity wells add force to the player in the direction of the force vector that gravity would apply in real life to objects. Obviously I've magnified the power of gravity since it is such a weak force. It is based on this equation Fg = GM1M2/|r^2| * r/|r|.
My issue is rooted in player movement and player jumping. I want to be able to have the player's ground running velocity translate into his jumping velocity, as well as increase his movement speed without giving the player the ability to overpower the force vectors of the gravity wells.
Currently movement is using a function of translation that cannot overpower the forces of my artificial gravity acting on it in the horizontal direction; it can only slightly empower or weaken it but cannot change direction unless the horizontal velocity vector has a very small magnitude.
When this translation gets higher than the power of the vector it causes issue with gameplay mechanics.
So I guess my problem can be boiled down to the question: Can I get advise on how one might go about creating a workaround or creating realistic force vectors based on the way that a player would run and jump.
An issue I have run into in my programming is that if I am simply applying vectors I do not like the slide effect that the player gets, I want a 2D-platformer style stop on a dime type deal, if anything he must stop very quicklyI guess I could keep him moving very slow but I would rather empower the player to make very quick and fluid motions so that players with high reaction times can have fun going fast, while not compromising mechanics and allowing methodical and slower players to also enjoy the game.
The player currently moves in this fashion:
enter code herebool isGrounded;
Vector3 startPosition, moveAmount;
float distToGround;
public float jumpForce, moveSpeed;
float horizontal, vertical;
// Use this for initialization
void Start () {
distToGround = collider.bounds.extents.y;
startPosition = transform.position;
isGrounded = false;
}
void jump(){
if(isGrounded){
this.transform.rigidbody.AddForce(Vector3.up * jumpForce);
}
}
void checkGrounding(){
if(Physics.Raycast(transform.position, -Vector3.up, distToGround +0.3f))
isGrounded = true;
}
void OnCollisionEnter(Collision coll){
if(coll.gameObject.name.Equals("Plane")){
checkGrounding();
if(isGrounded){
startPosition = transform.position;
}
}
}
void OnCollisionExit(Collision coll){
if(coll.gameObject.name.Equals("Plane"))
isGrounded = false;
}
// Update is called once per frame
void FixedUpdate () {
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
moveAmount = transform.right * horizontal * moveSpeed;
if(Input.GetKeyDown(KeyCode.R)){
transform.position = startPosition;
transform.rigidbody.angularVelocity = Vector3.zero;
transform.rigidbody.velocity = Vector3.zero;
}
if(horizontal!=0)
this.transform.Translate(Vector3.right*(horizontal/4.3f));
if(Input.GetAxis("Jump")!=0)
jump();
}
addendum: When using rigid body controls and making the user unable to move post-jump in a realistic system it makes the game so impossible. All entry trajectories must be pre-calculated. It's very difficult.
Additional question: is it possible to calculate the translation of a moving jump and store that and apply that throughout the jump.
Answer by yveris · Oct 20, 2013 at 08:40 AM
If there is not a more sophisticated fashion of calculating this sort of movement the vector of translation can be saved in the jump function like so:
void jump(){
if(isGrounded){
if (horizontal != 0)
if (Input.GetKey(KeyCode.LeftShift))
{
if (Physics.Raycast(transform.position, -Vector3.up, distToGround + 0.3f))
movingVector = Vector3.right * (horizontal);
}
else
{
movingVector = (Vector3.right * (horizontal / 4.3f));
}
this.transform.rigidbody.AddForce(Vector3.up * jumpForce);
isMoving = true;
}
}
This stores a boolean that during the fixed update keeps applying until is is grounded again.
This is checked as such:
void checkGrounding(){
if(Physics.Raycast(transform.position, -Vector3.up, distToGround +0.3f)){
isGrounded = true;
isMoving = false;
}
}
and is continually applied until the grounding is called again in the OnCollisionEnter function.
And the update function is edited and adds at the beginning this if statement; such that the user can still make slight alterations through the walking speed which is the targeted amount of alteration.
if (isMoving){
transform.Translate(movingVector);
}
I still think this is a bit overly complicated and if anyone can find a simpler and eloquent answer I would be much obliged.
If anything this question seems really specific but maybe it'll help people who are trying to make 2D platformers that need rigidbody physics but realstic constraints are causing an issue or they still want a mario type style of jump.