Duplicating Unity's mystic Interface power

后端 未结 3 610
刺人心
刺人心 2021-01-06 04:07

Unity3D has an interface like this, for any Component on a MonoBehavior you just do this:

public class LaraCroft:MonoBehaviour,IPointerDownHandler
  {
  publ         


        
相关标签:
3条回答
  • 2021-01-06 04:53

    I hate to answer my own questions, but the answer here is really:

    You cannot. You do have to add a daemon.

    But then, it's very much worth noting that

    Indeed, Unity add a daemon - they just hide it a little.

    The final absolutely critical point to understand is that:

    Unity screwed-up: you cannot in fact inherit from their lovely StandAloneInputModule. This is a big mistake.

    Unity's StandAloneInputModule and IPointerDownHandler family - are brilliant. But you can't inherit from them properly.

    The fact is, you just have to inherit sideways from IPointerDownHandler. That's all there is to it.

    The fact is you have to make your own daemon ("as if" it inherits from StandAloneInputModule) which actually just goes sideways from IPointerDownHandler family.

    So the actual answer is (A) you have this

    public interface ISingleFingerHandler
        {
        void OnSingleFingerDown (Vector2 position);
        void OnSingleFingerUp (Vector2 position);
        void OnSingleFingerDrag (Vector2 delta);
        }
    
    public class SingleFingerInputModule:MonoBehaviour,
                    IPointerDownHandler,IPointerUpHandler,IDragHandler
    

    and (B) you do have to put that on a game object (it's a daemon), and then (C) it's just stupidly easy to finally handle pinches, etc.

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

    That's it!

    Full production code for PinchInputModule ...

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

    ...which indeed inherits sideways from ("uses") IPointerDownHandler family.

    0 讨论(0)
  • 2021-01-06 04:57

    You say you don't want to do a daemon but that is exactly what Unity is doing. The StandaloneInputModule class that is automatically added when you add a UI component is that daemon.

    What you can do is create a new class derived from one of the classes derived from BaseInputModule (likey PointerInputModule for your case) that can handle listening to trigger and raising your extra events then add that new class to the EventSystem object.

    See the Unity manual section on the Event System for notes on how to create your custom events and more details on what the input module does.

    0 讨论(0)
  • 2021-01-06 04:59

    My assumption is that MonoBehaviour runs a type check in ctor. Which is why you cannot use the ctor on those to avoid overriding that process. The common solution is that your interface would also require to implement a registering method (Vuforia does that for instance) so any new instance registers itself.

    You could also extend MB class with your own MB system:

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

    It does not have the magic of Unity but you cannot achieve the magic of Unity with MonoBehaviour. It require the sub class to make sure it calls the base.Awake() if overriding it.

    You'd have to come up with your own side engine system to run your own engine logic. Not sure that'd be worth it.

    Another solution is to create your own Instantiate:

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

    Now it look like you are doing some magic only with :

     JoeBlowEngine.Instantiate(prefab, Vector3.zero, Quaternion.identity);
    
    0 讨论(0)
提交回复
热议问题