Asked by Coder

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Controller : MonoBehaviour
{
public Rigidbody rb;
public float jumpForce;
public float speed;
public float moveX;
public float moveY;
void Start()
{
if (rb == null)
{
rb = GetComponent<Rigidbody>();
}
}

// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
moveX = Input.GetAxis("Horizontal");
moveY = Input.GetAxis("Vertical");
transform.Translate(Vector3.forward * speed * moveY * Time.deltaTime);
transform.Translate(Vector3.right * speed * moveX * Time.deltaTime);
}
}


Make this movement script smoother and use riigdboy and based movement and check for a ground tag

All Answers 1

Answered by GPT-5 mini AI
Below is a Rigidbody-based movement script that is smoother (uses interpolation and velocity smoothing), moves in FixedUpdate (physics-safe), and checks collisions with objects tagged as "Ground" to allow jumping. It also prevents the player from tipping over by freezing rotation.

Drop this script on your player (which must have a Rigidbody). Make sure the ground objects are tagged with the Tag you set in the inspector (default "Ground").

Script:
using System.Collections.Generic;
using UnityEngine;

public class SmoothRBController : MonoBehaviour
{
[Header("References")]
public Rigidbody rb;

[Header("Movement")]
public float moveSpeed = 6f;
[Tooltip("How quickly horizontal velocity approaches target (higher = snappier)")]
public float acceleration = 10f;
[Tooltip("Multiplier for control while in air (0-1)")]
[Range(0f, 1f)]
public float airControl = 0.6f;

[Header("Jump")]
public float jumpForce = 5f;
public string groundTag = "Ground";

// Read-only for debugging
[SerializeField] private bool isGrounded;

private float inputX;
private float inputZ;
private bool wantJump;

// Track ground contacts robustly
private HashSet<Collider> groundColliders = new HashSet<Collider>();

void Start()
{
if (rb == null) rb = GetComponent<Rigidbody>();
if (rb == null)
{
Debug.LogError("SmoothRBController requires a Rigidbody.");
enabled = false;
return;
}

// Smooth visual motion
rb.interpolation = RigidbodyInterpolation.Interpolate;
// Prevent tipping over from physics impulses
rb.freezeRotation = true;
}

void Update()
{
// Read inputs in Update
inputX = Input.GetAxis("Horizontal");
inputZ = Input.GetAxis("Vertical");

if (Input.GetKeyDown(KeyCode.Space))
{
wantJump = true;
}
}

void FixedUpdate()
{
// Build world-space target velocity from local input (forward is transform.forward)
Vector3 localInput = new Vector3(inputX, 0f, inputZ);
// Keep magnitude <= 1 so diagonal doesn't exceed speed
if (localInput.sqrMagnitude > 1f) localInput.Normalize();

Vector3 targetVelocity = transform.TransformDirection(localInput) * moveSpeed;

// Current horizontal velocity
Vector3 currentVel = rb.velocity;
Vector3 horizontalVel = new Vector3(currentVel.x, 0f, currentVel.z);

// Choose control factor based on grounded state
float control = isGrounded ? acceleration : acceleration * airControl;

// Smoothly approach the target horizontal velocity
Vector3 newHorizontal = Vector3.Lerp(horizontalVel, targetVelocity, 1f - Mathf.Exp(-control * Time.fixedDeltaTime));

// Apply the new velocity while preserving vertical velocity
rb.velocity = new Vector3(newHorizontal.x, currentVel.y, newHorizontal.z);

// Jump if requested and grounded
if (wantJump && isGrounded)
{
// Reset vertical velocity before jump for consistent jumps
rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}

wantJump = false;
}

// Use collision callbacks to detect ground contacts reliably
void OnCollisionEnter(Collision collision)
{
EvaluateCollisionForGround(collision);
}

void OnCollisionStay(Collision collision)
{
EvaluateCollisionForGround(collision);
}

void OnCollisionExit(Collision collision)
{
// Remove collider if it was tracked as ground
if (collision.collider != null && collision.collider.CompareTag(groundTag))
{
groundColliders.Remove(collision.collider);
isGrounded = groundColliders.Count > 0;
}
}

private void EvaluateCollisionForGround(Collision collision)
{
// Only consider colliders tagged as ground
if (!collision.collider.CompareTag(groundTag)) return;

// Check contact normals to ensure we are standing on top (not hitting a wall)
foreach (ContactPoint cp in collision.contacts)
{
if (cp.normal.y > 0.5f)
{
groundColliders.Add(collision.collider);
isGrounded = true;
return;
}
}
}
}

Notes and tips:
- Assign the Rigidbody in the inspector (or let the script auto-find it).
- Set your ground objects to the "Ground" tag (or change groundTag).
- Tweak moveSpeed, acceleration, airControl and jumpForce to suit your feel.
- Rigidbody interpolation is enabled to make movement appear smoother visually.
- Movement and physics are done in FixedUpdate — do not call transform.Translate or set transform.position directly, as that bypasses the physics system.

If you want features like coyote time, jump buffering, slope handling, or using a LayerMask-based ground check instead of tags, tell me which and I can add them.