[英]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.