C#Unity - 确定哪个方法影响GameObject

时间:2017-02-04 17:30:56

标签: c# function unity3d function-call

我这里有这个代码:

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动画目的。 但是,当我想改变它的使用时,事情变得有趣。 例如,我将鼠标悬停在一个按钮上,该按钮开始移动。当它仍在移动时,我可能会再次悬停在它上面,在这种情况下我希望它重新启动,因此它会停止功能影响完全相同的按钮并重新启动另一个。我不知道如何识别同一函数的哪个调用会影响我给定的组件。或者我应该将此脚本添加到每个对象,以便它只能影响那个?

2 个答案:

答案 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;
    }
}