C# UnityEvent birden fazla tetikleniyor

706111

Hectopat
Katılım
28 Ağustos 2023
Mesajlar
6.020
Makaleler
1
Çözümler
29
Arkadaşlar merhaba.

Unity3D'de Event Sistemi yaptım. Kodlarım böyle;

C#:
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Events;

public class FishManager : MonoBehaviour
{


    // Instance
    public static FishManager Instance;

    // Fish List
    [SerializeField] List<GameObject> fishes;
    [SerializeField] int activeFish;

    // FishPool
    public Queue<GameObject> fishPool = new Queue<GameObject>();
    [SerializeField] public int poolSize;


    // RayCast
    RaycastHit2D hit;
    [SerializeField] Camera cam;



    // Action List Fish

    [System.Serializable] public class FishTriggerEvent: UnityEvent<GameObject>{}

    public FishTriggerEvent fishTriggerEvent;






    System.Random rand = new System.Random();
    GameObject fish;
    int random = 0;





    public void FillPool()
    {


        for (int i = 0; i < poolSize; i++)
        {
            random = rand.Next(0, fishes.Count);
            fish = Instantiate(fishes[random]);
            fish.SetActive(false);

            fishPool.Enqueue(fish);
        }

        for (int i = 0; i < activeFish; i++)
        {
            SpawnFish();
        }
    }


    public void SpawnFish()
    {

        if (fishPool.Count <= 0)
        {
            random = rand.Next(0, fishes.Count);
            fish = Instantiate(fishes[random]);
            fish.SetActive(false);
            fishPool.Enqueue(fish);
        }

        fish = fishPool.Dequeue();

        fish.SetActive(true);


    }



    private void Awake()
    {
        if (!Instance)
        {
            Instance = this;
        
        
            FillPool();
        }
        else
        {
            Destroy(gameObject);
        }
    }



    //
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Click();
        }
    }


    public void Click()
    {
        hit = Physics2D.Raycast(cam.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
        if (hit.collider)
        {
      
            TapFish(hit.collider.gameObject);

        }
    }

 
    bool oneTime = false;
    public void TapFish(GameObject go)
    {

        fishTriggerEvent?.Invoke(go);
        SpawnFish();
    }
}


C#:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using TMPro;
using UnityEngine.Events;


public class FishMove : MonoBehaviour
{


 

    // Screen Cam Location;
    float x = 0f;
    float y = 0f;

    // Finish;
    Vector2 finish;

    // GameObject Fish
    [SerializeField] GameObject fish;


    // Fish Speed;
    [SerializeField] float speed;

    // Fish point;
    [SerializeField] GameObject pointObject;
    [SerializeField] TextMeshPro pointText;
    [SerializeField] int point;

    // Score Pos;
    Vector2 scorePos;

    // Move Point or Fish
    bool pointMove = false;
    bool isPointAdd = false;


    // Particle System

    [SerializeField] ParticleSystem bubbleEffect;



    public void Start()
    {
    
        FishManager.Instance.fishTriggerEvent.AddListener(GetPoint);

        x = ScreenManager.instace.x / 2;
        y = ScreenManager.instace.y / 2;

        pointText.text = $"{point}";
        pointObject.SetActive(false);

        scorePos = PointManager.Instance.scoreObject.transform.position;


        Init();




    }


 


 

    void GetPoint(GameObject go)
    {
        if (fish == go)
        {
            Debug.Log("Çalışt");
            pointObject.SetActive(true);
            pointObject.transform.position = fish.transform.position;
            pointText.text = $"{point}";
            fish.SetActive(false);
            bubbleEffect.transform.position = fish.transform.position;
            bubbleEffect.Play();



            pointMove = true;






        }
    }









    void Update()
    {


        if (pointMove)
        {
            MovePoint();

        }
        else
        {
            MoveFish();
        }





    }


    void MoveFish()
    {
        if ((finish - (Vector2)fish.transform.position).sqrMagnitude != 0f)
        {

            fish.transform.position = Vector2.MoveTowards(fish.transform.position,
                                            finish, speed * Time.deltaTime);




        }
        else
        {

            FishManager.Instance.SpawnFish();
            ReturnPool();

        }
    }



    void MovePoint()
    {
        if ((scorePos - (Vector2)pointObject.transform.position).sqrMagnitude != 0f)
        {

            pointObject.transform.position = Vector2.MoveTowards(pointObject.transform.position,
                                            scorePos, 7f * Time.deltaTime);




        }
        else
        {

      

            if (!bubbleEffect.isPlaying)
            {
          
                ReturnPool();
            }

            if (!isPointAdd)
            {
                PointManager.Instance.addPoint(point);
                pointText.text = "";
                isPointAdd = true;
            }



        }
    }



    void ReturnPool()
    {

        FishManager.Instance.fishPool.Enqueue(gameObject);
        Init();
        gameObject.SetActive(false);
    }



    public void Init()
    {





        //Point
        pointObject.SetActive(false);
        pointMove = false;
        isPointAdd = false;
  


        // Fish Area
        fish.SetActive(true);

        fish.transform.localScale = new Vector3(1, 1, 1);

        if (UnityEngine.Random.Range(0, 2) == 0)
        {

            fish.transform.position = new Vector2(-x - 1f, UnityEngine.Random.Range(y, -y));

            finish = new Vector2(x + 1f, UnityEngine.Random.Range(y, -y));

        }
        else
        {
            fish.transform.position = new Vector2(x + 1f, UnityEngine.Random.Range(y, -y));
            finish = new Vector2(-x - 1f, UnityEngine.Random.Range(y, -y));
            fish.transform.localScale = new Vector3(-1, 1, 1);
        }




    }




}


Sorunum şu.

Şimdi diyelim balık nesnesinde BoxCollider2D var. FishManager'daki if ile fare dinlemesi olayı gerçekleştiği zaman, FishMove içindeki GetPoint metodu 3-4 kere tetikleniyor yani.

1 kere tetiklenmesi lazım ama olmuyor.

Nedeni anlamadım yani. Input.GetMousePositon(0) şartı, 3-4 kere mi tetikletiyor. Fazla fazla puan veriyor.
 
Son düzenleme:
Kodunuzu göz ucuyla inceledim. Sorun büyük ihtimalle update() içinde fare tıklama kontrolü ile ilgili.

Input.GetMouseButtonDown(0)
ile fare tıklaması algılandığında, o karede birden fazla kez balığın TapFish metodu çağrılıyor olabilir, çünkü Update()her karede çalışır ve çok hızlı bir şekilde birden fazla kez tıklama algılanıyor olabilir. Bu da GetPoint metodunun 3-4 kez tetiklenmesine yol açıyor.

Çözüm için zamanlama kontrolü eklemeyi dene. Yapamazsan yardımcı olmaya çalışırım.
 
Tam olarak o nedir hocam? Yapayım hemen.
 
Yanlış anımsamıyorsam cooldown süresi ekliyorduk. Ben ekleyebileceğiniz şeyi burada paylaşayım ama biraz zaman alabilir bekleyin.
 
Kod:
bool isTapped = false;
float tapCooldown = 0.2f; // burada süreyi siz belirleyin isterseniz
float tapCooldownTimer = 0f;

void Update()
{
    tapCooldownTimer -= Time.deltaTime; // süreyi korusun

    if (Input.GetMouseButtonDown(0) && tapCooldownTimer <= 0f)
    {
        Click();
        tapCooldownTimer = tapCooldown; // süreyi resetlesin
    }
}

public void TapFish(GameObject go)
{
    if (isTapped) return;

    isTapped = true; // ilk seferde true yap
    fishTriggerEvent?.Invoke(go); // balığı tetikle
    SpawnFish(); // yeni balık yap
}

Bunu direkt en sona eklemeniz sorun oluşturmuyordu sanırım. Unity de metot sırası önemli değildi diye hatırlıyorum.
 
Son düzenleme:
Hocam if(is trapped) return; satırını kaldırmayınca tetiklenme olmuyor. Onu yorum satırına alınca yine çokça tetikleniyor.
 
Tetikleme bir kez olduktan sonra mı bir daha olmuyor hiç mi olmuyor?
Evet bir tane balık nesnesine tıkladığım zaman çalışıyor ama diğerlerine bir daha tıklayamıyorum. Ekranda bir sürü balık var ondan.
 
O zaman if (isTapped) return balık tıklandıktan sonra bir daha tıklanmayı engelliyor. Tıklama sonrasında isTapped durumunu sıfırlamadığın için bu kontrol sürekli balık tıklandı kalıyor.

Balık tıklandığında durum isTapped = true. Balığın puan kazanma işlemi tamamlandıktan sonra tekrar false yapalım bu değişkeni.
Kod:
bool isTapped = false;
float tapCooldown = 0.2f;
float tapCooldownTimer = 0f;

void Update()
{
    tapCooldownTimer -= Time.deltaTime;

    if (Input.GetMouseButtonDown(0) && tapCooldownTimer <= 0f)
    {
        Click();
        tapCooldownTimer = tapCooldown;
    }
}

public void TapFish(GameObject go)
{
    if (isTapped) return;

    isTapped = true;
    fishTriggerEvent?.Invoke(go);
    SpawnFish();
}

void MovePoint()
{
    if ((scorePos - (Vector2)pointObject.transform.position).sqrMagnitude != 0f)
    {
        pointObject.transform.position = Vector2.MoveTowards(pointObject.transform.position, scorePos, 7f * Time.deltaTime);
    }
    else
    {
        if (!bubbleEffect.isPlaying)
        {
            ReturnPool();
        }

        if (!isPointAdd)
        {
            PointManager.Instance.addPoint(point);
            pointText.text = "";
            isPointAdd = true;
            isTapped = false;
        }
    }
}

Kafanızın karışmaması için açıklamaları sildim.

Az önceki kodu silip yerine bunu koyun.
 
Bu siteyi kullanmak için çerezler gereklidir. Siteyi kullanmaya devam etmek için çerezleri kabul etmelisiniz. Daha Fazlasını Öğren.…