In my game, when a key is pressed, the player must shoot an arrow with his bow. When the arrow is created, it follows a certain trajectory and if it encounters an enemy (which has the "Damageable" component inside it) it is destroyed, but if it encounters a wall the arrow must stop, because it is as if it were stuck in the wall.
However, a small problem occurred during the test. When it hits the enemy it disappears normally, but when it hits a wall (which is a Tilemap) it sometimes stops as soon as it hits it (as it should), sometimes it goes all the way through it and stops on the opposite side, like it happens in the image below.
[Here is an example of what happens.]
I tried using a FixedUpdate method and a Cast method to make it always check for collisions with the tilemap and then set a boolean that makes the speed zero.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//QUESTO SCRIPT GESTISCE TUTTI I COMANDI RELATIVI AL PROIETTILE
public class Projectile : MonoBehaviour
{
public int damage = 10;
public Vector2 moveSpeed = new Vector2(30f, 0);
public Vector2 knockback = new Vector2(1f, 0);
public ContactFilter2D castFilter;
CircleCollider2D arrowHitbox;
RaycastHit2D[] wallHits = new RaycastHit2D[5];
[SerializeField]
private bool _isMoving = true;
public bool IsMoving
{
get { return _isMoving; }
set
{
_isMoving = value;
if(_isMoving == false)
{
rb.velocity = Vector3.zero;
rb.gravityScale = 0;
}
}
}
private Vector2 _moveDirection = Vector2.right;
public Vector2 MoveDirection
{
get { return _moveDirection; }
set { _moveDirection = value; }
}
Rigidbody2D rb;
void Awake()
{
rb = GetComponent<Rigidbody2D>();
arrowHitbox = GetComponent<CircleCollider2D>();
}
void Start()
{
rb.velocity = new Vector2(moveSpeed.x * transform.localScale.x, moveSpeed.y);
MoveDirection = (gameObject.transform.localScale.x > 0) ? Vector2.right : Vector2.left;
}
void FixedUpdate()
{
IsMoving = !(arrowHitbox.Cast(MoveDirection, wallHits, 0) > 0);
}
private void OnTriggerEnter2D(Collider2D collision)
{
Damageable damageable = collision.GetComponent<Damageable>();
if(damageable != null && IsMoving)
{
Vector2 deliveredKnockback = transform.localScale.x > 0 ? knockback : new Vector2(-knockback.x, knockback.y);
bool gotHit = damageable.Hit(damage, deliveredKnockback);
if (gotHit) //Debug per controllare se il player è stato colpito.
{
Debug.Log(collision.name + " hit for " + damage);
}
Destroy(gameObject);
}
}
}
Since this wasn't working well either, I tried setting the Geometry Type of the CompositeCollider2D component to "Polygon" and it seems to work fine.
Is it possible to solve this problem in a more effective way? I'm also afraid that the polygon mode will weigh down the game.
Thank you.
