- Home /
Whenever I add a rigidbody and collider to my player, it interferes with the movement script and makes it teleport
Alright so here's the deal, I have the following script attached below that I'm using to control the movement for a third person game I'm working on. However, for some reason whenever I attach a rigidbody and a capsule collider to my player, things get weird.
What seems to happen is the character will teleport along the Y axis to wherever it was when the game started. So say the character was placed at X: 0 Y: 10 and Z: 0, and then I started walking, I would move just fine along the X and Z axis, but for as long as I'm holding down W, A, S, or D, the character will be transported up to Y: 10, until I let go of, when it will then teleport back to the ground.
The only solution I've found is to set the rigidbody to kinematic, but then the character doesn't react with gravity at all, and that just defeats the whole purpose of having a rigidbody.
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class ThirdPersonMovement : MonoBehaviour {
public CharacterController controller;
public float speed = 6f;
public float turnSmoothTime = 0.1f;
public float turnSmoothVelocity;
public Transform cam;
Animator m_Animator;
Vector3 m_Movement;
Quaternion m_Rotation = Quaternion.identity;
void Start()
{
m_Animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
Vector3 direction = new Vector3(horizontal, 0f, vertical).normalized;
if (direction.magnitude >= 0.1f)
{
float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg +cam.eulerAngles.y;
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
transform.rotation = Quaternion.Euler(0f, angle, 0f);
bool isWalking = true;
m_Animator.SetBool("IsWalking", isWalking);
Vector3 moveDir = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
controller.Move(moveDir.normalized * speed * Time.deltaTime);
}
else
{
bool isWalking = false;
m_Animator.SetBool("IsWalking", isWalking);
}
}
}
Answer by SteenPetersen · May 29, 2020 at 05:03 AM
Hi @isaiahburns
When adding a rigidbody you should no longer be using the character controller to move really. As now you will be moving using physics, therefore, the movement can get a bit wonky.
Moving with physics can be a bit different and perhaps you can use something like this to help you get started.
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class isaiahburns : MonoBehaviour
{
[SerializeField] float speed = 10.0f;
[SerializeField] float gravity = 10.0f;
[SerializeField] float maxVelocityChange = 10.0f;
[SerializeField] bool canJump = true;
[SerializeField] float jumpHeight = 2.0f;
private bool grounded = false;
private Rigidbody rb;
void Awake()
{
rb = GetComponent<Rigidbody>();
rb.freezeRotation = true;
rb.useGravity = false;
}
void FixedUpdate()
{
if (grounded)
{
// Calculate how fast we should be moving
Vector3 targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
targetVelocity = transform.TransformDirection(targetVelocity);
targetVelocity *= speed;
// Apply a force that attempts to reach our target velocity
Vector3 velocity = rb.velocity;
Vector3 velocityChange = (targetVelocity - velocity);
velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
velocityChange.y = 0;
rb.AddForce(velocityChange, ForceMode.VelocityChange);
// Jump
if (canJump && Input.GetButton("Jump"))
{
rb.velocity = new Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
}
}
// We apply gravity manually for more tuning control
rb.AddForce(new Vector3(0, -gravity * rb.mass, 0));
grounded = false;
}
void OnCollisionStay()
{
grounded = true;
}
float CalculateJumpVerticalSpeed()
{
// From the jump height and gravity we deduce the upwards speed
// for the character to reach at the apex.
return Mathf.Sqrt(2 * jumpHeight * gravity);
}
}
Let me know if that helps =)
Your answer
Follow this Question
Related Questions
Adding a rigidbody and capsule collider to my player makes it teleport along the Y axis while moving 0 Answers
Roll-A-Ball Movement (Without Endless Run) [C#] 2 Answers
Character jumping script without gravity? 2 Answers
How to affect multiple rigidbodies with one box collider trigger? 1 Answer
Do something if position Y is 4. (C#) 2 Answers