I’m trying to make a script that makes 2D bullets ricochet off a shield but to disappear if it hits the player or the ground. My code looks like this:`using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
public float speed;
public float lifetime;
public float distance;
public int damage;
public float offset;
public LayerMask whatIsSolid;
private float oppositeSpeed;
private void Start()
{
oppositeSpeed = (speed - (speed * 2));
}
private void Update()
{
RaycastHit2D hitInfo = Physics2D.Raycast(transform.position, transform.up, distance, whatIsSolid);
if (hitInfo.collider != null) {
if (hitInfo.collider.CompareTag("Player")) {
Debug.Log("Player has taken damage!");
hitInfo.collider.GetComponent<CharacterControl>().TakeDamage(damage);
DestroyProjectile();
}
if (hitInfo.collider.CompareTag("Ground")) {
DestroyProjectile();
}
if (hitInfo.collider.CompareTag("Shield")) {
oppositeSpeed = speed;
transform.rotation = Quaternion.Euler(0f, 0f, offset);
}
}
transform.Translate(Vector2.up * speed * Time.deltaTime);
}
void DestroyProjectile()
{
Destroy(gameObject);
}
}`
At the moment, the bullet always goes at a specific angle after the collision, which I understand why, since the ‘offset’ value is a specific number, but I don’t know how to fix this. In case you didn’t realise already, idk what I’m doing.
You want to use Vector2.Reflect. It takes two parameters: the incoming direction, which can be a normalised copy of the bullet velocity and the normal of the surface it hits. Where do you get the normal from? RaycastHit2d.normal
The normal is the perpendicular to the surface that it hits so that you will get the right kind of ricochet - sort of. Were I coding this, I certainly wouldn’t ricochet if the incoming angle were too steep. You wouldn’t expect a bullet arriving at 90˚ to the surface to bounce back. Reflect is very good for bouncing balls but you may need to have a think about what angles you want to ricochet and which you want to destroy.
When you have the result from Vector2.Reflect, multiply it by the speed (perhaps slowed down depending on angle) and the bullet should fly off again.
@SurreyMuso Thank you for the help so far! I don’t think I’ve implemented your suggestion correctly, as I’m still not used to using c# for unity. Here is my abysmal attempt at implementing it. As you’d probably expect, unity came up with an error on line 36.`using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
public float speed;
public float lifetime;
public float distance;
public int damage;
public float offset;
public LayerMask whatIsSolid;
private float oppositeSpeed;
Vector2 velocity;
private void Start()
{
oppositeSpeed = (speed - (speed * 2));
}
private void Update()
{
RaycastHit2D hitInfo = Physics2D.Raycast(transform.position, transform.up, distance, whatIsSolid);
if (hitInfo.collider != null) {
if (hitInfo.collider.CompareTag("Player")) {
Debug.Log("Player has taken damage!");
hitInfo.collider.GetComponent<CharacterControl>().TakeDamage(damage);
DestroyProjectile();
}
if (hitInfo.collider.CompareTag("Ground")) {
DestroyProjectile();
}
if (hitInfo.collider.CompareTag("Shield")) {
oppositeSpeed = speed;
transform.rotation = Vector2.Reflect(velocity.normalized, hitInfo.normal);
}
}
transform.Translate(Vector2.up * speed * Time.deltaTime);
}
void DestroyProjectile()
{
Destroy(gameObject);
}
}
`