2016-11-13 80 views
4

注 - “ISingleFingerHandler”“IPinchHandler”以及Unity类似的概念完整的解决方案是在这里:https://stackoverflow.com/a/40591301/294884仿型Unity的神秘接口电源


Unity3D有这样的接口,任何组件上的MonoBehavior你只做到这一点...

public class LaraCroft:MonoBehaviour,IPointerDownHandler 
    { 
    public void OnPointerDown(PointerEventData data) 
     { 
     Debug.Log("With no other effort, this function is called 
     for you, by the Unity engine, every time someone touches 
     the glass of your iPhone or Android."); 
     } 

必须要注册,设置一个委托或其他任何东西。每当有人触摸屏幕时,OnPointerDown(IPointerDownHandler中唯一的项目)会被调用。

令人惊叹!

这里有一个类似的界面,我写...

public interface ISingleFingerDownHandler 
    { 
    void OnSingleFingerDown(); 
    } 

现在,我希望消费者能够做到这一点...

public class LaraCroft:MonoBehaviour,ISingleFingerDownHandler 
    { 
    public void OnSingleFingerDown(PointerEventData data) 
     { 
     Debug.Log("this will get called every time 
     the screen is touched..."); 
     } 

只是为了回顾一下,使用统一的界面(那些该功能自动调用不需要进一步的努力 - 消费者确实不是必须注册或其他任何东西。

可悲的是,我能做到,只有这样的:

我写了一个“守护” ..

public class ISingleFingerDaemon:MonoBehaviour 
    { 
    private ISingleFingerDownHandler needsUs = null; 
    // of course that would be a List, 
    // just one shown for simplicity in this example code 

    void Awake() 
     { 
     needsUs = GetComponent(typeof(ISingleFingerDownHandler)) 
             as ISingleFingerDownHandler; 
     // of course, this could search the whole scene, 
     // just the local gameobject shown here for simplicity 
     } 

    ... when something happens ... 

     if (needsUs != null) needsUs.OnSingleFingerDown(data); 


    } 

而我得到的守护进程运行的地方。

如果你不是Unity用户 - 它所做的是查找并找到任何ISingleFingerDownHandler使用者,保留它们的列表,然后根据需要适当调用OnPointerDown。这工作正常,但

  • 消费者,程序员必须记住“把守护的地方”,让它运行等

  • 还有当你做这样的事情(在明显的抗高雅的仪态当然,统一或其他地方),重效率,安置,等等等等

•这种方法失败,如果一个消费者进来到存在于当守护程序没有为他们寻找一个时间(Unity的魔术接口不遭受这个问题 - 他们有更多的魔力对付那)

(PS,我知道如何写一个自动帮手放置守护进程等等!请不要在静脉回复,谢谢)

事实上,很明显,在统一的混蛋有一些系统会在幕后,这确实所有精美,因为“他们的”接口是完全可以调用所有需要的来电,无论甚至在飞行等

正在创建的项目有什么最佳方案?我坚持需要守护进程吗?也许需要注册?

(它肯定会吸 - 实际上通常不会在典型的统一项目可用 - 只是使它成为一个类继承;该类型的设施是自然的界面。)

因此,要回顾一下,但统一这...

public class LaraCroft:MonoBehaviour,IPointerDownHandler 

肯定有对我进行替换,延伸,应该是一个办法......

public class LaraCroft:MonoBehaviour,ISuperiorPointerDownHandler 

然后可以使用相同的方式/这股该界面的神奇特质?我可以做得很好,但只有我做了一个跛脚屁股守护进程。

+0

好主,没有人甚至投了这么复杂的问题?! :) – Fattie

+1

只是读这个 - 是的加一个。我想出了自己的roll-my-own消息系统,它需要每个对象中的一个组件侦听来自消息传递器的事件,该消息针对特定接口触发该对象上的Execute方法。这是一堆样板代码,一旦实施,效果很好。 –

+0

确实@ChuckSavage,挺对的。对于读过这一切的人来说,我已经仔细考虑过了,认为最好是“继承”Unity的IPointerDown/etc概念,并且只是简单地拥有自己的守护进程。 (这与我们所有人在Unity代码中一直做的没有什么不同:也就是说,这是一个完全错误的路径,试图使它像Unity的系统一样)。最终结果是**可笑地简单**:http:// stackoverflow.com/a/40591301/294884链接包括一个史诗般的讨论为什么它是要走的路。 (抛开显而易见的“令人难以置信的简单和优雅”。) – Fattie

回答

2

我不想回答我的问题,但答案这里是真的:

你不能。你必须添加一个守护进程。

不过,这是非常值得注意的是,

事实上,统一添加一个后台程序 - 他们只是隐藏了一点。

最终的绝对关键的一点明白的是:

团结拧追问:你不能实际上从他们的可爱StandAloneInputModule继承。这是一个大错误。

统一的StandAloneInputModule和IPointerDownHandler家庭 - 辉煌。但是你不能正确地继承它们。

事实是,你只需要从IPointerDownHandler侧身继承。这里的所有都是它的。

事实是,你必须让你自己的守护进程(“仿佛”它从StandAloneInputModule继承),实际上它只是从IPointerDownHandler家族侧身而来。

所以实际的答案是(A)你有这样的

public interface ISingleFingerHandler 
    { 
    void OnSingleFingerDown (Vector2 position); 
    void OnSingleFingerUp (Vector2 position); 
    void OnSingleFingerDrag (Vector2 delta); 
    } 

public class SingleFingerInputModule:MonoBehaviour, 
       IPointerDownHandler,IPointerUpHandler,IDragHandler 

和(B)你必须把一个游戏对象(这是一个守护进程),然后(C)是只是很容易最后处理捏等。

public class YourFingerClass:MonoBehaviour, IPinchHandler 
    { 
    public void OnPinchZoom (float delta) 
     { 
     _processPinch(delta); 
     } 

就是这样!

满负荷生产代码PinchInputModule ...

https://stackoverflow.com/a/40591301/294884

...这确实是从( “用途”)IPointerDownHandler家庭横盘继承。

4

你说你不想做守护进程,但这正是Unity正在做的。 StandaloneInputModule类当您添加UI组件时自动添加的类是守护程序

enter image description here

你可以做的是创建可以处理听触发和提高你的额外活动从BaseInputModule衍生(LIKEY PointerInputModule您的情况)中的一个类派生新类,然后添加一个新的类到EventSystem对象。

有关如何创建自定义事件的注意事项以及有关输入模块的更多详细信息,请参见Event System上的Unity手册部分。

+0

我认为你是对的。如果不以某种方式调用它,或者将它附加到活动的GameObject上,我没有看到这样做的方法。 – Programmer

+0

嗯,独一无二的讨论中,我可以找到有关延长PointerInputModule(或类似)是http://unity-coding.slashgames.org/extend-unitys-eventsystem-drag-drop/ – Fattie

+0

添C'S这里的例子是可能的方式去:https://forum.unity3d.com/threads/event-system-onenable-or-start.266354/ – Fattie

1

我的假设是,MonoBehaviour在ctor中运行一个类型检查。这就是为什么你不能在这些上使用ctor以避免压倒这一过程。常见的解决方案是你的界面也需要实现一个注册方法(例如Vuforia就是这么做的),所以任何新的实例都会自己注册。

你也可以用自己的MB系统扩展MB类:

public class JoeMonoBehaviour : MonoBehaviour 
{ 
    protected virtual void Awake(){ 
     Init(); 
    } 
    private void Init(){ 
     if(this is ISuperiorPointerDownHandler) 
     { 
       if(ISuperiorHandler.Instance != null){ 
        ISuperiorHandlerInstance.RegisterPointerDownHandler(this as ISuperiorPointerDownHandler); 
       } 
     } 
    } 
} 

它没有统一的魔法,但你不能达到统一与MonoBehaviour魔力。它需要子类确保它调用base.Awake(),如果覆盖它。

你必须想出你自己的引擎系统来运行你自己的引擎逻辑。不知道这是值得的。

另一个解决方案是创建自己的实例化:

namespace JoeBlowEngine{ 
    public static GameObject Instantiate(GameObject prefab, Vector3 position, Quaternion rotation){ 
      GameObject obj = (GameObject)Instantiate(prefab, position, rotation); 
      MonoBehaviour [] mbs = obj.GetComponentsInChildren<MonoBehaviour>(true); // I think it should also get all components on the parent object 
      foreach(MonoBehaviour mb in mbs){ 
       CheckForSuperior(mb); 
       CheckForInferior(mb); 
       // so on... 
      } 
      return obj; 
    } 
    internal static CheckForSuperior(MonoBehaviour mb) 
    { 
     if(mb is SomeType) { SomeTypeHandler.Instance.Register(mb as SomeType); } 
    } 
} 

现在它看起来就像你正在做一些神奇的只有:

JoeBlowEngine.Instantiate(prefab, Vector3.zero, Quaternion.identity); 
+0

我不认为你会彻底解读这个问题。他说他不会在任何地方叫它。他只是想让事情开始工作,我认为这是不可能的。它最开始的地方。看看他的问题引用 - “PS,我知道如何编写一个自动助手来放置守护进程等等:请不要以这种方式回复,谢谢”**我认为这就是你刚刚做的。 – Programmer

+0

OP不需要一个答案,因为他可以自己做,但我乞求认为这是为了被别人使用,不一定是10多年编程的人。如果不是这样,那么答案很简单。 “不能,下一步”。 – Everts

+1

程序员是非常正确的,那正是我想要避免的。然而,**优秀的点Everts ** - 当然 - “注册功能”可以只是接口所需的一个调用 - 这真棒。 – Fattie