【问题标题】:Unity c#: Binding functions with parametersUnity c#:使用参数绑定函数
【发布时间】:2018-03-16 20:11:19
【问题描述】:

我正在开发一个拖放系统并尝试实现一个挂钩系统(类似于 WordPress 使用的系统),以便在某些事件发生时触发操作。

我的委托函数有多个问题:

  • 无法将UIElementDragger.CallBackFunction 表达式转换为ListObserver.CallBackFunction 类型
  • ListObserver.ListObserver(string, ListObserver.CallBackFunction) 的最佳重载方法匹配有一些无效参数

您对如何正确或以其他方式实现“挂钩系统”有任何建议,以便我可以使用某些自定义事件调用的带有参数的函数?

我已经截断了下面的代码以保留相关部分,但如果您需要全部内容,我很乐意提供。

绑定事件的代码是:

注意:UIElementDragger 附加到 EventSystem。

//... removed "using"

public class GameSyllab : MonoBehaviour { 

//... removed attributes

private UIElementDragger UIElementDragger;

// Use this for initialization
void Start () {

    //Hook the functions
    UIElementDragger = GetComponent<UIElementDragger> ("UIElementDragger");
    UIElementDragger.HookOnto("DropComplete", DropComplete);
    UIElementDragger.HookOnto("DropCancel", DropCancel);

    //... removed unrelated code
}   

void DropComplete(Object objDraggable, Object objDropZone){
    // Do an action based on the element being dropped
}
void DropCancel(Object objDraggable, Object objDropZone){
    // Play a cancel sound
}

//...removed unrelated class code

添加可拖动行为的 UIElementDragger 类的代码:

注意:这个类也附加到 EventSystem

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class UIElementDragger : MonoBehaviour {
    //A list with observers that are waiting for something to happen
    List<ListObserver> observers = new List<ListObserver>();
    public delegate void CallBackFunction(Object objDraggable, Object objDropZone);

    // ... removed extra attributes

    // Update is called once per frame
    void Update () {

        //... removed Mouse down code

        if (Input.GetMouseButtonUp (0)) {
            if (objectToDrag != null) {
                Transform objectToDrop = GetDraggableTransformUnderMouse(DROPZONE_TAG);

                if (objectToDrop != null) {
                    //Drop the dragged object on it's new drop zone
                    objectToDrag.position = objectToDrop.position;
                    NotifyObservers ("DropComplete", objectToDrag, objectToDrop);
                } else {
                    //Move the item back to its original position
                    objectToDrag.position = originalPosition;
                    NotifyObservers ("DropCancelled", objectToDrag, null);
                }

                objectToDragImage.raycastTarget = true;
                objectToDrag = null;
            }
            dragging = false;
        }


    }




    //Send notifications if something has happened
    public void NotifyObservers(string hookName, Object objectInstance, Object dropZoneInstance)
    {
        for (int i = 0; i < observers.Count; i++)
        {
            if (observers [i].GetHookName () == hookName) {
                observers [i].Call (objectInstance, dropZoneInstance);
            }
        }
    }

    //Add observer to the list
    public void HookOnto(string newHookName, CallBackFunction newCallBackFunction)
    {
        ListObserver newObserver = new ListObserver (newHookName, newCallBackFunction);
        observers.Add(newObserver);
    }
}

//In the same file, but a separate class
public class ListObserver:MonoBehaviour{
    private string hookName;
    public delegate void CallBackFunction(Object objDraggable, Object objDropZone);
    private CallBackFunction callBackFunction;

    public ListObserver(string newHookName, CallBackFunction newCallBackFunction){
        hookName = newHookName;
        callBackFunction = newCallBackFunction;
    }

    public void Call(Object objDraggable, Object objDropZone){
        callBackFunction (objDraggable, objDropZone);
    }

    public string GetHookName(){
        return hookName;
    }
}

【问题讨论】:

    标签: c# unity3d events delegates listener


    【解决方案1】:

    您有两个不兼容的委托

    public delegate void CallBackFunction(Object objDraggable, Object objDropZone);
    

    public delegate void CallBackFunction(Object objDraggable, Object objDropZone);
    

    它们具有完全相同的名称和完全相同的参数,但它们不是同一个对象。如果您尝试将类命名为 MathClassList&lt;T&gt; 之类的名称,则会遇到同样的问题:所有这些类都已经存在(在另一个命名空间中)并且会导致问题,就像您会遇到的那样无法将Math 转换为System.MathClass 转换为System.Reflection.Class,因为这两种类型不兼容。

    您需要删除一个委托(UIElementDragger 内部的那个)并使用另一个代替,如果需要,请使用完全限定名称 (ListObserver.CallBackFunction)。

    【讨论】:

    • ...在那里我花了 4 个小时将我的代码颠倒过来试图找到问题...只需要一个很好的耳光;)这是一个如此简单的解决方案...不要不知道为什么我之前没有意识到这一点。谢谢德拉科!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    相关资源
    最近更新 更多