Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Instant velocity change in physics engine question.

Discussion in 'Scripting' started by jarden, Apr 22, 2011.

Thread Status:
Not open for further replies.
  1. jarden

    jarden

    Joined:
    Mar 29, 2011
    Posts:
    74
    Hi, Im trying to use the mouse or even the left/right arrows to make my game object change velocity instantly (from moving left, then snapping to moving right). I need to keep physics on the object. I searched around the forums and tried some things but I cant think of a way. Im using forcemode velocity change and have mass and all drag settings low as possible but it still has to slow down before it goes the opposite direction. I read not to use rigidbody.velocity in fixedupdate. Anyone know a proper way to do this? :confused:
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,400
    There's no way to have instant velocity changes with pure physics; they don't work that way (in real life or PhysX). You have to directly alter rigidbody.velocity if you want to do that.

    --Eric
     
  3. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    I think you want something like this?

    Code (csharp):
    1.  
    2. var speed=10.0;
    3.  
    4. function Update(){
    5.     x=(Input.GetKey("a")? -1.0 : 0.0) + (Input.GetKey("d") ? 1.0 : 0.0);
    6.     if(x!=0.0){
    7.         rigidbody.velocity=Vector3.right * x * speed;
    8.     }
    9. }
    10.  
    What Eric5h5 said is correct. The only way to do it is by controlling the velocity directly. So in the case I gave an example of how to do it. I deliberately didn't use GetAxis because it has a slowing effect on this particular operation.
     
  4. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    ForceMode.VelocityChange works. If your velocity is not zero, just add the difference between your desired velocity, and rigidbody.velocity.

    Tell that to a baseball!
     
    Last edited: Apr 22, 2011
  5. MitchStan

    MitchStan

    Joined:
    Feb 26, 2007
    Posts:
    567
    Wouldn't this do it:
    Code (csharp):
    1.  
    2. rigidbody.AddForce(newVelocity - rigidbody.velocity, ForceMode.VelocityChange);
    3.  
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,400
    A baseball is bouncing off something. ;)

    --Eric
     
  7. FredMastro

    FredMastro

    Joined:
    May 11, 2014
    Posts:
    6
    I know this is older but I had the same question and found this post.

    I used bigmisterb's theory and applied it with the Horizontal access

    Code (CSharp):
    1. float h = Input.GetAxis("Horizontal");
    2.         rigidbody2D.AddForce(Vector2.right * h * Speed);
    3.         rigidbody2D.transform.position = new Vector2(Mathf.Clamp(rigidbody2D.transform.position.x, minX, maxX), 8f);
    4.  
    5.         if (h != 0.0f && rigidbody2D.velocity.x != 0.0f)
    6.         {
    7.             rigidbody2D.velocity = Vector2.right * h * Speed;
    8.         }
     
    Last edited: Jun 5, 2014
    rricecake likes this.
  8. RainerEngblom

    RainerEngblom

    Joined:
    Sep 10, 2020
    Posts:
    9
    This is the retro platform jumper movement I usually use:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class PlayerMove2D : MonoBehaviour
    {
    public Rigidbody2D rb;
    public float moveSpeed = 50f;
    public float jumpForce = 10;
    public LayerMask groundLayer;
    public Transform groundChecker;
    public float maxVelocity = 50f;
    private Vector3 currScale = Vector3.one;

    void Update()
    {
    //Moving left or right
    float moveX = (Input.GetKey("a") ? -1.0f : 0.0f) + (Input.GetKey("d") ? 1.0f : 0.0f);

    if(!IsGrounded()) //Gliding movement in air
    {
    if (Mathf.Abs(rb.velocity.x) < maxVelocity)
    {
    rb.AddForce(transform.right * moveX/2);
    }
    }
    else //Sticky movement on ground
    {
    rb.velocity = new Vector2(moveX * moveSpeed, rb.velocity.y);
    }
    //Check which way the sprite should be
    if (moveX != 0)
    {
    currScale.x = Mathf.Sign(moveX) * 1;
    transform.localScale = currScale;
    }
    //Jump
    if(Input.GetButtonDown("Fire1"))
    {
    if (IsGrounded())
    {
    rb.AddForce(Vector2.up * jumpForce);
    }
    }
    }
    bool IsGrounded()
    {
    return Physics2D.Raycast(groundChecker.position, -transform.up, 0.4f, groundLayer);
    }
    }
     
  9. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,513
    Please use code-tags when posting code. Whilst it's appreciated you're trying to help, please note that you are replying to a thread from 2014 that's related to 3D physics not 2D and there are far better ways now to determine contact with ground than the overused "raycast" method as demonstrated here.

     
Thread Status:
Not open for further replies.