C# Unity - 确定哪个方法正在影响游戏对象

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

启动协程

While it still moves, I may hover over it again, in that case I want it to restart, so it stops the function affecting the exact same button and restarts another one. I just have no clue how to identify which call of the same function affects my given component. Or shall I add this script to every object so it can affect only that one?

一种解决方案是将包含协程函数的脚本附加到 each 个游戏对象。如果您不想这样做,还有另一种方法可以做到这一点。

首先,简单地存储 IEnumerator 并不足以真正做到这一点。您需要一种方法来识别最后一个协程中的 GameObject 运行。

1.得到一个可以用来识别Object的值。在这种情况下,带有GetInstanceID()的实例ID应该没问题。

2。制作一个简单的 struct 来保存旧协程信息。

3。最后,制作一个字典,将包含实例 ID(键)和来自 #2 的结构作为值.

有了这三个东西,你就可以启动一个协程,把它添加到Dictionary。协程完成后,从 Dictionary.

中删除 instance ID

下面的代码可以让一个协程控制多个对象,而无需将协程函数放在自己的脚本中。最大的区别在于,当在 the-same 函数上调用新协程时,它会停止该对象上的旧协程 然后创建一个新协程并启动它。

这是我用的。评论很好,让你知道是怎么回事。

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