bouncing an object of a wall.

i want to make an object not really bounce but in fact more like go in the opposite direction with the same velocity.

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

public class ballmove : MonoBehaviour
    {
    private Rigidbody rb;
    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    void Update()
    {
        rb.AddForce(Vector3.forward * 0.02f, ForceMode.VelocityChange);

    }
    void OnCollisionEnter(Collision collision)
    {
        {
            // Check if collision is with a wall
            if (collision.collider.CompareTag("Wall"))
            {

                // Calculate the reflection vector
                Vector3 reflection = Vector3.Reflect(rb.velocity, collision.contacts[0].normal);
                // Apply the reflection vector as a force
                rb.AddForce(reflection, ForceMode.VelocityChange);
            }
        }
}

this is what i have for the object right now.
so far it just moves forward until it collides with the wall where it looks like it stops but if i look at the numbers its actually moving along the x and y direction. why? i don really know honestly. might be because the wall is not actually aligned properly with the object. which i hope is the reason so that the reason is simple.

but basically it doesnt actually reflect back in the other direction.
one reason i thought of is that because its in the update event where it constantly moves forward. but in the other hand i dont know how to fix it either.
if thats not the problem… then well im stumped.

You need to first understand what your code is actually doing.

  • Update - each frame you AddForce to Rigidbody in forward direction (all the time).
  • You hit on something, you check if its Wall and…? You make short burst in oposite direction.
  • Now you have loop. Each Update frame you push forward, and hit the Wall making weak bump back, and push again forward and bump back etc.
  • You dont turn force in oposite direction.

Try this, I wrote it without editor so could be error, but maybe idea will be more clear.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ballmove : MonoBehaviour
{
    Rigidbody rb;
    Vector3 direction;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
 
        // Ball direction at start
        direction = Vector3.forward * 0.02f;
    }

    void Update()
    {
        // Each frame you push in that direction
        rb.AddForce(direction, ForceMode.VelocityChange);
    }

    void OnCollisionEnter(Collision collision)
    {
        if (collision.collider.CompareTag("Wall"))
        {
            // You reflect direction
            direction = Vector3.Reflect(rb.velocity, collision.contacts[0].normal);
        }
    }
}

In my opinion better use velocity if you plan to do something like Pong Ball. Method AddForce is more like holding the gas pedal in car (or space ship with drive on). Can be used also for impulse jump of character and gravity get him back to ground.

sorry for the late reply…
ok so unfortunately while i do understand what is going on. it still doesn’t work…

i said this in the first question
so far it just moves forward until it collides with the wall where it looks like it stops but if i look at the numbers its actually moving along the x and y direction.
i hope that doesnt really change anything right…? since reflect should be in the completely other direction?
basically what happens now is this

https://vimeo.com/795498537

as you can see at the top right when the box touches the wall it starts to move ever so slightly.

I think you can make it go faster, just change a setting in the menus.

No, because you’re pushing the object forward in one direction every frame. Just because you’ve done some calculations elsewhere doesn’t mean you’ve broken the Update method loop.

    void Update()
    {
        rb.AddForce(Vector3.forward * 0.02f, ForceMode.VelocityChange);
    }

The method always pushes the object forward because you have set Vector3.forward to a fixed position. Move the code to Start if you want to do it one time.

ok im getting more and more confused by the second somehow.
anyways from what i understand… i tried to move the addforce to start event, whilst i add another addforce to when collision

    void Start()
    {
        rb = GetComponent<Rigidbody>();

        // Ball direction at start
        direction = Vector3.forward * 2f;
        rb.AddForce(direction, ForceMode.VelocityChange);
    }
    void OnCollisionEnter(Collision collision)
    {
        if (collision.collider.CompareTag("Wall"))
        {
            // You reflect direction
            direction = Vector3.Reflect(rb.velocity, collision.contacts[0].normal);
            rb.AddForce(direction, ForceMode.VelocityChange);
        }
    }

i hope you can see where im coming from and maybe what im misunderstanding here.
unfortunately after trying this, it also does not work.

i noticed that you said this in the previous reply which i missed. so i also wanted to ask how you can change the code to “use velocity” in this scenario, because i saw the code that you gave in the first reply, and you didnt actually touch any of the things related to the velocity if im not wrong.

edit: after looking into it abit more. theres something i realized. when the box touches the wall,
the rotation of the box became from all 0 to x:-0.87,y:0.218,z:0.009

I got up this morning, had my coffee, read what I wrote to you earlier and noticed that I wrote nonsense. I wrote a simple script with comments, maybe this will be more helpful.

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

public class Move : MonoBehaviour
{
    // Drag and drop Rigidbody in Inspector
    public Rigidbody rb;
    public Vector3   velocity;

    void Start()
    {
        // Add force once at start
        rb.AddForce(Vector3.forward * 3.0f, ForceMode.VelocityChange);
    }

    void Update()
    {
        // Track velocity, it holds magnitude and direction (for collision math)
        velocity = rb.velocity;
    }

    void OnCollisionEnter(Collision collision)
    {
        // Magnitude of the velocity vector is speed of the object (we will use it for constant speed so object never stop)
        float speed = velocity.magnitude;

        // Reflect params must be normalized so we get new direction
        Vector3 direction = Vector3.Reflect(velocity.normalized, collision.contacts[0].normal);

        // Like earlier wrote: velocity vector is magnitude (speed) and direction (a new one)
        rb.velocity = direction * speed;
    }
}
1 Like

hi, im so sorry for the late reply. good news. It works now! thank you so much. just a few last question. since right now when it bounces off, the rotation changes. does that affect the next bounce direction? because as of now it doesnt look like it does when it bounces against another wall opposite it. the x position does move veryyy slightly though. is there a way to make it like pong where u start off going straight and it somehow goes to the side completely. should i like multiply the rotation when on collision or something?
secondly for some reason when it knocks against my player it slows down alot. it might have been because the player was barely tall enough to even touch the ball, but when i made the player taller, for the most part it bounced back at a normal speed. but i somehow replicated the slow down once with the taller character.

If you need a complete physical engine, then rather familiarize yourself with Physical Materials and Rigidbody parameters.

Writing your own physics engine is a lot of work and knowledge not only in programming.

hmmm okok thank you!

edit: wait hang on what do u mean a…physical engine
and when i started this project i randomly followed another tutorial which might complicate things i think so now my player is using character controller while my ball is using rigidbody…i dont think i should have made it so complicated for my first project.
in fact if my player is going to be as simple as moving left and right and detecting collision against the ball. will using rigid body be actually easier then…

In such situation, you just put on your Rigidbody (drag and drop) Physical Material with high bounciness. It’s the simplest explanation how to use Physical Materials I had found.

:open_mouth: that looks really useful. will definitely try it and hopefully come back with good news. thank you!

hi! im back. i have a very simple question which I’m sure is something quite stupid. but I followed the physics material tutorial. and I’m wondering if I put the bounce there will the ball lose any velocity? because it sure looks like it. but at the same time I’ve already made dynamic and static friction to 0. I’m assuming the rigid body has nothing to do with this as the drag and gravity are both 0? does it have some thing to do with this line?
rb.AddForce(Vector3.forward * 5.0f, ForceMode.VelocityChange);
btw this was done in the start event.
i created a new script for this new ball i made to test out physic materials. so yea