2016-11-13 86 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