Wednesday, January 13, 2021

Hello Unity, Hello Logic Forge visual scripting


 

Tuesday, May 10, 2016

Playables Crossfade animation mixer Unity 5.4

using UnityEngine;using UnityEngine.Experimental.Director;


namespace ws.winx.unity.components {
    public class CrossFadeMixerPlayable : CustomAnimationPlayable {


        private float m_TransitionDuration = 1.0f;        
private float m_TransitionTime = 0.0f;        
private float m_TransitionStart = 0.0f;

        private bool m_InTransition = false;
        private AnimationMixerPlayable mixer;
        private enum FreePort {
            PORT0 = 0,            PORT1        }

        private FreePort __freePort;

        private float __frameDuration;



        public CrossFadeMixerPlayable() {


            mixer = AnimationMixerPlayable.Create(); 
           Playable.Connect(mixer, this);          
  mixer.AddInput(Playable.Null);           
 mixer.AddInput(Playable.Null);           
 __freePort = FreePort.PORT0;       
 }

     public void Play(AnimationClipPlayable animationClipPlayable) {
            this.Crossfade(animationClipPlayable,0f);        }

             
public void Crossfade(AnimationClipPlayable animationPlayable, float transitionDuration, int frameRate = 30) {



            m_TransitionTime = 0.0f;            
__frameDuration = 1f / frameRate;

            Playable playable = mixer.GetInput((int)__freePort);

            if (playable != Playable.Null) {
                playable.time = 0f;  
              playable.state = PlayState.Paused;  
              Playable.Disconnect(mixer, (int)__freePort);            }


            //Connect to free port    
        Playable.Connect(animationPlayable, mixer, 0, (int)__freePort);           
 animationPlayable.time = 0f;   
         animationPlayable.state = PlayState.Playing;

            //UPGRADES            //make dynamic transition value equal duration of current playable to finish???            //transitionDuration=(1f-(float)(playable1.time-(int)playable1.time))*playable1.CastTo<AnimationClipPlayable>().clip.length;            //if this duration is longer then new playable then shift start of transition for the amount of difference
            if ( __freePort == FreePort.PORT0) {


                __freePort = FreePort.PORT1;           
 
else {

                __freePort = FreePort.PORT0;            
}


            m_TransitionDuration = transitionDuration;

            m_InTransition = true;
            Debug.Log("Time at start:" + m_TransitionTime + " duration:" + m_TransitionDuration);
        }

        public override void PrepareFrame(FrameData info) {


            if (m_InTransition) {
                if (m_TransitionTime <= m_TransitionDuration)
                {
                    m_TransitionTime += __frameDuration;// Time.time - m_TransitionStart;   
float weight = Mathf.Clamp01(m_TransitionTime / m_TransitionDuration);

                    mixer.SetInputWeight(1 - (int)__freePort, weight);
                    mixer.SetInputWeight((int)__freePort, 1.0f - weight);

                    Debug.Log("Transition time update:" + m_TransitionTime);                }
                else                {

                    mixer.RemoveInput((int)__freePort);
                    m_InTransition = false;
                    Debug.Log("Transition end at:" + m_TransitionTime);                }

                Debug.Log(this.ToString());            }

        }


        public override string ToString() {
            string info = string.Empty;
            info += " crossfade layer mixer time:" + mixer.time;
            for (int i = 0; i < mixer.inputCount; i++) {
                Playable playable = mixer.GetInput(i);
                if (playable != Playable.Null) {
                    info += "\n Port:" + i + " State:" + playable.state + " time:" + ((float)(playable.time - (int)playable.time)) + " weight:" + mixer.GetInputWeight(i) + " clip:" + playable.CastTo<AnimationClipPlayable>().clip;                } else {
                    info += "\n Port:" + i + " Empty!";                }
            }


            return info;        }




    }
}

Wednesday, February 24, 2016

Headaches and tips - Grass, Lights, Cloth, Prefab


Grass Not Rendered in Scene or/and Editor View????
In Terrain component, "Settings" you can see Detail Distance is default 80 and max is 250 meaning if your camera is further then 250 nothing will be rendered.




Light NOT RENDERED????
Render mode is set to "Auto" so Unity decides what to render. Set Important force to be rendered.




Cloth (extremities go out of the cloth)????
Create pair of empty game objects with the Sphere colliders and position then in pairs along the bone. Increase the radius of Sphere until extremities not go out. Make also cut in cloth if not enough.

Revert Value to Prefab not working on ur custom components????
Use EditorGUI.BeginProperty(...) [ur custom GUI code here] EditorGUILayout.EndProperty()


Reserve space when developing with EditorGUILayout and need to draw elements with EditorGUI
Rect rect =GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth,18f);//
EditorGUIUtility.fieldWidth - get the width of Inspector.window

Wednesday, December 9, 2015

How to: Add Persistent Bool Listener programatically - Unity 5

 

    State is ScriptableObject so your persistence can be done on something persistent (Prefab).
If event is on Scene GameObject then you can add presistent listener from some of the scene GameObjects;

               if(PrefabUtility.GetPrefabType(serializedProperty.serializedObject.targetObject)==PrefabType.Prefab)
                   prefab=serializedProperty.serializedObject.targetObject;
                else
                   prefab=PrefabUtility.GetPrefabParent(serializedProperty.serializedObject.targetObject);



               
UnityAction<boolm=(UnityAction<bool>)Delegate.CreateDelegate(typeof(UnityAction<bool>),prefab,typeof(MonoBehaviour).GetProperty("enabled").GetSetMethod());

                if(objPrev!=null){


                    UnityEventTools.RemovePersistentListener<bool>((objPrev as State).OnEnter,m);
                    UnityEventTools.RemovePersistentListener<bool>((objPrev as State).OnExit,m);

                }
                    
                UnityEventTools.AddBoolPersistentListener((serializedProperty.objectReferenceValue as State).OnEnter,m,true);
                UnityEventTools.AddBoolPersistentListener((serializedProperty.objectReferenceValue as State).OnExit,m,false);

Sunday, August 16, 2015

Unity 5 Observables Reactions Rx

Why not use Reaction in Unity game development. It as such powerful technics.
Discussion is based on great lib UniRx. I couldn't be more grateful and happy that people like neuecc exist and share.






I wanted to have more visual control and not recreate wheel, more in Unity way so I've create Unity Observables. UnityObservables reuse UnityEvent drawing and UnityAction serialization logic.

#if UNI_RX
using UnityEngine.Events;
using System;
using System.Collections.Generic;
using System.Reflection;
using UniRx;
using UniRx.InternalUtil;



using UnityEngine;

namespace ws.winx.unity.core{

   using UnityEngine.Events;
   using System;
   using System.Collections.Generic;
   using UniRx;
   using UniRx.InternalUtil;
   using UnityEngine;
   using System.Reflection;
   using UniRx.Triggers;
   
   
   public static class  ObservableExtensionsEx{
      public static IDisposable DisposeWith(this IDisposable disposable, GameObject gameObject)
      {
         return gameObject.OnDestroyAsObservable().First().Subscribe(p => disposable.Dispose());
      }
      
      public static IDisposable AddListener (this IObservable<GameObject> source,UnityAction call)
      {
         return source.Where(tgt=>tgt==null || tgt==(call.Target as MonoBehaviour).gameObject).Subscribe<GameObject> (x => call ());
         //return ((UnityObservable)source).Subscribe (call);                        }
      
      public static IDisposable AddListener<T1> (this IObservable<Tuple<T1,GameObject>> source,UnityAction<T1> call)
      {
         
         return source.Where(tgt => tgt.Item2 == null || tgt.Item2 == (call.Target as MonoBehaviour).gameObject).Subscribe<Tuple<T1,GameObject>> (x => call (x.Item1));
         //return ((UnityObservable<T1>)source).Subscribe (call);               }

      public static IDisposable AddListener<T1,T2> (this IObservable<Tuple<T1,T2,GameObject>> source,UnityAction<T1,T2> call)
      {
         return source.Where (typle => typle.Item3 == null || typle.Item3 == (call.Target as MonoBehaviour).gameObject).Subscribe ((typle) => call (typle.Item1, typle.Item2));
         //return ((UnityObservable<T1,T2>)source).Subscribe (call);      }
      

      
      public static IDisposable AddListener<T1,T2,T3> (this IObservable<Tuple<T1,T2,T3,GameObject>> source,UnityAction<T1,T2,T3> call)
      {
         return source.Where(tgt=>tgt.Item4==null || tgt.Item4==(call.Target as MonoBehaviour).gameObject).Subscribe (typle => call (typle.Item1,typle.Item2,typle.Item3));
         //return ((UnityObservable<T1,T2,T3>)source).Subscribe (call);               }
      
      
      public static IDisposable AddListener<T1,T2,T3,T4> (this IObservable<Tuple<T1,T2,T3,T4,GameObject>> source,UnityAction<T1,T2,T3,T4> call)
      {
         return source.Where(tgt=>tgt.Item5==null || tgt.Item5==(call.Target as MonoBehaviour).gameObject).Subscribe<Tuple<T1,T2,T3,T4,GameObject>> (x => call (x.Item1,x.Item2,x.Item3,x.Item4));

         //return ((UnityObservable<T1,T2,T3,T4>)source).Subscribe (call);               }
      
      
   }
   
   [Serializable]
   public class UnityObservable:UnityEvent,IObservable<GameObject>
   {
      
      private Dictionary<UnityAction,IDisposable> __disposables;
      private Subject<GameObject> subject;
      private bool persistentTargetsAreSubscribed;
      private CompositeDisposable __disposer;
      
      
      
      
      //      // Constructors      //      public UnityObservable ():base()
      {
         
         __disposables = new Dictionary<UnityAction, IDisposable> ();
         
         subject = new Subject<GameObject> ();
         
         __disposer = new CompositeDisposable ();
         
         //num of persistent is 0 here, so why SubscibeToPersistent is called in Invoke      }
      
      public new void AddListener (UnityAction call)
      {
         Subscribe (call);
      }
      
      void SubscibeToPersistent ()
      {
         //check is some listners are subscribed thru editor         if (!persistentTargetsAreSubscribed && this.GetPersistentEventCount () > 0) {
            //subscribe persistent obeservers to observer            int persistentTargetsNumber = this.GetPersistentEventCount ();
            MethodInfo methodInfo;
            UnityEngine.Object persistentTarget;
            
            
            
            for (int i=0; i<persistentTargetsNumber; i++) {
               
               persistentTarget = this.GetPersistentTarget (i);
               methodInfo = persistentTarget.GetType ().GetMethod (this.GetPersistentMethodName (i));
               UnityAction call= System.Delegate.CreateDelegate (typeof(UnityAction), persistentTarget, methodInfo) as UnityAction;
               
               this.AddListener(call);
               //subject.Where(trg=>trg==null || trg==(call.Target as MonoBehaviour).gameObject).Subscribe<GameObject> (x => call ())                           }
            
            persistentTargetsAreSubscribed = true;
         }
         
         
         
      }
      
      public void InvokeOnTarget (GameObject target)
      {
         
         SubscibeToPersistent ();
         
         if (subject.HasObservers) {
            subject.OnNext (target);
         }
         
      }
      
      public new void Invoke ()
      {
         
         SubscibeToPersistent ();
         
         if (subject.HasObservers) {
            
            subject.OnNext(null);
         }
         
      }
      
      public new void RemoveListener (UnityAction call)
      {
         if (__disposables.ContainsKey (call)) {
            IDisposable disposable=__disposables [call];
            __disposables.Remove(call);
            
            disposable.Dispose();
            
            Debug.Log("Observer "+call.Method.Name+" on target "+call.Target+" Removed");
            
         }
         
         
      }
      
      public new void RemoveAllListeners ()
      {
         foreach (var d in __disposables)
            d.Value.Dispose ();
         
         __disposables.Clear ();
         
         __disposer.Dispose ();
      }

      
      
      public IDisposable Subscribe (UnityAction call)
      {
         IDisposable disposable = subject.Where(tgt=>tgt==null || tgt==(call.Target as MonoBehaviour).gameObject).Subscribe<GameObject> (x => call ());
         __disposables [call] = disposable;
         return disposable;
      }
      
      #region IObservable implementation      public IDisposable Subscribe (IObserver<GameObject> observer)
      {
         //Debug.LogWarning ("Use Subscribe (UnityAction call)");         return subject.Subscribe<GameObject> (observer.OnNext).AddTo(__disposer);
      }
      #endregion                                                    }
   
   
   
   [Serializable]
   public abstract class UnityObservable<T1,T2,T3,T4>:UnityEvent<T1,T2,T3,T4>,IObservable<Tuple<T1,T2,T3,T4,GameObject>>
   {
      private Dictionary<UnityAction<T1,T2,T3,T4>,IDisposable> __disposables;
      private Subject<Tuple<T1,T2,T3,T4,GameObject>> subject;
      private bool persistentTargetsAreSubscribed;
      private CompositeDisposable __disposer;
      
      
      
      //      // Constructors      //      public UnityObservable ():base()
      {
         
         __disposables = new Dictionary<UnityAction<T1,T2,T3,T4>, IDisposable> ();
         
         subject = new Subject<Tuple<T1,T2,T3,T4,GameObject>> ();
         
         __disposer = new CompositeDisposable ();
         
         //num of persistent is 0 here, so why SubscibeToPersistent is called in Invoke      }
      
      public new void AddListener (UnityAction<T1,T2,T3,T4> call)
      {
         Subscribe (call);
      }
      
      
      
      
      void SubscibeToPersistent ()
      {
         //check is some listners are subscribed thru editor         if (!persistentTargetsAreSubscribed && this.GetPersistentEventCount () > 0) {
            //subscribe persistent obeservers to observer            int persistentTargetsNumber = this.GetPersistentEventCount ();
            MethodInfo methodInfo;
            UnityEngine.Object persistentTarget;
            
            
            
            for (int i=0; i<persistentTargetsNumber; i++) {
               
               persistentTarget = this.GetPersistentTarget (i);
               methodInfo = persistentTarget.GetType ().GetMethod (this.GetPersistentMethodName (i));
               UnityAction<T1,T2,T3,T4> call= System.Delegate.CreateDelegate (typeof(UnityAction<T1,T2,T3,T4>), persistentTarget, methodInfo) as UnityAction<T1,T2,T3,T4>;
               
               this.AddListener(call);
               //subject.Where(trg=>trg.Item5==null || trg.Item5==(call.Target as MonoBehaviour).gameObject).Subscribe<Tuple<T1,T2,T3,T4,GameObject>> (x => call (x.Item1,x.Item2,x.Item3,x.Item4));                           }
            
            persistentTargetsAreSubscribed = true;
         }
         
         
         
      }
      
      public void InvokeOnTarget (GameObject target, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
      {
         
         SubscibeToPersistent ();
         
         if (subject.HasObservers) {
            subject.OnNext (Tuple.Create (arg1, arg2, arg3, arg4, target));
         }
         
      }
      
      public new void Invoke (T1 arg1, T2 arg2, T3 arg3, T4 arg4)
      {
         
         SubscibeToPersistent ();
         
         if (subject.HasObservers) {
            
            subject.OnNext (Tuple.Create (arg1, arg2, arg3, arg4,(GameObject)null));
         }
         
      }
      
      public new void RemoveListener (UnityAction<T1,T2,T3,T4> call)
      {
         if (__disposables.ContainsKey (call)) {
            IDisposable disposable=__disposables [call];
            __disposables.Remove(call);
            
            disposable.Dispose();
            
            Debug.Log("Observer "+call.Method.Name+" on target "+call.Target+" Removed");
            
         }
         
         
      }
      
      public new void RemoveAllListeners ()
      {
         
         foreach (var d in __disposables)
            d.Value.Dispose ();
         
         
         __disposables.Clear ();
         
      }
      
      public IDisposable Subscribe (UnityAction<T1,T2,T3,T4> call)
      {
         //convert UnityAction<T1,T2,T3,T4> to Action<T1,T2,T3,T4>         IDisposable disposable = subject.Where(tgt=>tgt.Item5==null || tgt.Item5==(call.Target as MonoBehaviour).gameObject).Subscribe<Tuple<T1,T2,T3,T4,GameObject>> (x => call (x.Item1,x.Item2,x.Item3,x.Item4));
         
         __disposables [call] = disposable;
         
         return disposable;
         
      }
      
      
      #region IObservable implementation      public IDisposable Subscribe (IObserver<Tuple<T1,T2,T3,T4,GameObject>> observer)
      {
         //Debug.LogWarning ("Use Subscribe (UnityAction<T1,T2,T3,T4> call)");         //Action<Tuple<T1,T2,T3,T4,GameObject>> action = observer.OnNext as Action<Tuple<T1,T2,T3,T4,GameObject>>;                           //UnityAction<Tuple<T1,T2,T3,T4,GameObject>> call=Delegate.CreateDelegate(typeof(UnityAction<Tuple<T1,T2,T3,T4,GameObject>>),action.Target,action.Method) as UnityAction<Tuple<T1,T2,T3,T4,GameObject>>;                  return subject.Subscribe(observer.OnNext).AddTo(__disposer);
      }
      #endregion                                                    }
   
   [Serializable]
   public abstract class UnityObservable<T1,T2,T3>:UnityEvent<T1,T2,T3>,IObservable<Tuple<T1,T2,T3,GameObject>>
   {
      
      private Dictionary<UnityAction<T1,T2,T3>,IDisposable> __disposables;
      private Subject<Tuple<T1,T2,T3,GameObject>> subject;
      private bool persistentTargetsAreSubscribed;
      private CompositeDisposable __disposer;
      
      
      
      //      // Constructors      //      public UnityObservable ():base()
      {
         
         __disposables = new Dictionary<UnityAction<T1,T2,T3>, IDisposable> ();
         
         subject = new Subject<Tuple<T1,T2,T3,GameObject>> ();
         
         __disposer=new CompositeDisposable();
         
         //num of persistent is 0 here, so why SubscibeToPersistent is called in Invoke      }
      
      public new void AddListener (UnityAction<T1,T2,T3> call)
      {
         Subscribe (call);
      }
      
      void SubscibeToPersistent ()
      {
         //check is some listners are subscribed thru editor         if (!persistentTargetsAreSubscribed && this.GetPersistentEventCount () > 0) {
            //subscribe persistent obeservers to observer            int persistentTargetsNumber = this.GetPersistentEventCount ();
            MethodInfo methodInfo;
            UnityEngine.Object persistentTarget;
            
            
            
            for (int i=0; i<persistentTargetsNumber; i++) {
               
               persistentTarget = this.GetPersistentTarget (i);
               methodInfo = persistentTarget.GetType ().GetMethod (this.GetPersistentMethodName (i));
               UnityAction<T1,T2,T3> call= System.Delegate.CreateDelegate (typeof(UnityAction<T1,T2,T3>), persistentTarget, methodInfo) as UnityAction<T1,T2,T3>;
               //subject.Where(trg=>trg.Item4==null || trg.Item4==(call.Target as MonoBehaviour).gameObject).Subscribe<Tuple<T1,T2,T3,GameObject>> (x => call (x.Item1,x.Item2,x.Item3));               AddListener(call);
            }
            
            persistentTargetsAreSubscribed = true;
         }
         
         
         
      }
      
      public void InvokeOnTarget (GameObject target, T1 arg1, T2 arg2, T3 arg3)
      {
         
         SubscibeToPersistent ();
         
         if (subject.HasObservers) {
            subject.OnNext (Tuple.Create (arg1, arg2, arg3, target));
         }
         
      }
      
      public new void Invoke (T1 arg1, T2 arg2, T3 arg3)
      {
         
         SubscibeToPersistent ();
         
         if (subject.HasObservers) {
            
            subject.OnNext (Tuple.Create (arg1, arg2, arg3, (GameObject)null));
         }
         
      }
      
      public new void RemoveListener (UnityAction<T1,T2,T3> call)
      {
         if (__disposables.ContainsKey (call)) {
            IDisposable disposable=__disposables [call];
            __disposables.Remove(call);
            
            disposable.Dispose();
            
            Debug.Log("Observer "+call.Method.Name+" on target "+call.Target+" Removed");
            
         }
         
         
      }
      
      public new void RemoveAllListeners ()
      {
         
         foreach (var d in __disposables)
            d.Value.Dispose ();
         
         __disposables.Clear ();
         
      }
      
      public IDisposable Subscribe (UnityAction<T1,T2,T3> call)
      {
         
         //convert UnityAction<T1,T2,T3> to Action<T1,T2,T3>         IDisposable disposable = subject.Where(tgt=>tgt.Item4==null || tgt.Item4==(call.Target as MonoBehaviour).gameObject).Subscribe<Tuple<T1,T2,T3,GameObject>> (x => call (x.Item1,x.Item2,x.Item3));
         
         __disposables [call] = disposable;
         
         return disposable;
         
      }
      
      
      #region IObservable implementation      public IDisposable Subscribe (IObserver<Tuple<T1,T2,T3,GameObject>> observer)
      {
         //Debug.LogWarning ("Use Subscribe (UnityAction<T1,T2,T3> call)");         return subject.Subscribe<Tuple<T1,T2,T3,GameObject>> (observer.OnNext).AddTo(__disposer);
      }
      #endregion                                                    }
   
   [Serializable]
   public abstract class UnityObservable<T1,T2>:UnityEvent<T1,T2>,IObservable<Tuple<T1,T2,GameObject>>
   {
      
      
      
      
      private Dictionary<UnityAction<T1,T2>,IDisposable> __disposables;
      
      
      private Subject<Tuple<T1,T2,GameObject>> subject;
      private bool persistentTargetsAreSubscribed;
      private CompositeDisposable __disposer;
      
      
      
      //      // Constructors      //      public UnityObservable ():base()
      {
         
         __disposables = new Dictionary<UnityAction<T1,T2>, IDisposable> ();
         
         subject = new Subject<Tuple<T1,T2,GameObject>> ();
         
         __disposer = new CompositeDisposable ();
         
         //num of persistent is 0 here, so why SubscibeToPersistent is called in Invoke      }
      
      public new void AddListener (UnityAction<T1,T2> call)
      {
         Subscribe (call);
      }
      
      void SubscibeToPersistent ()
      {
         //check is some listners are subscribed thru editor         if (!persistentTargetsAreSubscribed && this.GetPersistentEventCount () > 0) {
            //subscribe persistent obeservers to observer            int persistentTargetsNumber = this.GetPersistentEventCount ();
            MethodInfo methodInfo;
            UnityEngine.Object persistentTarget;
            
            
            
            for (int i=0; i<persistentTargetsNumber; i++) {
               
               persistentTarget = this.GetPersistentTarget (i);
               methodInfo = persistentTarget.GetType ().GetMethod (this.GetPersistentMethodName (i));
               UnityAction<T1,T2> call= System.Delegate.CreateDelegate (typeof(UnityAction<T1,T2>), persistentTarget, methodInfo) as UnityAction<T1,T2>;
               //subject.Where(trg=>trg.Item3==null || trg.Item3==(call.Target as MonoBehaviour).gameObject).Subscribe<Tuple<T1,T2,GameObject>> (x => call (x.Item1,x.Item2));               AddListener(call);
            }
            
            persistentTargetsAreSubscribed = true;
         }
         
         
         
      }
      
      public void InvokeOnTarget (GameObject target, T1 arg1, T2 arg2)
      {
         
         SubscibeToPersistent ();
         
         if (subject.HasObservers) {
            subject.OnNext (Tuple.Create (arg1, arg2, target));
         }
         
      }
      
      public new void Invoke (T1 arg1, T2 arg2)
      {
         
         SubscibeToPersistent ();
         
         if (subject.HasObservers) {
            
            subject.OnNext (Tuple.Create (arg1, arg2, (GameObject)null));
         }
         
      }
      
      public new void RemoveListener (UnityAction<T1,T2> call)
      {
         if (__disposables.ContainsKey (call)) {
            IDisposable disposable=__disposables [call];
            __disposables.Remove(call);
            
            disposable.Dispose();
            
            Debug.Log("Observer "+call.Method.Name+" on target "+call.Target+" Removed");
            
         }
         
         
      }
      
      public new void RemoveAllListeners ()
      {
         
         foreach (var d in __disposables)
            d.Value.Dispose ();
         
         __disposables.Clear ();
         
         __disposer.Dispose ();
         
      }
      
      public IDisposable Subscribe (UnityAction<T1,T2> call)
      {
         
         IDisposable disposable= subject.Where(tgt=>tgt.Item3==null || tgt.Item3==(call.Target as MonoBehaviour).gameObject).Subscribe<Tuple<T1,T2,GameObject>> (x => call (x.Item1,x.Item2));
         
         __disposables [call] = disposable;
         
         return disposable;
         
      }
      
      
      #region IObservable implementation      public IDisposable Subscribe (IObserver<Tuple<T1,T2,GameObject>> observer)
      {
         //Debug.LogWarning ("Use Subscribe (UnityAction<T1,T2> call)");         return subject.Subscribe<Tuple<T1,T2,GameObject>> (observer.OnNext).AddTo(__disposer);
      }
      #endregion                                                    }
   
   
   
   [Serializable]
   public abstract class UnityObservable<T1>:UnityEvent<T1>,IObservable<Tuple<T1,GameObject>>
   {
      
      
      
      
      private Dictionary<UnityAction<T1>,IDisposable> __disposables;
      
      
      private Subject<Tuple<T1,GameObject>> subject;
      private bool persistentTargetsAreSubscribed;
      
      private CompositeDisposable __disposer;
      
      
      //      // Constructors      //      public UnityObservable ():base()
      {
         
         __disposables = new Dictionary<UnityAction<T1>, IDisposable> ();
         
         subject = new Subject<Tuple<T1,GameObject>> ();
         
         __disposer = new CompositeDisposable ();
         
         //num of persistent is 0 here, so why SubscibeToPersistent is called in Invoke      }
      
      public new void AddListener (UnityAction<T1> call)
      {
         Subscribe (call);
      }
      
      void SubscibeToPersistent ()
      {
         //check is some listners are subscribed thru editor         if (!persistentTargetsAreSubscribed && this.GetPersistentEventCount () > 0) {
            //subscribe persistent obeservers to observer            int persistentTargetsNumber = this.GetPersistentEventCount ();
            MethodInfo methodInfo;
            UnityEngine.Object persistentTarget;
            
            
            
            for (int i=0; i<persistentTargetsNumber; i++) {
               
               persistentTarget = this.GetPersistentTarget (i);
               methodInfo = persistentTarget.GetType ().GetMethod (this.GetPersistentMethodName (i));
               UnityAction<T1> call= System.Delegate.CreateDelegate (typeof(UnityAction<T1>), persistentTarget, methodInfo) as UnityAction<T1>;
               //subject.Where(trg=>trg.Item2==null || trg.Item2==(call.Target as MonoBehaviour).gameObject).Subscribe<Tuple<T1,GameObject>> (x => call (x.Item1));               AddListener(call);
            }
            
            persistentTargetsAreSubscribed = true;
         }
         
         
         
      }
      
      public void InvokeOnTarget (GameObject target, T1 arg1)
      {
         
         SubscibeToPersistent ();
         
         if (subject.HasObservers) {
            subject.OnNext (Tuple.Create (arg1, target));
         }
         
      }
      
      public new void Invoke (T1 arg1)
      {
         
         SubscibeToPersistent ();
         
         if (subject.HasObservers) {
            
            subject.OnNext (Tuple.Create (arg1,(GameObject)null));
         }
         
      }
      
      public new void RemoveListener (UnityAction<T1> call)
      {
         if (__disposables.ContainsKey (call)) {
            IDisposable disposable=__disposables [call];
            __disposables.Remove(call);
            
            disposable.Dispose();
            
            Debug.Log("Observer "+call.Method.Name+" on target "+call.Target+" Removed");
            
         }
         
         
      }
      
      public new void RemoveAllListeners ()
      {
         foreach (var d in __disposables)
            d.Value.Dispose ();
         
         __disposables.Clear ();
         
         //I hope disposer check if something was manually disposed before         __disposer.Dispose ();
         
      }
      
      public IDisposable Subscribe (UnityAction<T1> call)
      {
         
         IDisposable disposable = subject.Where (tgt => tgt.Item2 == null || tgt.Item2 == (call.Target as MonoBehaviour).gameObject).Subscribe<Tuple<T1,GameObject>> (x => call (x.Item1));
         
         __disposables[call] = disposable;
         
         return disposable;
         
      }
      
      #region IObservable implementation      public IDisposable Subscribe (IObserver<Tuple<T1,GameObject>> observer)
      {
         //Debug.LogWarning ("Use Subscribe (UnityAction<T1> call)");         return subject.Subscribe<Tuple<T1,GameObject>> (observer.OnNext).AddTo(__disposer);
      }
      #endregion                                                    }
   
   
   
   
   
   
   





}
#endif