Jump to content
Unity Insider Forum

Event funktioniert nicht


Kalicronic

Recommended Posts

Hallo Leutz,

Ich bin gerade dabei mit Unity in C# zu arbeiten. Dabei habe ich ein Verständnis Problem mit Events. Ich habe eine Klasse, die Clicks und Touches erkennt. Nachdem also einer erkannt wurde, möchte ich das ein Event ausgelöst wird und etwas an eine andere Klasse schickt. Leider Funktioniert das nur zur hälfte.

Das vorhandene Event funktioniert zu der Klasse in dem die Spieler Bewegung stattfindet. Eine andere klasse in dem ich die Kamera nach einem Klick auf den Spieler bewegen möchte, wird das Event nicht ausgelöst.

Per Debug.Log sehe ich das der bei einem Klick auf dem Spieler auch der Spieler wirklich angeklickt wird, aber in der Klasse für die Kamera wird mir kein Debug.Log ausgegeben.

Ich poste mal die Klasse für die Klick und Touche Erkennung und die der Camera Behandlung.

using UnityEngine;

public class ClickAndTouchHandling : MonoBehaviour
{
    private float holdTime = 0.3f;
    private float tabClickTime = 0;
    
    // Events
    public delegate void UnityEventHandler(RaycastHit hit);
    public static event UnityEventHandler shortClick;

    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        ClickTouchHandling();
    }

    private void ClickTouchHandling()
    {
        Vector2 inputType;

        if (Input.touchCount > 0 || Input.GetMouseButton(0)) // timer to check short touch
        {
            tabClickTime += Time.deltaTime;
        }

        if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Ended) // single touch release
        {
            inputType = Input.GetTouch(0).position;
            InputHandling(inputType);            
        }

        if (Input.GetMouseButtonUp(0)) // single mousebutton release
        {
            inputType = Input.mousePosition;
            InputHandling(inputType);
        }
    }

    private void InputHandling(Vector2 inputType)
    {        
        if (tabClickTime <= holdTime) // defined short touch
        {
            RaycastHit hit = new RaycastHit();
            Ray ray = Camera.main.ScreenPointToRay(inputType);
            if (Physics.Raycast(ray, out hit, 100.0f))
            {
                Debug.Log(hit.transform.name);

                if (hit.transform.name == "Player" || hit.transform.name == "Air_iland_1")
                {
                    shortClick(hit); // Event
                }
            }            
        }
        tabClickTime = 0;
    }
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CamController : MonoBehaviour
{
	/*-----some deklarations-----*/

    Vector3 playerInfo;
    private Vector3 oldCamVec;

    private bool playerSelected = false;   

    // Use this for initialization
    void Start()
    {        
        ClickAndTouchHandling.shortClick += playerSelect;
    }

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

    private void playerSelect(RaycastHit hit)
    {
        Debug.Log("shortClick!");
        if (playerSelected)
        {
            playerSelected = false;
            CreatureHudGO.SetActive(false);
        }
        else
        {
            oldCamVec = mainCamera.transform.position;
            playerSelected = true;
            CreatureHudGO.SetActive(true);
        }
    }    
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Time.deltaTime enthält doch nur die Zeit die für den letzten Roundtrip vergangen ist. Heißt wenn du länger als 0,3 sekunden für den letzen roundtrip gebraucht hast wird nichts gemacht. Ich vermute das hier dann auch der Fehler liegen könnte entferne mal das erste if in InputHandling.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nein, Leider ist das nicht das Problem, hab es auch ausprobiert.

Ich habe aber auch schon oben beschrieben das er das Event auslöst, aber halt nur zu der einen Klasse. Zu der CamController-Klasse nur nicht und wie gesagt er zeigt mir im Debug an das er auch das richtige Objekt und alles erkennt.

Also es wird im prinzip nur das Event nicht ausgelöst zu der CamController Klasse.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Oh Gott!!! Das war es.

Das Script befand sich zwar im Camera Object, aber aus irgendeinen Grund hat er es nicht richtig geladen. Habe es gelöscht und nochmal dem Camera Object hinzugefügt.

 

Danke =D

 

Kurze Frage noch: Ist es denn Sinnvoll das Klick und Touches in einer Klasse auszulagern und über Events zu steuern oder gibt es da alternativen wie Observer, usw.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Zwar off topic, aber die Zeilen:

public delegate void UnityEventHandler(RaycastHit hit);
public static event UnityEventHandler shortClick;

könnte man mit einem Einzeiler austauschen:

public static event Action<RaycastHit> shortClick;

.NET bietet mit "Action" (delegate ohne Rückgabewert) und "Func" (Delegate mit Rückgabewert) von Haus aus zwei Delegates, die eigentlich so gut wie alle Anwendungsfälle Abdecken. Vor allem dann nützlich, wenn man stark auf functionale Programmierung mit Lambdas setzt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Und was mir noch aufgefallen ist, du solltest vor dem Aufruf den delagete auf null prüfen, sonst fliegt eine Exception, wenn niemand zuvor das Event abonniert hat. 

Am besten lagert man es in eine separate Methode aus, hier eine Thread-safe variante:

{   
    private void InputHandling(Vector2 inputType)
    {        
        if (tabClickTime <= holdTime) // defined short touch
        {
            RaycastHit hit = new RaycastHit();
            Ray ray = Camera.main.ScreenPointToRay(inputType);
            if (Physics.Raycast(ray, out hit, 100.0f))
            {
                Debug.Log(hit.transform.name);

                if (hit.transform.name == "Player" || hit.transform.name == "Air_iland_1")
                {
                    OnShortClick(hit); // Event
                }
            }            
        }
        tabClickTime = 0;
    }
        
    private void OnShortClick(RaycastHit hit)
    {
        var handler = shortClick;
        if(handler != null)
        {
            handler(hit);
        }
    }
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 20 Stunden schrieb Kalicronic:

Auf jeden Fall vielen dank für die kleinen Optimierungen.

Ich nutze so gut wie nie var. Hat das einen genaueren Grund das du es vorher in eine var steckst?

var kann man anstelle eines Typen schreiben, aber nur an stellen wo aus dem Kontext heraus ersichtlich ist, was für einem Typ man bekommt.
Ob man var benutzt oder den ganzen Type auschreibt ist in den meisten Fällen Geschmacksache, das Produkt nach dem Kompilieren ist das selbe. Bei sehr langen Typen oder wenn man noch gar nicht genau weiß was man zurückbekommt, ist var dann doch sehr hilfreich.

Durch das kopieren in eine lokale Variable wird es thread save. Wenn ein anderer Thread genau zu dem Zeitpunkt, wo du shortClick aufrufst auf diese variable schreibend zugreift (in der Regel einen Handler hinzufügt oder entfernt), dann knallts und de erhältst eine Exception.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...