收集一个代表的不同功能

时间:2017-02-06 12:51:29

标签: c# events unity3d delegates

我有不同的functions我希望彼此调用。它们都是UI动画,一个用于旋转,一个用于缩放,一个用于移动,依此类推。我希望链接它们,所以在coroutine结束时,如果订阅了其他内容,则会触发一个事件。目前,我必须为所有创建delegates,这会使代码的扩展无法忍受。如何创建委托 - 或代表集合? - 谁的活动可以解雇各种功能?

修改 这些功能并不相互依赖。仅移动移动。仅旋转旋转,依此类推。 只有MoveRotate的一个实例可以对一个组件产生影响。

class MoveClass : MonoBehaviour
{
    #region Move
    //to ensure only one mover coroutine can be active.
    public IEnumerator moveRoutine = null;
    /// <summary>
    /// Moves a UnityEngine.GameObject from position A to position B over timeToReachDestination.
    /// Uses Coroutines.
    /// </summary>
    /// <param name="from"></param>
    /// <param name="to"></param>
    /// <param name="overTime"></param>
    public void Move(Transform from, Transform to, float overTime)
    {
        //pull off this shit to ensure only once it will be executed.
        if (moveRoutine != null)
        {
            StopCoroutine(moveRoutine);
        }
        moveRoutine = _Move(from, to, overTime);
        StartCoroutine(moveRoutine);
        //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;
        }
        if(event != null)
        {
            event(/*parameters*/);
            //or loop through the events?
        }
    }
    #endregion
}

3 个答案:

答案 0 :(得分:2)

好像你想在你的协程结束时回调一次。

IEnumerator _Move(Transform from, Transform to, float overTime, Action /*<Parameter>*/ onCompletion = null)
{
    // Your current code

    if(onCompletion!= null)
    {
        onCompletion(/*parameters*/);
        //or loop through the events?
    }
}

编辑:添加了onCompletion = null,因此它具有默认参数。

考虑到你可能有不同的回调参数列表,你会想出各种重载。公共代码将移动到在所有不同重载中调用的方法,只有最后一部分会有所不同:

void MoveItem(Transform from, Transform to, float overTime)
{
     float step = Vector2.Distance(original, to.position) * (Time.deltaTime / overTime);
     from.position = Vector2.MoveTowards(from.position, to.position, step);
}
IEnumerator _Move(Transform from, Transform to, float overTime, Action onCompletion = null)
{
    Vector2 original = from.position;
    float timer = 0.0f;
    while (timer < overTime)
    {
        MoveItem(from, to, overTime);
        timer += Time.deltaTime;
        yield return null;
    }
    if(event != null)
    {
        event();
    }
}

    IEnumerator _Move(Transform from, Transform to, float overTime, Action <float>onCompletion = null)
{
    Vector2 original = from.position;
    float timer = 0.0f;
    while (timer < overTime)
    {
        MoveItem(from, to, overTime);
        timer += Time.deltaTime;
        yield return null;
    }
    if(event != null)
    {
        event(10.0f);
    }
}

您可以灵活地为MoveItem方法提供委托,以便您可以传递任何移动方法(移动的形状可以是线性,指数等)。

答案 1 :(得分:1)

以更详细的形式解释我的评论。

您可以从代码中触发全局(一)EventHandler

public delegate void MeEventHandler(object sender, MeEventArgs e);

然后如你所料,你应该建立基础MeEventArgs类:

public abstract class MeEventArgs
{
    // nothing in here or some common fields/properties
}

接下来,您可以通过各种方式获得:

public sealed class MeTransformEventArgs
    : MeEventArgs
{
    public bool SuccesfullyTransformed { get; set; }
    public Vector3 PreviousPosition { get; set; }
    public Vector3 NewPosition { get; set; }
}

与旋转事件相同:

public sealed class MeRotationEventArgs
    : MeEventArgs
{
    public bool Successfull { get; set; }
    public Quaternion FromAngle { get; set; }
    public Quaternion ToAngle { get; set; }
}

和其他人一样......

现在您可以将您的活动设为:

public event MeEventHandler MeEvent;

无论何时你想发动这个事件:

MeEvent(this, (MeEventArgs)new MeTransformEventArgs() { SuccesfullyTransformed = false, PreviousPosition = Vector3.zero, NewPosition = Vector3.zero });

然后你用这些来抓住这些:

void WhenEventFired(object sender, MeEventArgs e)
{
    if(e is MeTransformEventArgs)
    {
        MeTransformEventArgs eArgs = (MeTransformEventArgs)e;
        // do something with event.
    }
}

答案 2 :(得分:0)

  

如何创建委托 - 或代表集合? - 谁的活动可以解雇各种各样的功能?

多播代表。

Action onCompletion = SomeMethod;
onCompletion += SomeOtherMethod;
// Now the delegate will call both methods when invoked.
StartCoroutine(_Move(..., onCompletion));

或者你可以简单地制作代表的集合,I.E。 List<Action>