Player Collision with Goomba Not Triggering Death - Unity Debugging Issue

fumiko, that is the player, has “playermovement2” and “player” script, there is a small renderer and a big renderer, but I only have content in the small one, the content of the big renderer is none. Goomba, the enemy, has 3 scripts called goomba, entity movement, animatedsprite, and I also have a game manager.Now, if my character moves and touches the goomba, the goomba flattens and disappears, but if the goomba hits me, the goomba turns back and continues moving, the player must die.When I add debug to the player hit code, such a message does not appear, but when the player kills the goomba, my debug works, that is, flatten and hit methods work. First of all, the player script:

 using System.Collections;
using UnityEngine;

public class Player : MonoBehaviour
{
    public CapsuleCollider2D capsuleCollider { get; private set; }
    public PlayerMovement movement { get; private set; }
    public DeathAnimation deathAnimation { get; private set; }

    public PlayerSpriteRenderer smallRenderer;
    public PlayerSpriteRenderer bigRenderer;
    private PlayerSpriteRenderer activeRenderer;

    //public bool big => bigRenderer.enabled;
    public bool dead => deathAnimation.enabled;
    public bool starpower { get; private set; }

    private void Awake()
    {
        capsuleCollider = GetComponent<CapsuleCollider2D>();
        movement = GetComponent<PlayerMovement>();
        deathAnimation = GetComponent<DeathAnimation>();
        activeRenderer = smallRenderer;
    }

    public void Hit()
    {
        if (starpower)
        {
            return; // Eğer starpower aktifse zarar görmez.
        }

        // Ölüm animasyonu ve sahnenin yeniden yüklenmesi.
        GetComponent<Animator>().SetTrigger("Death");
        Destroy(gameObject, 1f); // 1 saniye sonra yok olur.
        GameManager.Instance.ResetLevel(); // Sahneyi yeniden başlat.
    }

    public void Death()
    {
        smallRenderer.enabled = false;
        //bigRenderer.enabled = false;
        deathAnimation.enabled = true;

        GameManager.Instance.ResetLevel(3f);
    }

    public void Grow()
    {
        smallRenderer.enabled = false;
        //bigRenderer.enabled = true;
        //activeRenderer = bigRenderer;

        capsuleCollider.size = new Vector2(1f, 2f);
        capsuleCollider.offset = new Vector2(0f, 0.5f);

        StartCoroutine(ScaleAnimation());
    }

    public void Shrink()
    {
        smallRenderer.enabled = true;
        //bigRenderer.enabled = false;
        activeRenderer = smallRenderer;

        capsuleCollider.size = new Vector2(1f, 1f);
        capsuleCollider.offset = new Vector2(0f, 0f);

        StartCoroutine(ScaleAnimation());
    }

    private IEnumerator ScaleAnimation()
    {
        float elapsed = 0f;
        float duration = 0.5f;

        while (elapsed < duration)
        {
            elapsed += Time.deltaTime;

            if (Time.frameCount % 4 == 0)
            {
                smallRenderer.enabled = !smallRenderer.enabled;
                //bigRenderer.enabled = !smallRenderer.enabled;
            }

            yield return null;
        }

        smallRenderer.enabled = false;
       // bigRenderer.enabled = false;
        activeRenderer.enabled = true;
    }

    public void Starpower()
    {
        StartCoroutine(StarpowerAnimation());
    }

    private IEnumerator StarpowerAnimation()
    {
        starpower = true;

        float elapsed = 0f;
        float duration = 10f;

        while (elapsed < duration)
        {
            elapsed += Time.deltaTime;

            if (Time.frameCount % 4 == 0)
            {
                activeRenderer.spriteRenderer.color = Random.ColorHSV(0f, 1f, 1f, 1f, 1f, 1f);
            }

            yield return null;
        }

        activeRenderer.spriteRenderer.color = Color.white;
        starpower = false;
    }

}

PlayerMovement2 Script: using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement2 : MonoBehaviour
{
    public float speed = 5f; // Karakterin hareket hızı
    public float jumpForce = 10f; // Zıplama gücü
    private bool isGrounded = true; // Karakter zeminde mi?
    private Vector2 velocity;
    private bool isJumping;

    private Animator animator; // Animator bileşeni
    private SpriteRenderer spriteRenderer; // Sprite Renderer bileşeni
    private Rigidbody2D rb; // Fizik için Rigidbody2D bileşeni

    private void Start()
    {
        // Gerekli bileşenleri al
        animator = GetComponent<Animator>();
        spriteRenderer = GetComponent<SpriteRenderer>();
        rb = GetComponent<Rigidbody2D>();
    }

    private void Update()
    {
        // Yatay eksendeki hareket girişini al
        float move = Input.GetAxis("Horizontal");

        // Karakteri hareket ettir
        transform.Translate(new Vector3(move, 0, 0) * speed * Time.deltaTime);

        // Yürüyüş animasyonunu kontrol et
        if (move != 0)
        {
            animator.SetBool("isWalking", true);
            spriteRenderer.flipX = move < 0; // Sol tarafa giderken sprite'ı çevir
        }
        else
        {
            animator.SetBool("isWalking", false);
        }

        // Zıplama işlemi
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            rb.AddForce(new Vector2(0, jumpForce), ForceMode2D.Impulse);
            animator.SetBool("isJumping", true); // Zıplama animasyonunu başlat
            isGrounded = false; // Karakter artık havada
        }
    }

    private void FixedUpdate()
    {
        // Rigidbody ile fiziksel hareket
        rb.velocity = new Vector2(Input.GetAxis("Horizontal") * speed, rb.velocity.y);
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        // Eğer karakter zemine çarparsa
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = true;
            animator.SetBool("isJumping", false); // Zıplama animasyonunu durdur
        }
        if (collision.gameObject.layer == LayerMask.NameToLayer("Enemy"))
        {
            // Bounce off enemy head
            if (transform.DotTest(collision.transform, Vector2.down))
            {
                velocity.y = jumpForce / 2f;
                animator.SetBool("isJumping", true);
            }
        }
        else if (collision.gameObject.layer != LayerMask.NameToLayer("PowerUp"))
        {
            // Stop vertical movement if mario bonks his head
            if (transform.DotTest(collision.transform, Vector2.up))
            {
                velocity.y = 0f;
            }
        }

    }
}
entity movement : using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
public class EntityMovement : MonoBehaviour
{
    public float speed = 1f;
    public Vector2 direction = Vector2.left;

    private Rigidbody2D rb;
    private Vector2 velocity;

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

    private void OnBecameVisible()
    {
#if UNITY_EDITOR
        enabled = !EditorApplication.isPaused;
#else
        enabled = true;
#endif
    }

    private void OnBecameInvisible()
    {
        enabled = false;
    }

    private void OnEnable()
    {
        rb.WakeUp();
    }

    private void OnDisable()
    {
        rb.velocity = Vector2.zero;
        rb.Sleep();
    }

    private void FixedUpdate()
    {
        velocity.x = direction.x * speed;
        velocity.y += Physics2D.gravity.y * Time.fixedDeltaTime;

        rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);

        if (rb.Raycast(direction))
        {
            direction = -direction;
        }

        if (rb.Raycast(Vector2.down))
        {
            velocity.y = Mathf.Max(velocity.y, 0f);
        }

        if (direction.x > 0f)
        {
            transform.localEulerAngles = new Vector3(0f, 180f, 0f);
        }
        else if (direction.x < 0f)
        {
            transform.localEulerAngles = Vector3.zero;
        }
    }
}
AnimatedSprite kodu : using UnityEngine;

[RequireComponent(typeof(SpriteRenderer))]
public class AnimatedSprite : MonoBehaviour
{
    public Sprite[] sprites;
    public float framerate = 1f / 6f;

    private SpriteRenderer spriteRenderer;
    private int frame;

    private void Awake()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
    }

    private void OnEnable()
    {
        InvokeRepeating(nameof(Animate), framerate, framerate);
    }

    private void OnDisable()
    {
        CancelInvoke();
    }

    private void Animate()
    {
        frame++;

        if (frame >= sprites.Length)
        {
            frame = 0;
        }

        if (frame >= 0 && frame < sprites.Length)
        {
            spriteRenderer.sprite = sprites[frame];
        }
    }

}  game manager kodu : using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance { get; private set; }

    public int world { get; private set; } = 1;
    public int stage { get; private set; } = 1;
    public int lives { get; private set; } = 3;
    public int coins { get; private set; } = 0;

    private void Awake()
    {
        if (Instance != null)
        {
            DestroyImmediate(gameObject);
        }
        else
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
    }

    private void OnDestroy()
    {
        if (Instance == this)
        {
            Instance = null;
        }
    }

    private void Start()
    {
        Application.targetFrameRate = 60;
        NewGame();
    }

    public void NewGame()
    {
        lives = 3;
        coins = 0;

        LoadLevel(1, 1);
    }

    public void GameOver()
    {
        NewGame();
    }

    public void LoadLevel(int world, int stage)
    {
        this.world = world;
        this.stage = stage;

        SceneManager.LoadScene($"{world}-{stage}");
    }

    public void NextLevel()
    {
        LoadLevel(world, stage + 1);
    }

    public void ResetLevel(float delay)
    {
        CancelInvoke(nameof(ResetLevel));
        Invoke(nameof(ResetLevel), delay);
    }

    public void ResetLevel()
    {
        lives--;

        if (lives > 0)
        {
            LoadLevel(world, stage);
        }
        else
        {
            GameOver();
        }
    }

    public void AddCoin()
    {
        coins++;

        if (coins == 100)
        {
            coins = 0;
            AddLife();
        }
    }

    public void AddLife()
    {
        lives++;
    }

}
goomba kodu :using UnityEngine;

public class Goomba : MonoBehaviour
{
    public Sprite flatSprite;

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Player") && collision.gameObject.TryGetComponent(out Player player))
        {
            if (player.starpower)
            {
                Hit();
            }
            else if (collision.transform.DotTest(transform, Vector2.down))
            {
                Flatten();
            }
            else
            {
                player.Hit();
            }
        }
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.gameObject.layer == LayerMask.NameToLayer("Shell"))
        {
            Hit();
        }
    }

    private void Flatten()
    {
        GetComponent<Collider2D>().enabled = false;
        GetComponent<EntityMovement>().enabled = false;
        GetComponent<AnimatedSprite>().enabled = false;
        GetComponent<SpriteRenderer>().sprite = flatSprite;
        Destroy(gameObject, 0.5f);
    }

    private void Hit()
    {
        GetComponent<AnimatedSprite>().enabled = false;
        GetComponent<DeathAnimation>().enabled = true;
        Destroy(gameObject, 3f);
    }

}

I think in EntityMovement.FixedUpdate you shoot a raycast forward, and if it hits something turn around. You turn it around before there is any collision.

To fix this you can either change the logic so the turning around happens in OnCollisionEnter, or check the tag of the object hit by the raycast and if it’s the player manually call a Kill() method

1 Like

Thank you, I tried the method you mentioned first ,I deleted the direction change code in the fixupdate code,I updated the code of OnCollisionEnter,

private void OnCollisionEnter2D(Collision2D collision)
{
// Player ile çarpışma kontrolü
if (collision.gameObject.CompareTag(“Player”) && collision.gameObject.TryGetComponent(out Player player))
{
if (player.starpower) // Eğer Player starpower modundaysa Goomba ölür
{
Hit(); // Goomba’yı öldür
}
else if (collision.transform.DotTest(transform, Vector2.down)) // Player üstüne zıpladıysa
{
Flatten(); // Goomba’yı yassılaştır
}
else
{
Debug.Log(“Çalisti”);

        player.Hit(); // Player'ı öldür
    }
}
else // Diğer nesnelerle çarpışma kontrolü
{
    // Eğer çarptığı nesne Player değilse yön değiştir
    direction = -direction;
}
}private void FixedUpdate()
{
// Hareketi hesapla
velocity.x = direction.x * speed;
velocity.y += Physics2D.gravity.y * Time.fixedDeltaTime;

// Rigidbody pozisyonunu güncelle
rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);

    


// Hareket yönüne göre yüz yönünü ayarla
if (velocity.x > 0f)
{
    transform.localEulerAngles = Vector3.zero; // Yön sağa
}
else if (velocity.x < 0f)
{
    transform.localEulerAngles = new Vector3(0f, 180f, 0f); // Yön sola
}

// Öndeki nesneyi kontrol et (Raycast ile)
//if (rb.Raycast(direction))
// {

// direction = -direction; // Herhangi bir engele çarptığında yön değiştir
// }

// Yerde olduğundan emin ol
if (rb.Raycast(Vector2.down))
{
    velocity.y = Mathf.Max(velocity.y, 0f);
}
}
```Now when the player hits the goomba, the goomba flattens and dies, this is okay, but this time when the goomba hits the player, the player should die but the goomba dies again.