- Home /
How to make an object ricochet in 2d
I am trying to make an object move and ricochet of walls in 2d, but my problem is I don't know how to get it to do that. If I need to use a rigidbody, that's fine, if I need to use something else, that's fine, but I NEED to get this to work. Although it is not much, here is my code:
public class BallController : MonoBehaviour { public float speed;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
transform.Translate(Vector3.up * Time.deltaTime * speed);
}
}
People I want to notify about this issue:
watch this it might be helpful.(its a tutorial about how when a bullet hits a wall and then it reflects)
link of the tutorial.
https://answers.unity.com/storage/attachments/109681-untitled.png
Answer by SFoxx28 · Jan 20, 2018 at 04:37 AM
This code below works perfectly for me in a 3D topdown game I'm making. I commented out the changes I think you'll need to make in order to get it to work in a 2D game. I followed this youtube tutorial to create this.
The public layer mask tells the projectile what it is allowed to bounce off of. Set this to the same layer(s) as the walls in your game.
public LayerMask collisionMask;
public float speed;
private void BounceProjectile()
{
Ray ray = new Ray(transform.position, transform.forward); //You might have to change this to transform.up instead of transform.forward for a 2D game
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Time.deltaTime * ProjectileSpeed + 0.1f, collisionMask))
{
//Vector2 reflectDir2D = Vector2.Reflect(ray.direction, hit.normal);
Vector3 reflectDir = Vector3.Reflect(ray.direction, hit.normal);
float rot = 90 - Mathf.Atan2(reflectDir.z, reflectDir.x) * Mathf.Rad2Deg; //I think this should be Mathf.Atan2(reflectDir2D.y, reflectDir.x) * Mathf.Rad2Deg; for 2D
transform.eulerAngles = new Vector3(0, rot, 0); //For 2D I think this should be maybe Vector3(0,0,rot)
}
}
@SFoxx28 No, that does not work, Could it be that I have this code in my update function? anyway, I edited the code to all your specifications HERE:
transform.Translate(Vector3.up Time.deltaTime speed);
Ray ray = new Ray(transform.position, transform.up); //You might have to change this to transform.up ins$$anonymous$$d of transform.forward for a 2D game
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Time.deltaTime * speed + 0.1f, collision$$anonymous$$ask))
{
//Vector2 reflectDir2D = Vector2.Reflect(ray.direction, hit.normal);
Vector3 reflectDir = Vector3.Reflect(ray.direction, hit.normal);
float rot = 90 - $$anonymous$$athf.Atan2(reflectDir2D.y, reflectDir.x) * $$anonymous$$athf.Rad2Deg; //I think this should be $$anonymous$$athf.Atan2(reflectDir2D.y, reflectDir.x) * $$anonymous$$athf.Rad2Deg; for 2D
transform.eulerAngles = new Vector3(0,0,rot); //For 2D I think this should be maybe Vector3(0,0,rot)
It did not see a variable in the place of reflectDir2D.y. I tried uncommenting the line of code you commented out: Vector2 reflectDir2D = Vector2.Reflect(ray.direction, hit.normal); and that stopped it from complaining about there not being a variable but the bullet still didn't ricochet. And yes I did set the collision$$anonymous$$ask to the layer that my wall was on.
I made a slight change from reflectDir.x to reflectDir2D.x try that and see if it works. I'm also going to fire up a 2D environment and see if I can get it to work on my end to help you out.
Ray ray = new Ray(transform.position, transform.up); //You might have to change this to transform.up ins$$anonymous$$d of transform.forward for a 2D game
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Time.deltaTime * speed + 0.1f, collision$$anonymous$$ask))
{
Vector2 reflectDir2D = Vector2.Reflect(ray.direction, hit.normal);
//Vector3 reflectDir = Vector3.Reflect(ray.direction, hit.normal);
float rot = 90 - $$anonymous$$athf.Atan2(reflectDir2D.y, reflectDir2D.x) * $$anonymous$$athf.Rad2Deg; //I think this should be $$anonymous$$athf.Atan2(reflectDir2D.y, reflectDir2D.x) * $$anonymous$$athf.Rad2Deg; for 2D
transform.eulerAngles = new Vector3(0,0,rot); //For 2D I think this should be maybe Vector3(0,0,rot)
I couldn't get the code to work on my end as it is. However I did find this tutorial that I think you should try. It is specifically for reflecting objects in 2D and it is complete with the source code.
Here: http://www.theappguruz.com/blog/reflect-object-in-unity2d
This should work for you, let us know if it does.
@SFoxx28 Unfortunately, the code you gave me doesn't work for me ether and the code from the link you gave me might work but there are multiple problems:
#region PUBLIC-PROPERTIES
publicfloatbulletSpeed; // It says publicfloatbulletSpeed does not exitst in it's current context #endregion
#region PRIVATE-PROPERTIES
#endregion
#region UNITY-CALLBAC$$anonymous$$S
voidOnEnable() { rigidbody2D.velocity = transform.right * bulletSpeed; //It says using rigidbody2d is obsolete so it is saying .velocity does not exist and because of the variable above not working it says bullet speed does not work } void OnCollisionEnter2D(Collision2D other) { if (other.transform.CompareTag("Wall")) CollisionWithWall(other); // It says CollisionWithWall does not exist in it's current context } #endregion
#region PRIVATE-$$anonymous$$EHODS
voidCollisionWithWall(Collision2D other) { Vector3reflectedPosition = Vector3.Reflect(transform.right,other.contacts[0].normal); // It says Vector3reflectedPosition does not exist in it it's current context rigidbody2D.velocity = (reflectedPosition).normalized * bulletSpeed; // It says rigidbody2D is obsolete so .velocity does not exist in it's current context it also says reflectedPosition does not exist in it's current context and because of the variable not working at the top of the script it says bulletSpeed does not exist in it's current context
Vector3dir = rigidbody2D.velocity; // It says Vector3dir does not exist in it's current context and rigidbody2D is obsolete so it says .velocity doesen't exist in it's current context float angle = $$anonymous$$athf.Atan2(dir.y, dir.x) * $$anonymous$$athf.Rad2Deg; // It says both dir don't exist in there current context rigidbody2D.$$anonymous$$oveRotation(angle); // And it says rigidbody2D is obsolete so it says .$$anonymous$$oveRotation does not exist in it's current context } #endregion }
Answer by FlightOfOne · Jan 20, 2018 at 09:21 PM
You can use Vector2.Reflect:
Vector2 ricochetDirection = Vector2.Reflect(_incomingDirection, _hitSurfaceNormal)
@FlightCrazed Where would you recommend putting that in my code to make it work?