簡體   English   中英

C#Unity - 確定哪個方法影響GameObject

[英]C# Unity - identify which method is affecting a GameObject

我在這里有這個代碼:

public void Move(Transform from, Transform to, float overTime)
{
    StartCoroutine(_Move(from, to, overTime));
}
IEnumerator _Move(Transform from, Transform to, float overTime)
{
    Vector2 original = from.position;
    float timer = 0.0f;
    while (timer < overTime)
    {
        float step = Vector2.Distance(original, to.position) * (Time.deltaTime / overTime);
        from.position = Vector2.MoveTowards(from.position, to.position, step);
        timer += Time.deltaTime;
        yield return null;
    }
}

這很簡單。 它所做的就是隨着時間的推移將GameObject移動到目的地。 我打算將它用於UI動畫目的。 但是,當我想改變它的使用時,事情變得有趣。 例如,我將鼠標懸停在一個按鈕上,該按鈕開始移動。 當它仍然移動時,我可能會再次懸停在它上面,在這種情況下我希望它重新啟動,因此它會停止影響完全相同按鈕功能並重新啟動另一個按鈕 我不知道如何識別同一函數的哪個調用會影響我給定的組件。 或者我應該將此腳本添加到每個對象,以便它只影響那個?

我在這里有很多不同的做法。 首先,如果您的Ui對象已經受到協同程序的影響,您不希望其他協同程序也開始對其進行操作,只需要新的協程。 為了避免這種情況,聲明了一個協程變量:

IEnumerator myCoRoutine

當你第一次鼠標懸停開始這樣的協程:

myCoRoutine = _Move(from, to, overTime);
Start Coroutine(_Move());

但是,你想檢查一個協程是否還沒有運行,如果是的話就停止它,然后開始一個新的,對吧? 所以,這樣做:

if(myCoRoutine !=null) StopCoroutine(mtCoRoutine);
myCoRoutine = _Move(from, to, overTime);
Start Coroutine(_Move());

您可能希望使用OnPointerEnter啟動協同程序

當它仍在移動時,我可能會再次懸停在它上面,在這種情況下我希望它重新啟動,因此它會停止影響完全相同按鈕的功能並重新啟動另一個按鈕。 我不知道如何識別同一函數的哪個調用會影響我給定的組件。 或者我應該將此腳本添加到每個對象,以便它只影響那個?

一種解決方案是將包含協同程序功能的腳本附加到每個 GameObjects。 如果您不想這樣做,那么還有另一種方法可以做到這一點。

首先,僅僅存儲IEnumerator並不足以實際執行此操作。 您需要一種方法來識別在最后一個協同程序中運行的GameObject。

1.獲取可用於標識Object的值。 在這種情況下,具有GetInstanceID()的實例ID應該沒問題。

2.使用一個簡單的struct來保存舊的協同程序信息。

3。最后,創建一個包含實例ID(鍵)和#2結構的字典作為值。

通過這三件事,您可以啟動協程,將其添加到Dictionary 協程完成后,從Dictionary刪除instance ID

下面的代碼將使一個協程控制許多對象,而無需將coroutine函數放在自己的腳本中。 最大的區別是,當新cororutine的呼吁,相同的功能,它停止該對象的舊創建一個新的開始吧。

這就是我使用的。 這是非常好的評論,以便您知道發生了什么。

Dictionary<int, MoveInfo> movingObject = new Dictionary<int, MoveInfo>();

public void Move(Transform from, Transform to, float overTime)
{
    MoveInfo moveInfo;

    //Check if the Object exist in the Dictionay
    if (movingObject.TryGetValue(from.GetInstanceID(), out moveInfo))
    {
        //This Object exist and therefore, the coroutine function is already running. Stop it

        //Remove it from the Dictionary
        movingObject.Remove(from.GetInstanceID());

        //Stop the old coroutine
        StopCoroutine(moveInfo.currentCoroutine);
    }

    //Create a new coroutine
    moveInfo = createMoveInfoInstance(from);

    //Add it to the dictionary 
    movingObject.Add(from.GetInstanceID(), moveInfo);

    //Get instance of the new coroutine we are about to start
    moveInfo.currentCoroutine = _Move(moveInfo, from, to, overTime);

    //Modify the dictionary because the Add function does not update the currentCoroutine reference
    movingObject[from.GetInstanceID()] = moveInfo;

    //Start the coroutine
    StartCoroutine(moveInfo.currentCoroutine);
}

MoveInfo createMoveInfoInstance(Transform from)
{
    MoveInfo moveInfo = new MoveInfo();
    moveInfo.instanceID = from.GetInstanceID();
    return moveInfo;
}

IEnumerator _Move(MoveInfo moveInfo, Transform from, Transform to, float overTime)
{
    Vector2 original = from.position;
    float timer = 0.0f;

    Debug.Log("New Coroutine Started");
    while (timer < overTime)
    {
        float step = Vector2.Distance(original, to.position) * (Time.deltaTime / overTime);
        from.position = Vector2.MoveTowards(from.position, to.position, step);
        timer += Time.deltaTime;
        yield return null;
    }

    //Remove it from the Dictionary if it exist
    if (movingObject.ContainsKey(from.GetInstanceID()))
    {
        movingObject.Remove(from.GetInstanceID());
    }
}

public struct MoveInfo
{
    public IEnumerator currentCoroutine;
    public int instanceID;

    public MoveInfo(IEnumerator currentCoroutine, int instanceID)
    {
        this.currentCoroutine = currentCoroutine;
        this.instanceID = instanceID;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM