0
\$\begingroup\$

I am spawning objects at a random place at the top of the screen, tilted at a random angle like this:

[SerializeField] Vector2 spawnSizeMinMax;
[SerializeField] float spawnAngleMax;

void Update()
{
    if (Time.time > nextSpawnTime)
    {
        nextSpawnTime = Time.time + SecondBtwnSpawns;

        float spawnAngle = Random.Range(-spawnAngleMax, spawnAngleMax);  //rotation
        float spawnSize = Random.Range(spawnSizeMinMax.x, spawnSizeMinMax.y);  //Size
        Vector2 SpawnPos = new Vector2(Random.Range(-SpawnX, SpawnX), 5.67f);  //position for their spawn
        GameObject newBlock = (GameObject)Instantiate(fallingRock, SpawnPos, Quaternion.Euler(Vector3.forward * spawnAngle));
        newBlock.transform.localScale = Vector2.one * spawnSize;
    }
}

And then I use this script to move them down along their local "down" vector (which may be pointing along a diagonal), and reflect them off of the walls when they hit:

[SerializeField] float DropSpeed = 10f;
Rigidbody2D rb;
Vector3 lastVelocity;

void Awake()
{
    rb = GetComponent<Rigidbody2D>();
}

void Update()
{
    lastVelocity = rb.velocity;
    DropDown();
}

void DropDown()
{
    transform.Translate(Vector3.down * DropSpeed * Time.deltaTime);
}

void OnCollisionEnter2D(Collision2D collision)
{
    var speed = lastVelocity.magnitude;
    var direction = Vector3.Reflect(lastVelocity.normalized, collision.contacts[0].normal);

    rb.velocity = direction * Mathf.Max(speed, 2f);
}

But when I use this code, they don't bounce off the wall. How can I fix that?

\$\endgroup\$
1
\$\begingroup\$

You should not mix Transform changes (like transform.Translate()) with Rigidbody/Rigidbody2D movement. Use one or the other exclusively. If you want your object to move with physics, let the physics engine handle all its movement.

Mixing these means anytime you edit the Transform, you're ripping the object out of the control of the physics engine, teleporting it, then throwing it back in haphazardly. This can result in inaccurate collision resolution (because there's a component to the object's motion that's invisible to the physics engine which only sees its velocity), performance issues (the physics engine has to do extra work every time you teleport the object), and confusing trigger/collision messages (every time the object teleports, you get a fresh pair of enter/exit events).

In this instance, because the diagonal falling is coming from the transform, not the body's velocity, it has no velocity to reflect!

I think you want something more like this:

public class Bouncer : MonoBehaviour {    
    [SerializeField] float DropSpeed = 10f;
    Rigidbody2D rb;
    Vector2 lastVelocity;

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

        // Apply your initial velocity on spawn.
        // Then you don't need to transform the object every update tick.
        rb.velocity = transform.up * -DropSpeed;
    }
    
    // Do this in FixedUpdate, so you're caching the velocity in every
    // physics step, rather than only on rendered frames.
    void FixedUpdate()
    {
        lastVelocity = rb.velocity;
    }
    
    void OnCollisionEnter2D(Collision2D collision)
    {
        var speed = lastVelocity.magnitude;
        var direction = Vector2.Reflect(lastVelocity.normalized, 
                                        collision.contacts[0].normal);
    
        rb.velocity = direction * Mathf.Max(speed, 2f);
    }
}

I've tested this and it correctly bounces an object off a wall with the same speed it had coming in. Though you get pretty much the same behaviour without this script at all, just using a PhysicsMaterial2D with Friction = 0 and Bounciness = 1 and giving your Rigidbody2D an initial velocity or impulse to start it off.

\$\endgroup\$
4
  • \$\begingroup\$ ty! yes i should have known to let physics plays apart. But previously my object dropped in an angular fashion. Now it is just straight down. I set the rotation on my spawn script not on the rock itself, pls advce? \$\endgroup\$
    – weekdays
    Oct 16 '21 at 17:07
  • \$\begingroup\$ Sounds like a problem on your spawn script, which is not shown in your question. \$\endgroup\$
    – DMGregory
    Oct 16 '21 at 17:09
  • \$\begingroup\$ I'm sorry. Ok i have edited it and put the spawn script. I'm really sorry, i hope you can make a quick check if there's anything wrong \$\endgroup\$
    – weekdays
    Oct 16 '21 at 17:39
  • \$\begingroup\$ Ah, I'd assumed the sideways component of your velocity was being applied by the spawning script, but you're just rotating the object and then translating it along its local down vector. You can get a similar behaviour by just applying a velocity when you first fetch the Rigidbody. \$\endgroup\$
    – DMGregory
    Oct 16 '21 at 17:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .