Hello all, I have created a player controller script like this: Code (csharp): using UnityEngine; using System.Collections; public class PlayerController : MonoBehaviour { public float speed; public Rigidbody rb; public Animator anim; public float jumpPower; private bool grounded; private float distToGround; public float hits; // Use this for initialization void Start () { rb = GetComponent<Rigidbody>(); anim = GetComponent<Animator>(); } void OnCollisionStay(Collision collisionInfo) { grounded = true; } void OnCollisionExit(Collision collisionInfo) { grounded = false; } // Update is called once per frame void Update () { float moveHorizontal = Input.GetAxis("Horizontal"); float moveZ = Input.GetAxis("Vertical"); rb.velocity = new Vector3(moveHorizontal *speed, rb.velocity.y, moveZ*speed); if(Input.GetKeyDown(KeyCode.Space) && grounded == true) { Jump(); } } void Jump() { rb.AddForce(Vector3.up * jumpPower); // animation.Play("jump_pose"); } void FixedUpdate() { // } } This script, however, does not seem to be working. It usually ends up freezing the player where you cannot move the player at all with any keys. This is demonstrated here: https://embed.gyazo.com/768346efa3444041f574b65912f852c2.gif It is also demonstrated here showing the movement before it: https://gyazo.com/1b516af1ae6b493297139a7ad9ca61f1 Could you please advise me on how to fix this? I would appreciate any help. Thanks, 8Development
Code (CSharp): using UnityEngine; using System.Collections; public class PlayerController : MonoBehaviour { public float speed; public Rigidbody rb; public Animator anim; public float jumpPower; private bool grounded; private float distToGround; public float hits; // Use this for initialization void Start () { rb = GetComponent<Rigidbody>(); anim = GetComponent<Animator>(); } void OnCollisionStay(Collision collisionInfo) { grounded = true; } void OnCollisionExit(Collision collisionInfo) { grounded = false; } // Update is called once per frame void Update () { float moveHorizontal = Input.GetAxis("Horizontal"); float moveZ = Input.GetAxis("Vertical"); if(Input.GetKeyDown(KeyCode.Space) && grounded == true) { Jump(); } } void Jump() { rb.AddForce(Vector3.up * jumpPower); // animation.Play("jump_pose"); } void FixedUpdate() { rb.AddForce(moveHorizontal * speed, rb.velocity.y, moveZ * speed); } } try using addforce instead of velocity.
well, from the looks of it, you are using onCollision events to handle your grounded method, which is probably not the best way to do it. You can use velocity, as that is a convenient way to control the actual rigidbody. Code (csharp): using UnityEngine; using System.Collections; public class PlayerController : MonoBehaviour { public Animator anim; public float speed = 8; public float jumpPower = 7; public float hits; private bool grounded = false; private float distToGround; private Rigidbody rb; // Use this for initialization void Start () { rb = GetComponent<Rigidbody>(); anim = GetComponent<Animator>(); } // Update is called once per frame void Update () { if(rb == null) return; // gather movement keys float moveh = Input.GetAxis("Horizontal"); float movev = Input.GetAxis("Vertical"); // create a vector from those keys Vector3 newVelocity = new Vector3(moveh * speed, 0, movev * speed); // use the camera to transform the rotation of the velocity Transform camera = Camera.main.transform; Vector3 lookAt = camera.position + camera.forward; lookAt.y = camera.y; camera.LookAt(lookAt); newVelocity = camera.TransformDirection(newVelocity); // reset the camera to look at the player camera.LookAt(transform); // assign the y from the current velocity newVelocity.y = rb.velocity.y; // if we are grounded, lerp the velocity towards the new one at a fast rate // also, if we just pressed the jump key, jump if(grounded){ newVelocity = Vector3.Lerp(rb.velocity, newVelocity, 5 * Time.deltaTime); if(Input.GetKeyDown(KeyCode.Space)){ newVelocity = new Vector3(newVelocity.x, jumpPower, newVelocity.y); } } else { // if we are not grounded, we lerp the velocity towards the new one at a slow rate newVelocity = Vector3.Lerp(rb.velocity, newVelocity, Time.deltaTime); } // set the velocity back onto the object. rb.velocity = newVelocity; // update our grounded variable if we can spherecast to the ground. RaycastHit hit; Ray ray = new Ray(transform.position, Vector3.down); grounded = Physics.SphereCast(ray, 0.5f, 0.55f); } }
Velocity may not be that convenient, because if you jump, there is always a maximum height, and the velocity there is 0 as well and if you have a good timing, you could just jump forever
run that code and tell me if you can jump forever..... you can only jump when grounded is true... and grounded is only true if you can spherecast to the ground below you.
@bigmisterb Ohh, you were talking about setting the velocity, well sorry. Your system has a huge bug. The jump height will change based on the frames the player was in the ground. Edit: not when you're working with velocity itself, but the docs don't recommend that
so.... the jump height... which is not specific by the way, can jump higher, if you are on the ground longer? Code (csharp): newVelocity = new Vector3(newVelocity.x, jumpPower, newVelocity.y); This line sets the velocity to jumpPower... no more, no less. If you spend 100 frames on the ground, then press the jump key you are going to give yourself jumpPower velocity. AddForce would do exactly what you are describing, not setting the velocity directly. Please test the code before you start pointing flaws and bugs. I have used this same type of code many times and it works great every time.
Thank you guys so much for your help. I found out all I really had to do was change the velocity line. Code (csharp): transform.position += new Vector3(input_x , 0f, input_y ).normalized * speed * Time.deltaTime; Thanks, 8Development