我这里有这个代码:
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动画目的。
但是,当我想改变它的使用时,事情变得有趣。
例如,我将鼠标悬停在一个按钮上,该按钮开始移动。当它仍在移动时,我可能会再次悬停在它上面,在这种情况下我希望它重新启动,因此它会停止功能影响完全相同的按钮并重新启动另一个。我不知道如何识别同一函数的哪个调用会影响我给定的组件。或者我应该将此脚本添加到每个对象,以便它只能影响那个?
答案 0 :(得分:2)
我在这里有很多不同的做法。首先,如果您的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
启动协同程序答案 1 :(得分:1)
当它仍然移动时,我可能会再次盘旋它,在那种情况下我想要 它重新启动,所以它停止影响完全相同的功能 按钮并重新启动另一个。我根本不知道如何识别 哪个相同函数的调用会影响我给定的组件。或者我 将此脚本添加到每个对象,以便它只影响那个?
一种解决方案是将包含协同程序功能的脚本附加到每个 GameObjects。如果您不想这样做,那么还有另一种方法可以做到这一点。
首先,仅仅存储IEnumerator
并不足以实际执行此操作。您需要一种方法来识别在最后一个协同程序中运行的GameObject。
1 。获取可用于标识Object的值。在这种情况下,带GetInstanceID()
的实例ID应该没问题。
2 。制作一个简单的struct
,其中包含旧的协同程序信息。
3 。最后,制作一个包含实例ID(键)和#2 结构的字典作为值。
通过这三件事,您可以启动协程,将其添加到Dictionary
。协程完成后,从instance ID
删除Dictionary
。
下面的代码将使一个协程控制许多对象,而无需将coroutine函数放在自己的脚本中。最大的区别在于,当在同一个函数上调用新的cororutine时,它会停止该对象上的旧cororut 然后创建一个新的并开始它。
这就是我使用的。这是非常好的评论,以便您知道发生了什么。
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;
}
}