C# Unity3D nesneye dokunduğumuz zaman sıfırlanması sağlamak

706111

Hectopat
Katılım
28 Ağustos 2023
Mesajlar
6.020
Makaleler
1
Çözümler
29
Arkadaşlar merhaba. Balık vurma oyunu yapıyorum da. Bir sürü balık olacak ve ekrana salınacak hep. Balıkları gerek object pool'da çekiyor, gerekse oluşturma ve yoketme metotlarıyla sahnede yönetiyoruz.

Öncelikle elimizde bir nesne var. Nesnenin Move scripti var. Move scripti içinde nesnenin varacağı konum vardır. Bu vuracağı konu rastgele oluşur.
Nesne, varacağı konuma varırsa tekrardan rastgele vuracağı bir konum oluşuyor.

1000 tane böyle nesne var. Gerek sırayla oluşup ekrana belli aralıkla salınıyorlar, gerekse object pool'dan belli arayla salınıyorlar. Ekranda rastgele varacağı konuma, nesneleri üzerine tıkladığımız zaman performansı etkilemeden rastgele oluşmasını sağlamak isterim.

Aklıma üç yol geldi;
1. Nesne üzerinde Update fonksiyonu içinde RayCast ile erişip yaparım ama performans sorunu olur mu?
2. Bir Input Manager eklemek. Input Manager sahnede olacak ve RayCast ile erişilen nesnelerin Move scriptine erişilip, vuracağı konum tekrar hesap edilecek. Bunda da performans sorunu olur mu? Çünkü dakikada 40 kere tıklanacak bu nesnelere ve 40 kere GetComponent yapısı ile bileşenlere erişilecek.
3. OnMouseDown metodu var birde. Bu metot ile nesneye tıkladığımız zaman sıfırlarım. Aklıma en çok yatan bu. Move scriptine ekler, tıklanma olayında tetiklenir.

Başka yol gelmedi. Çok yol, yöntem bilmem çünkü.

Tamamen performans sorununu önlemek için yöntem lazımdır. Önerilerinize açığım.

Arkadaşlar birde bu nesnelerin sahnede oluşma zamanı vardır, performansa etkisi vardır. Bu kısmı dikkate almayın. Odağım nesneler ile etkileşim süreci yani.

@count, @TheAny, @900, @bitwise, @RaSGooL
 
Son düzenleme:
Raycast ile yapılması en mantıklı ama bunu obje içinde değil de oltanin olduğu scriptten çağır

Ray kodunu yazarken de ilk başa onMouseButtonDown şartını koyarsan optimizasyon sorunu olmaz.
 
Raycast ile yapılması en mantıklı ama bunu obje içinde değil de oltanin olduğu scriptten çağır

Ray kodunu yazarken de ilk başa onMouseButtonDown şartını koyarsan optimizasyon sorunu olmaz.
RayCast ile yapayım ama her objenin bir scriptine/componentine erişmem gerekiyor. Ondan performansı sorunu oluşturmaz mı bu yöntem?

Oyunumda olta yoktur. Her balığın kendi scripti vardır.

Dediğini yöntemi yapmaya çalışacağım. Tüm nesnelerin tek bir Scripti referans almasını sağlayacağım.
 
RayCast ile yapayım ama her objenin bir scriptine/componentine erişmem gerekiyor. Ondan performansı sorunu oluşturmaz mı bu yöntem?

Oyunumda olta yoktur. Her balığın kendi scripti vardır.
Yanlış anladıysam düzeltin beni lütfen

Mouse ile balığa tıkandığı zaman tıklaman balığın üzerindeki vector3 değerinin değeri rastgele yeni değer atanacak

Bunu anladım ben. Eğer yanlış anladıysam tekrar açıklayabilir misiniz? Optimal yolu bulalım
 
Yanlış anladıysam düzeltin beni lütfen

Mouse ile balığa tıkandığı zaman tıklaman balığın üzerindeki x değişkeninin değeri 0 olacak
Hocam ben direkt balığın kodunu atayım. OnMouseDown ile yapmıştım;
C#:
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using TMPro;

public class FishMove : MonoBehaviour
{
    // Finish location
    Vector2 finish;

    // Fish Specs;
    [SerializeField] FishScript fishScript;

    // Bubble
    [SerializeField] ParticleSystem bubbleRef;
    ParticleSystem bubble;


 


    // Point
    [SerializeField] GameObject pointRef;
    GameObject pointObject;
    TextMeshPro pointText;
    bool pointIsActive;
    bool addPoint;
    int point = 0;
    Vector2 scoreLocation;
    float pointSpeed = 7f;

 
 



    // Speed
    float speed = 0f;



    // Start is called before the first frame update
    void Start()
    {
        // Set Bubble
        bubble = Instantiate(bubbleRef);

        // Set Point
        pointObject = Instantiate(pointRef);
        point = fishScript.point;
        pointText = pointObject.GetComponent<TextMeshPro>();
 

        scoreLocation = ScoreManager.INSTANCE.scoreText.transform.position;
 


        Init();




    }

    // Update is called once per frame
    void Update()
    {


        if (pointIsActive)
        {

            if (Vector2.Distance(pointObject.transform.position, scoreLocation) != 0f)
            {
                pointObject.transform.position = Vector2.MoveTowards(pointObject.transform.position,
                                           scoreLocation, pointSpeed * Time.deltaTime);

            }

            else
            {
                if(addPoint){
                    ScoreManager.INSTANCE.AddPoint(point);
                    pointText.text = "";
               
                    addPoint = false;
                }
         
                if(!bubble.isPlaying){
                    sendPool();

                }
            }



        }
        else
        {
            if (Vector2.Distance(transform.position, finish) != 0f)
            {

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




            }
            else
            {

                sendPool();

            }
        }


    }



    void Init()
    {

        transform.position = FishInit.INSTANCE.setLocation();
        finish = FishInit.INSTANCE.setFinishLocation(gameObject);

        transform.localScale = new Vector3(1, 1, 1);
        if (transform.position.x > 0)
        {
            transform.localScale = new Vector3(-1, 1, 1);


        }

 


        speed = fishScript.speed;


        // Point
        pointObject.transform.position = transform.position;
        pointObject.SetActive(false);
        pointIsActive = pointObject.activeInHierarchy;
        addPoint = true;
        pointText.text = $"{point}";
   

        // Bubble

         bubble.transform.position = transform.position;
 
   

    }


    void OnMouseDown()
    {


        bubble.Play();
        pointObject.SetActive(true);

        pointIsActive = pointObject.activeInHierarchy;
   
        pointObject.transform.position = transform.position;
        bubble.transform.position = transform.position;

        transform.position = new Vector2(100, 100);
        //sendPool();

    }


    void sendPool()
    {
        Init();
        FishManager.INSTANCE.fishRemoveScene(gameObject);
    }


}


Kodun işlevi; balığa tıkladığımız zaman onu bir noktaya gönderiyor. Referans aldığı puan ve balon nesnelerinin de işlevleri başlıyor. İşlevleri bitince de balığı tekrar ayarlıyor ve havuza geri gönderiliyor.

Tıklamazsak ise finish noktasına gidiyor, tekrar ayarlanıyor ve havuza geri gönderiliyor.
 
Hocam ben direkt balığın kodunu atayım. OnMouseDown ile yapmıştım;
C#:
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using TMPro;

public class FishMove : MonoBehaviour
{
    // Finish location
    Vector2 finish;

    // Fish Specs;
    [SerializeField] FishScript fishScript;

    // Bubble
    [SerializeField] ParticleSystem bubbleRef;
    ParticleSystem bubble;


 


    // Point
    [SerializeField] GameObject pointRef;
    GameObject pointObject;
    TextMeshPro pointText;
    bool pointIsActive;
    bool addPoint;
    int point = 0;
    Vector2 scoreLocation;
    float pointSpeed = 7f;

 
 



    // Speed
    float speed = 0f;



    // Start is called before the first frame update
    void Start()
    {
        // Set Bubble
        bubble = Instantiate(bubbleRef);

        // Set Point
        pointObject = Instantiate(pointRef);
        point = fishScript.point;
        pointText = pointObject.GetComponent<TextMeshPro>();
  

        scoreLocation = ScoreManager.INSTANCE.scoreText.transform.position;
  


        Init();




    }

    // Update is called once per frame
    void Update()
    {


        if (pointIsActive)
        {

            if (Vector2.Distance(pointObject.transform.position, scoreLocation) != 0f)
            {
                pointObject.transform.position = Vector2.MoveTowards(pointObject.transform.position,
                                           scoreLocation, pointSpeed * Time.deltaTime);

            }

            else
            {
                if(addPoint){
                    ScoreManager.INSTANCE.AddPoint(point);
                    pointText.text = "";
                
                    addPoint = false;
                }
          
                if(!bubble.isPlaying){
                    sendPool();

                }
            }



        }
        else
        {
            if (Vector2.Distance(transform.position, finish) != 0f)
            {

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




            }
            else
            {

                sendPool();

            }
        }


    }



    void Init()
    {

        transform.position = FishInit.INSTANCE.setLocation();
        finish = FishInit.INSTANCE.setFinishLocation(gameObject);

        transform.localScale = new Vector3(1, 1, 1);
        if (transform.position.x > 0)
        {
            transform.localScale = new Vector3(-1, 1, 1);


        }

  


        speed = fishScript.speed;


        // Point
        pointObject.transform.position = transform.position;
        pointObject.SetActive(false);
        pointIsActive = pointObject.activeInHierarchy;
        addPoint = true;
        pointText.text = $"{point}";
    

        // Bubble

         bubble.transform.position = transform.position;
  
    

    }


    void OnMouseDown()
    {


        bubble.Play();
        pointObject.SetActive(true);

        pointIsActive = pointObject.activeInHierarchy;
    
        pointObject.transform.position = transform.position;
        bubble.transform.position = transform.position;

        transform.position = new Vector2(100, 100);
        //sendPool();

    }


    void sendPool()
    {
        Init();
        FishManager.INSTANCE.fishRemoveScene(gameObject);
    }


}


Kodun işlevi, balığa tıkladığımız zaman onu bir noktaya gönderiyor. Referans aldığı puan ve balon nesnelerinin de işlevleri bitince, balığı tekrar ayarlıyor ve havuza geri gönderiyor.
Burada onmusedown fonksiyonunu kullanıyorsunuz. Bu fonksiyon birbirine çok yakın objelerde çok sağlıklı çalışmıyor bu yüzden bu fonksiyonla yapmak çok sağlıklı olmayacaktır. Bunun yerine oltadan ray atarak yapmak daha mantıklı olur.

Şu an telefonda olduğum için düzgün yazamıyorum ama size yapmanız kodu tarif edeyim

İlk önce fish move scripti üzerindeki move down fonksiyonunun adını değistirin adi ClickedToFish olsun mesela

Sonrasında olta script üzerinde update kısmına

If (on mouse button down (0) & raycast (out hit)
{
Hit.transform.getcomponent<fishmove>().ClickedToFish()
}

Eğer o sırada tiklanan balığın altındaki diğer balıklarin da bu fonksiyonu çalışsın istiyorsaniz raycastall kullanın. Veya daha kalabalık bir alanı alsın isterseniz spherecast de kullanabilirsiniz

Optimizasyon açısından pek bir sıkıntı olmayacaktır. Çünkü ilk şart on mouse down olduğu ve bu şart false geldiği zaman devamı kontrol edilmediği için optimizasyon sorunu yaratmaz
 
Burada onmusedown fonksiyonunu kullanıyorsunuz. Bu fonksiyon birbirine çok yakın objelerde çok sağlıklı çalışmıyor bu yüzden bu fonksiyonla yapmak çok sağlıklı olmayacaktır. Bunun yerine oltadan ray atarak yapmak daha mantıklı olur.

Şu an telefonda olduğum için düzgün yazamıyorum ama size yapmanız kodu tarif edeyim

İlk önce fish move scripti üzerindeki move down fonksiyonunun adını değistirin adi ClickedToFish olsun mesela

Sonrasında olta script üzerinde update kısmına

If (on mouse button down (0) & raycast (out hit)
{
Hit.transform.getcomponent<fishmove>().ClickedToFish()
}

Eğer o sırada tiklanan balığın altındaki diğer balıklarin da bu fonksiyonu çalışsın istiyorsaniz raycastall kullanın. Veya daha kalabalık bir alanı alsın isterseniz spherecast de kullanabilirsiniz
Hocam birde oyunum 2D olacaktır. Bu raycast fonksiyonlarını tek bir InputManager sınıfı yapıp oradan yapayım ama nesnelerin scriptine erişmek performans kaybı yaratır mı?

Siz bir ara işiniz olmaz ise yazarsanız çok makbule geçer. Ne zaman boş olursanız, detaylıca anlatmak isterseniz buradayım.
 
Hocam birde oyunum 2D olacaktır. Bu raycast fonksiyonlarını tek bir InputManager sınıfı yapıp oradan yapayım ama nesnelerin scriptine erişmek performans kaybı yaratır mı?

Siz bir ara işiniz olmaz ise yazarsanız çok makbule geçer. Ne zaman boş olursanız, detaylıca anlatmak isterseniz buradayım.
Hocam 2d hiç proje geliştirmedim :). Şu ana kadar muhtemelen 25-30 proje geliştirmişimdir ve hepsi 3d idi. 2d konusunda vereceğim bilgi yanlış olabilir bunu baştan söyleyeyim.
2d oyunlarda belki raycast yerine onmousedown yazmak daha mantıklı olabilir. Şu an yazdığınız kodda ne istediğiniz gibi olmadı onu tam anlayamadım ben. Sanırım yeni uyandığım için beynim tam açılmadı 😂
 

Technopat Haberler

Geri
Yukarı