Search Unity

UniRx - Reactive Extensions for Unity

Discussion in 'Assets and Asset Store' started by neuecc, May 28, 2014.

  1. TarlSS

    TarlSS

    Joined:
    Apr 26, 2014
    Posts:
    21
    Running UniRX as part of UFrame

    So I'm basically getting a lot of lines like this
    e:\Programming\UframeTest\Assets\uFrameComplete\uFrame\Base\StateMachine.cs(40,40): Error CS0104: 'IObserver' is an ambiguous reference between 'System.IObserver<UniRx.Unit>' and 'UniRx.IObserver<UniRx.Unit>' (CS0104) (Assembly-CSharp)

    It's obvious your version of IObserver is colliding with System.IObserver.
    What's up with this? How in the world did you get anything to compile?
    I'm using Mono. Is there some kind of trick or setting I need to use so I don't frigging have to go in and replace every line of code? Is this a Mono vs Visual studio issue?
     
  2. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    for example, zip with stream.

    cancel1.SelectMany(_ => cancel2).Zip(subscribeMessage, (x, y) => x).SelectMany(_ => cancel3).Subscribe();

    this code run cancel1 immediately and continue to cancel2 and stopped.
    when tapped subscribeMessage, start to next stream(cancel3).

    This is not best answer but one of the idea.
    FRP has many way, There's More Then One Way To Do It.
     
  3. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    Maybe your issue comes from your MonoDevelop's language/Framework version.
    .NET Framework 4.0 introduced System.IObserver but Unity's .NET Framework is .NET Framework 3.5.
    You can change(?) target framework to .NET 3.5.

    I'm using Visual Studio 2013 and VSTU(Visual Studio Tools for Unity),
    My target framework is "Unity 3.5 .net Subset Base Class Libraries"(this is VSTU's custom target framework settings).
     
  4. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
  5. antareslabs

    antareslabs

    Joined:
    Oct 30, 2014
    Posts:
    6
    Tnks! it`s work!
     
  6. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    Hi, Today 'UniRx - Reactive Extensions for Unity - 4.6' has been accepted!
    Sorry for late update.

    Big Change is corotuine run on UnityEditor(with Observable.FromCoroutine).
    And this version supports Unity5 Beta.
    If you make WindowsStoreApp, UniRx has breaking change(in NETFX_CORE, UniRx.IObservable is replace to System.IObservable)

    ---
    Improvement : Add support Unity5
    Improvement : Run coroutine on UnityEditor in MainThreadDispatcher, thanks @movajr
    Add : Observable.FromCoroutineValue
    Add : Observable.Amb
    Add : ObservableWWW.LoadFromCacheOrDownload
    Add : Observable.Merge overloads
    Add : AsyncSubject[T].Value
    Add : AsyncOperation.AsObservable(Extension Method)
    Fix : ObservableWWW allows same hash key, thanks @badoet
    Fix : Observable.FromCoroutine makes thread-safe
    Fix : Observable.DistinctUntilChanged throws exception when sequence contains null
    Fix : Logger throws exception when message is null
    Fix : Logger throws exception when use same logger name
    Fix : Makes Observable.Zip iOS AOT Safety
    Performance Improvement : AnonymousObserver(it is used Subscribe implicitly)
    Performance Improvement : BehaviorSubject[T]
    Performance Improvement : ReplaySubject[T]
    Breaking Change : in NETFX_CORE, use System.IObservable/IObserver/IProgress/Tuple instead of UniRx.IObservable, etc.
    ---

    UniRx lacks some operators yet(requested Observable.Windows, Observable.Join, etc...)
    I'll add many operators next release.
     
  7. AGeorgy

    AGeorgy

    Joined:
    Sep 16, 2013
    Posts:
    42
    cooool!
     
  8. AGeorgy

    AGeorgy

    Joined:
    Sep 16, 2013
    Posts:
    42
    Again confused
    Code (CSharp):
    1. IEnumerator AsyncA()
    2.     {
    3.         Debug.Log( "a start" );
    4.         yield return new WaitForSeconds( 2 );
    5.         Debug.Log( "a end" );
    6.     }
    7.     IEnumerator AsyncB()
    8.     {
    9.         Debug.Log( "b start" );
    10.         yield return new WaitForSeconds( 2 );
    11.         Debug.Log( "b end" );
    12.     }
    13. IEnumerator AsyncC()
    14.     {
    15.         Debug.Log( "c start" );
    16.         yield return new WaitForSeconds( 2 );
    17.         Debug.Log( "c end" );
    18.     }
    19.     public override void Awake()
    20.     {
    21.         var cancel1 = Observable.FromCoroutine( AsyncA );
    22.         var cancel2 = Observable.FromCoroutine( AsyncB );
    23.         var cancel3 = Observable.FromCoroutine( AsyncC );
    24.         var cancel4 = Observable.FromCoroutine( AsyncA );
    25.  
    26.         base.Awake();
    27.     }

    how to do it?

    Code (CSharp):
    1.                        cancel2   ->   cancel4
    2. cancel1   ->   and
    3.                        cancel3
    if something like this :

    Code (CSharp):
    1. cancel1
    2. .SelectMany( _ =>cancel2)
    3. .Zip( cancel3, ( x, y ) => x )
    4. .SelectMany( _ =>cancel4)
    cancel3 fire immediately.
     
    Last edited: Feb 9, 2015
  9. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    My idea, use Publish.

    Code (CSharp):
    1. var cancel1 = Observable.FromCoroutine(AsyncA).Publish(); // Publish is branching
    2. var cancel2 = Observable.FromCoroutine(AsyncB);
    3. var cancel3 = Observable.FromCoroutine(AsyncC);
    4. var cancel4 = Observable.FromCoroutine(AsyncA);
    5.  
    6. cancel1.SelectMany(cancel2).SelectMany(cancel4).Subscribe(x => Debug.Log("1-2-4 onnext:" + x), () => Debug.Log("1-2-4 oncomplete"));
    7. cancel1.SelectMany(cancel3).Subscribe(x => Debug.Log("1-3 onnext:" + x), () => Debug.Log("1-3 oncomplete"));
    8.  
    9. cancel1.Connect(); // fire
     
  10. AGeorgy

    AGeorgy

    Joined:
    Sep 16, 2013
    Posts:
    42
    Thanks a lot neuecc
    Im used:

    Code (CSharp):
    1. var cancelA = Observable.FromCoroutine( AsyncA );
    2.         var cancelB = Observable.FromCoroutine( AsyncB ).Publish();
    3.         var cancelC = Observable.FromCoroutine( AsyncC ).Publish();
    4.         var cancelD = Observable.FromCoroutine( AsyncD );
    5.  
    6. cancelB.SelectMany( cancelD ).Subscribe( _ => Debug.Log( "oncomplete" ) );
    7.  
    8.         cancelA.Subscribe( _ => { cancelB.Connect(); cancelC.Connect(); } );
    9.  
     
  11. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    Hi, today accepted update release on AssetStore.
    This update focus integrated with uGUI.
    I added ReactiveProperty and OnXxxAsObservable for uGUI controls.
    Please see Sample12 and Sample13, or new ReadMe section.
    https://github.com/neuecc/UniRx#ugui-integration

    Otherwise added frame count based time operators and more.

    Add : ReactiveProperty
    Add : ReactiveCollection
    Add : InspectorDisplayAttribute(for ReactiveProperty)
    Add : Observable.WhenAll(this IEnumerable[IObservable[T]])
    Add : Observable.AsUnitObservable
    Add : AsyncOperation.AsAsyncOperationObservable
    Add : Observable.NextFrame
    Add : Observable.IntervalFrame
    Add : Observable.TimerFrame
    Add : Observable.SampleFrame
    Add : Observable.ThrottleFrame
    Add : Observable.TimeoutFrame
    Add : Observable.DelayFrameSubscription
    Add : Observable.DelayFrame(FrameCountType)
    Add : Observable.SubscribeToText(for uGUI)
    Add : Observable.SubscribeToInteractable(for uGUI)
    Add : Button.OnClickAsObservable, Toggle/Scrollbar/ScrollRect/Slider.OnValueChangedAsObservable, InputField.OnEndEditAsObservable, InputField.OnValueChangeAsObservable
    Add : ObservableStateMachineBehaviour
    Add : ObservableUIBehaviours(ObservableButton, ObservableEventTrigger, ObservableImage, ObservableInputField, ObservableSelectable, ObservableSlider, ObservableText, ObservableToggle, ObservableUIBehaviour)
    Add : Graphic.DirtyLayoutCallbackAsObservable, Graphic.DirtyMaterialCallbackAsObservable, Graphic.DirtyVerticesCallbackAsObservable
    Fix : Prevent warning when Android build, thanks @mikanbako
    Fix : ObservableWWW progress not reporting 1 when done, thanks @etic
    Fix : Some methods runs once after disposed, thanks @TigerHix
    Improvement : Add class constraints to ObserveEveryValueChanged
    Improvement : Add Examples, Sample12_ReactiveProperty and Sample13_ToDoApp
    Improvement : ReadMe is added UI section
    Breaking Change : Observable.WhenAll if sequence is empty, return empty array

    ---

    sorry, I didn't add Observable.Window(Many user request operation!) yet.
    please wait for next release.
     
    Yasuyuki, movra and zyzyx like this.
  12. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    Hi, today accepted update release on AssetStore.
    Sorry for quick patch releases.
    This release contains support for Model-View-(Reactive)Presenter Pattern concept.
    https://github.com/neuecc/UniRx#model-view-reactivepresenter-pattern

    ---

    Add : ReadOnlyReactiveProperty
    Add : ReactiveProperty.SetValueAndForceNotify
    Add : Observable.Pairwise
    Add : Observable.SelectMany(IEnumerator)
    Add : ObservableEventTriggerSlim
    Add : IEnumerable[IObservable[bool]].CombineLatestValuesAreAllTrue/CombineLatestValuesAreAllFalse
    Fix : Compiler error on Unity 4.6 at Examples
    Fix : Observable.NextFrame should complete after the frame was rendered, thanks @Useurmind
    Fix : Observable.TimerFrame should complete after the frame was rendered
    Fix : 'newValue' is not used in CollectionReplaceEvent[T], thanks @Grabacr07
    Fix : When UniRx is dll or in plugin folder and use SelectMany and resultSelector returns AnonymousType, can't compile. (It's Unity's compiler bug)
    Breaking Change : ReactiveProperty changed to doesn't notify equality value
    Breaking Change : When ReactiveProperty is called Dispose, notify OnCompleted to all subscribers
    Breaking Change : ObservableMonoBehaviour.Awake, Start, Destroy notify OnCompleted
    Improvement : Add Model-View-(Reactive)Presenter Pattern section to ReadMe

    ---

    Known issues:
    * ReactiveProperty when value is null set value throws null reference exception
    * ReactiveCollection can't compile when build target is Web Player

    I update for there fix soon.
    And next release includes delete ObservableUIComponents.
    Sorry for unstable release and breaking changes.
    I will be careful from now on.
     
    zyzyx and movra like this.
  13. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    Today accepted 4.7.2 release.
    Here is release note.

    ---

    Add : ObservableLogger.DebugFormat/LogFormat/WarningFormat/ErrorFormat
    Fix : ReactiveProperty when value is null set value throws null reference exception
    Fix : ReactiveCollection can't compile when build target is Web Player, thanks @FodderMK
    Improvement : InspectorDisplayAttribute better handling on error
    Breaking Change : Remove ObservableUIComponents(ObservableButton/Image/InputField/etc...)
    Breaking Change : ObservableEventTriggerSlim rename to ObservableEventTrigger

    ---

    Next release, I add ObservableTriggers it is lightweight ObservableMonoBehaviour
    and planed some useful features.
    Please wait a moment.
     
    zyzyx likes this.
  14. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Hi,

    I'm facing a problem using your Rx port in quite specific scenario.

    I'm trying to write Unity-compatible dll; so that I'm not dealing with bunch of sources in Assets/ folder, but rather import one precompiled assembly with game logic core, and use classes from there in scripts. This assembly intended to be Unity agnostic, so it doesn't reference UnityEngine.dll.

    At first UniRx sources seemed well decoupled, but in fact it takes much efforts to separate UnityEngine dependent parts (they are not only in UnityEngineBridge/). Files like Observer.cs cannot be simply moved to precompiled assembly, because they are contaminated with unnecessary `partial class ObservableExtensions` (partial classes cannot be split among assemblies).

    Could you please refactor your code so that it could be easily split on Unity agnostic and Unity dependent parts?

    Thank you.
     
  15. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    Hmmmm.

    I don't think share dll with Unity and CLR.
    Do you think split UniRx.Share.dll and UniRx.Unity.dll?
    It is impossible.
    partial class is necessary.
    For example, it's hard to use Observable.Timer and ObservableUnity.TimerFrame.
    And default time based scheduler changed to Scheduler.MainThread(It's depend on UnityEngine) is the issue too.

    The separation is possible if you add some modification(my co-worker made UniRx for CLR)
    But you can't link dll for Unity and dll for CLR.

    Could you do share with source code instead of share with dll.
    In share project, use RxNET for CLR Project, use UniRx for Unity Project by #if directive.
    And generate dll for Unity and dll for CLR...
     
  16. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    >>> It is impossible.
    >>> But you can't link dll for Unity and dll for CLR.

    Everything is possible, since original Rx was initially Unity agnostic :)

    For example, it's easy to move some interfaces like IObserver.cs and ISubject.cs from Assembly-CSharp.dll to MyGame.Core.dll. So I can use these interfaces in context with no Unity Player (like console test runner or smth like this).

    It's impossible to move MainThreadScheduler.cs from Assembly-CSharp.dll to MyGame.Core.dll — well, let it remain in Assets/ folder like usual script. No problem if I can inject it to MyGame.Core.dll via interface IScheduler (object oriented way of separation of concerns).

    But this interface IScheduler isn't placed to separate movable file IScheduler.cs, it is mixed with `static partial class Scheduler` in the same file Scheduler.cs, which is contaminated with MainThreadScheduler reference, which depends on UnityEngine namespace.

    The same concerns `static class Observer` which is mixed with `static class Stubs` and `static partial class ObservableExtensions` in the same file.

    And so on.

    Although I can move these interfaces to separate files, I don't want to edit third party code and get update problems later. Just want to reorder file structure, make it more modular.
     
  17. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Yes, it would be nice to have UniRx.Share.dll with no dependencies and UniRx.Unity.dll with two dependencies on UniRx.Share.dll and UnityEngine.dll.

    Why not? Just imagine that Rx comes to you with one portable assembly, not as bunch of sources from codeplex.

    If default instances where not placed in one class, it could be possible to separate them. It could be possible to inject it with IScheduler interface if needed. Anyway, I'm not using advanced concerns like schedulers, just very basic observables like replacements for standard events.
     
    Last edited: Apr 9, 2015
  18. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    Interface of the Scheduler changed Scheduler.MainThreadScheduler to MainThreadScheduler.Instance.
    This is Rx.NET is also similar approach, I don't mind.

    Generator (e.g. Timer / TimerFrame) splits Observable and others I can not be approved.

    > Why not? Just imagine that Rx comes to you with one portable assembly, not as bunch of sources from codeplex.

    Extension method can split but static class(for observable generator) can not.

    UniRx You are separated as much as possible to UnityEngineBridge.
    However, the primary purpose is the provision of easy-to-understand API.
    Therefore, it is not willing that it is tightly coupled.

    In any case, please Pull Request in GitHub.

    Thank you!
     
  19. p87

    p87

    Joined:
    Jun 6, 2013
    Posts:
    318
    neuecc, just wanted to say thank you for all of your work on UniRx! It has become an indispensable part of my project. Great work!
     
  20. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    Hi, today new release(4.8) has been accepted!

    This release is biggest changes, introduce ObservableTriggers.
    https://github.com/neuecc/UniRx#triggers-for-monobehaviour
    It is more lightweight, more useful ObservableMonoBehaviour.

    And add subscription's lifecycle support(TakeUntilDestroy, RepeatSafe, AddTo(gameObject), etc...),
    user friendly ReactiveProperty's inspector, etc.

    ---

    Add : ReactiveDictionary
    Add : BoolReactiveProperty
    Add : More Specialized ReactiveProperty(Vector2/Vector3/Vector4/Color/Rect/AnimationCurve/Bounds/Quaternion)
    Add : ReactiveProperty.SetValue virtual method
    Add : ObservableTriggers in UniRx.Triggers namespace(ObservableAnimatorTrigger,ObservableCollision2DTrigger, ObservableCollisionTrigger, ObservableDestroyTrigger,ObservableEnableTrigger, ObservableFixedUpdateTrigger, ObservableUpdateTrigger,ObservableLastUpdateTrigger, ObservableMouseTrigger, ObservableTrigger2DTrigger,ObservableTriggerTrigger, ObservableVisibleTrigger, ObservableTransformChangedTrigger,ObservableRectTransformTrigger, ObservableCanvasGroupChangedTrigger,ObservableStateMachineTrigger, ObservableEventTrigger)
    Add : ObservableTriggerExtensions
    Add : Observable.StartWith(valueFactory)
    Add : Observable.TakeUntilDestroy
    Add : Observable.TakeUntilDisable
    Add : Observable.RepeatSafe
    Add : Observable.RepeatUntil
    Add : Observable.RepeatUntilDestroy
    Add : Observable.RepeatUntilDisable
    Add : Observable.EveryValueChanged(frameCountType)
    Add : Observable.FromAsyncPattern
    Add : WebRequest.GetResponseAsObservable/GetRequestStreamAsObservable
    Add : IDisposable.AddTo(GameObject/Component)
    Add : Logger.Raw
    Improvement : ReactiveProperty.ToString
    Improvement : ReactiveCollectionEvent.ToString
    Improvement : InspectorDisplayDrawer notify property changed on Inspector
    Improvement : InspectorDisplayDrawer auto detect known specialized ReactiveProperty
    Improvement : UnityEvent.AsObservable makes AOT safe
    Improvement : ObserveEveryValueChanged automaticaly detect object is destroy/GC and publish OnCompleted
    Fix : Compiler error on target platform as Windows Universal App
    Fix : Observable.SampleFrame doesn't call OnCompleted
    Fix : Observable.ThrottleFrame leaks internal timer.
    Fix : Observable.Timeout sometimes doesn't trigger, thanks @zhaoyk
    Breaking Change : IReactiveProperty.IDisposable moved to ReactiveProeprty.IDisposable
    Breaking Change : UniRx.UI namespace is disappeared
    Breaking Change : ObservableStateMachineBehaviour renamed to ObservableStateMachineTrigger(namespace moved to UniRx.Triggers)
    Breaking Change : TypedMonoBehaviour/ObservableMonoBehaviour is not recommended(use UniRx.Triggers instead)

    ---
     
  21. kimsama

    kimsama

    Joined:
    Jan 2, 2009
    Posts:
    166
    First, thanks for sharing the great stuff, UniRx really rocks.

    I'm trying to do various experiments with UniRx to solve real problems.

    BTW what is the best practice for the following situations?

    I'm trying to apply UniRx to turn-based RPG game such as similar to Final Fantasy series.

    • Situation: using Rx to a buffered or debuffered skill such as 'Poison' attack

    For an example, when a character who got poison attack, he/she lose 3 point of health per a turn during 5 turns. So the attacked character lose totally 15 health points over the poison attack.

    Observable with Interval or TimeSpan does not seem to be fit with this kind of situation. It depends on system timer but the problem only needs turn count.

    I looked into CountNotifier but it also does not seems to do well with this situation.

    Should I make any custom method similar to Interval which does rely on turn count not system's timer or any some other good ideas?

    Best,

    -Kim

    ps. I forked out UniRx on this https://github.com/kimsama/UniRx and you can see what I've experiments on wip/test branch. (actually can be seen on https://github.com/kimsama/UniRx/tree/wip/test/Assets/UniRx/Examples/BufferSkill)
     
  22. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    Thank you for your interest!

    I think you can create ObservableSystemTimer(TurnCountNotifier/StateMachineNotifier) like CountNotifier.
    I think that it is a good method because Timer/Scheduler is a time base, probably it is difficult to apply it well.

    Best regards.
     
  23. kimsama

    kimsama

    Joined:
    Jan 2, 2009
    Posts:
    166
    Thank you for the reply.
     
  24. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    zyzyx likes this.
  25. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    @neuecc

    Thanks so much for UniRX - you're a star.

    I have been using it with UFrame for a short while, but not I want to investigate a little more so I downloaded the latest version. I am interested in the WWW example and I am not sure about the expected output?

    Also I wondered if you had a simple JSON example or how I might go about doing this?

    cheers

    Nalin
     
  26. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114

    Thank you!

    Hmn, ObservableWWW's simple sample is here.
    https://github.com/neuecc/UniRx/blob/master/Assets/UniRx/Examples/Sample01_ObservableWWW.cs

    Return type is IObservable[string], it's string is (maybe) json.

    Code (CSharp):
    1. ObservableWWW.Get("http://api/getjson")
    2.     .Select(jsonString =>
    3.     {
    4.         /* deserialize code here! */
    5.         return Deserialize(jsonString);
    6.     });
    7.     .Subscribe(x =>
    8.     {
    9.         /* x is T */
    10.     });
    I usually use JSON.NET for Unity(paid asset) and I've created following method.

    Code (CSharp):
    1. IObservable<DataResponse> GetResponseAsync()
    2. {
    3.   return ObservableWWW.Get("[URL]http://api/[/URL]")
    4.   .Select(x => JsonConvert.DeserializeObject<DataResponse>(x));
    5. }
     
    Dustin-Horne likes this.
  27. Shildrak

    Shildrak

    Joined:
    Jul 14, 2012
    Posts:
    5
    I only recently stumbled on unirx and must say I am impressed. Great job so far!

    I do have a question regarding "best practise" for ReactiveProperty, though. Is this intended as the default choice for your model fields whenever there is a possibility you might want to bind to it? I suppose an advantage to this is that it can handle multiple subscribers where an extension like <property>.AsObservable<T> would spawn anonymous observables for each?

    Sorry, I just feel a little dirty currently when I allocate properties on my model as ReactiveProperties instead of "pure" properties :).

    I'll probably end up with a little self-imposed convention and make my properties something like
    Code (csharp):
    1.  
    2. public ReactiveProperty<float> SpeedAsObservable;
    3. public float Speed {
    4.     get { return SpeedAsObservable.Value; }
    5.     set { SpeedAsObservable.Value = value; }
    6. }
    7.  
    That way I can easily optimize later if need be.
     
    Last edited: May 13, 2015
  28. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    I recommend that you use ReactiveProperty in substitution for a standard property.
    Property's user must access to `.Value`!
    > I just feel a little dirty currently when I allocate properties on my model as ReactiveProperties instead of "pure" properties
    Yes, you are right.
    But it is easy to define and easy to understand the property is reactive or not.

    Code (CSharp):
    1.  
    2. public ReactiveProperty<float> Speed { get; private set; }
    3.  
    4. ctor() // or Awake/Start/Initialize(PresenterBase its include next release)
    5. {
    6.     Speed = new ReactiveProperty();
    7. }
    8.  
    Even your example is not a mistake because it is a preference.
     
  29. AGeorgy

    AGeorgy

    Joined:
    Sep 16, 2013
    Posts:
    42
    I have:

    Code (CSharp):
    1. _KinectInteraction_C.CursorNormalizedPosition
    2.             .Subscribe( pos =>
    3.              {
    4.                  pointer.position = new Vector2( pos.x * Screen.width, pos.y * Screen.height );
    5.                  text.text = raycastResults.Count.ToString() + ":  " + pointer.position.ToString();
    6.  
    7.                  CursorRec.anchoredPosition = pointer.position;
    8.  
    9.                  EventSystem.current.RaycastAll( pointer, raycastResults );
    10.                  if( raycastResults.Count > 1 )
    11.                  {
    12.                      text.text += ":    " + raycastResults.First( o => o.gameObject.tag != "Cursor" ).gameObject.name;
    13.                  }
    14.              } )
    TestInteraction.cs:127:
    Code (CSharp):
    1. text.text += ":    " + raycastResults.First( o => o.gameObject.tag != "Cursor" ).gameObject.name;
    I just used "for".
    But why "First" fire an error?
     
    Last edited: May 14, 2015
  30. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    It is about LINQ to Objects.
    You can reproduce ` Enumerable.Range(1, 5).First(x => x >= 10); `.
    So first throws InvalidOperationException if no element satisfies the condition in predicate.
    You can use FirstOrDefault(it returns null if element not found)
     
  31. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    It returns `default(T)`, e.g. `0` in case of `int`.
     
  32. Xonor

    Xonor

    Joined:
    Sep 16, 2014
    Posts:
    6
    Hi.
    I created issue on github, can u help me?

    https://github.com/neuecc/UniRx/issues/66
     
  33. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
    Last edited: May 22, 2015
  34. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    > LOOM
    LOOM it looks like offering only MainThreadDispatcher and ObserveOn in UniRx.
    I think possible completely replace in UniRx.

    > issue 66(can't compile/runtime error on Windows Phone 8.1)
    I've fixed.

    Known issues for iOS Platform.
    Currently, Unity 5.0.2p2 with IL2CPP can't compile, the log shows unknown error.
    It is maybe Unity's bug, I've reported.
    Unity 5.1.0f2 works, please use 5.1 instead of 5.0.
     
  35. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
  36. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    Hi, today new release(4.8.1) has been accepted!
    This release is small but contains some important fixes.
    And thank you to many contributers!

    ---

    Add : PresenterBase
    Add : MessageBroker
    Add : ThrottleFirst, ThrottleFirstFrame, thanks @torisoup
    Add : UIBehaviour.ObservableEventTrigger extensions
    Add : ReactiveCollection.ObserveCountChanged(notifyCurrentCount)
    Add : Append IReactiveCollection/IReactiveDictionary interfafces to ReactiveCollection/ReactiveDictionary
    Improvement : Make DisposableExtensions.AddTo method-chainable, thanks @shiwano
    Improvement : Make LifetimeDisposableExtensions.AddTo method-chainable
    Improvement : documentation grammer, thanks @orenro
    Improvement : Moved IScheduler interface to separate file, thanks @Qbit86
    Improvement : ReactiveProperty.Dispose as virtual
    Fix : XmlDoc warning was removed
    Fix : MainThraedDispatcher cause "Some objects were not cleaned up when closing the scene find target" error
    Fix : Nested ReactiveProperty can't show on editor inspector
    Fix : StartWith throws OnError passing non array IEnumerable, thanks @torisoup
    Fix : Observable.EveryUpdate calls OnNext immediately, thanks @torisoup
    Fix : check cancellationToken after yield at Observable.EveryUpdate/EveryFixedUpdate/EveryEndOfFrame
    Fix : Windows Phone 8.1 build error, thanks @Xianor
    Fix : Windows Phone 8.1 runtime error, thanks @Xianor
    Breaking Change : initialized from source's ReactiveProperty doesn't publish value on subscribe when value didn't set
    Breaking Change : HttpWebRequest.GetResponseObservableAsync was renamed to GetResponseAsObservable

    ---

    New feature:
    PresenterBase is support base class for MV(R)P.
    https://github.com/neuecc/UniRx#presenterbase

    MessageBroker is simple pub-sub event bus.
    https://github.com/neuecc/UniRx/blob/master/Assets/UniRx/Scripts/Notifiers/MessageBroker.cs
     
  37. AGeorgy

    AGeorgy

    Joined:
    Sep 16, 2013
    Posts:
    42
    Please show on example. How to use PresenterBase?
    Lets say, it is necessary to be able to show GUI window to do something, close the window.
    Do I need to use somewhere dispose?
    Can there be a memory leak in this case?
     
  38. AGeorgy

    AGeorgy

    Joined:
    Sep 16, 2013
    Posts:
    42
    For exampleI have a window that you can open and close.When you open the slideshow starts.Before closing the slideshow has to stop.
    How to implement it for PresenterBase?
    ReactiveProperty in model as in examples does not help a lot.
     
  39. slimshader

    slimshader

    Joined:
    Jun 11, 2013
    Posts:
    187
    Hi, I am using PresenterBase as my base class for custom Presenters as descibed in MV(R)P and while I founf that OnAwake() should be used instead of Awake() I don't understand what to use instead of Update(). SHoul;d it be replaced by OnEveryUpdate()?
     
  40. metroidsnes

    metroidsnes

    Joined:
    Jan 5, 2014
    Posts:
    67
    Does UniRx work with PlayStation 4 and other consoles?
     
  41. slimshader

    slimshader

    Joined:
    Jun 11, 2013
    Posts:
    187
    Observable.Join() missing?

    I am trying to implement example from "Combining" section of linked article (http://sugarpillstudios.com/wp/?page_id=279) and it seems UniRx does not have Observable.Join()? What to use instead?
     
  42. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
    Sorry for late responses.

    Question about PresenterBase:
    Hmm, is it about PresenterBase?
    For example, Window already exists and default is inactive(open = active, close = inactive).
    It can control by PresenterBase.
    If Open and Close is asynchronous(for example, some loading, animating, etc), returns IObservable, it's async signature.
    If window is new scene, previous scene's data is all destroyed, you don't need dispose.

    Question about Update:
    You can use Update simply.
    PresenterBase only constraints Awake and Start, other MonoBehaviour's event is free.

    Question about Console:
    Maybe works but I don't have console's development environment, I can't check it.

    Question about Observable.Join:
    Yes, and sorry, the operator is missing.
    I accept your request, thank you.
     
  43. AGeorgy

    AGeorgy

    Joined:
    Sep 16, 2013
    Posts:
    42
    How to make a condition for the stream?
    I'm doing:
    Code (CSharp):
    1. Temp = Observable.Return( Unit.Default )
    2.             .SelectMany( _ => ... )
    3.             .Concat( Observable.Merge(
    4.                 Observable.Return( Unit.Default )
    5.                 .Where( _ => i == true )
    6.                 .SelectMany( _ => ... )
    7.                 .SelectMany( _ => ... ),
    8.  
    9.                 Observable.Return( Unit.Default )
    10.                 .Where( _ => i == false )
    11.                 .SelectMany( _ => ... )
    12.                 ) )
    13.             .SelectMany( _ => ... );
    or:
    Code (CSharp):
    1. private IObservable<Unit> Temp( bool isTemp )
    2.     {
    3.         if( isTemp )
    4.         {
    5.             return Observable.Return( Unit.Default )
    6.                 .SelectMany( _ => ... )
    7.                 .SelectMany( _ => ... );
    8.         }
    9.         else
    10.             return Observable.Return( Unit.Default )
    11.                .SelectMany( _ => ... )
    12.                .SelectMany( _ => ... );
    13.     }
    14.  
    15.  
    16. Observable.Return( Unit.Default )
    17.             .SelectMany( _ => ... )
    18.             .SelectMany( temp => Temp( temp ) )
    19.             .SelectMany( _ => ... );
    But maybe there are best practices?
     
    Last edited: Jun 24, 2015
  44. slimshader

    slimshader

    Joined:
    Jun 11, 2013
    Posts:
    187
    Thanks! And let me just say that UniRx and LINQ for GO are fantastic assets. Thanks for making and sharing them.

    Another question: What is your recommendation for viewing Model in Inspector? I mean Presenter holds reference to Model which has ReactiveProperties. How to make model's RPs in Presenter's inspector?

    And one more: Is there a way to convert ReactiveProperty<Type> to TypeReactiveProperty? For example: would it be possible to make IsDead (from your example) a BoolReactiveProperty so that it would be possible to view it in Inspector via provided inspectors.
     
  45. daeuk

    daeuk

    Joined:
    Mar 3, 2013
    Posts:
    67
    this is being seen on uframe (Unity 5.1)... any suggestions?

     
    Last edited: Jun 12, 2015
  46. dimitroff

    dimitroff

    Joined:
    Apr 3, 2013
    Posts:
    131
    Thanks for the great library, I am looking into implementing it in our current game.

    I have a question, I want to handle all errors in the chain at one place, here is an example:

    Code (CSharp):
    1. public class Rest : MonoBehaviour {
    2.  
    3.     // Use this for initialization
    4.     void Start () {
    5.  
    6.         MakeApiRequest ("http://api.github.com/users").Subscribe (
    7.             result => {
    8.                 Debug.Log(result.GetJsonType());
    9.             }, error => {
    10.                 Debug.Log("Error: " + error.Message);
    11.             });
    12.  
    13.     }
    14.  
    15.     public static IObservable<JsonData> MakeApiRequest(string url) {
    16.  
    17.         return ObservableWWW.Get(url).CatchIgnore( (WWWErrorException ex) => {
    18.      
    19.             Debug.Log("WWW ERROR: " + ex.Message);
    20.      
    21.         }).Select( response => {
    22.             JsonData data = JsonMapper.ToObject(response);
    23.  
    24.             if(!data.IsArray) {
    25.                 throw new Exception("Error parsing Data");
    26.             }
    27.  
    28.             return data;
    29.         });
    30.     }
    31.  
    32. }
    In this case, I want to catch the WWWException and the parsing Exception in one place, because I want to show an "Error dialog" for example. Could you tell me the right approach to do this?

    Edit: I just realised that I could just use CatchIgnore after MakeApiRequest to catch all Exceptions. But if you have a better approach..

    Thanks!
     
    Last edited: Jun 17, 2015
  47. RobGraat

    RobGraat

    Joined:
    Oct 12, 2014
    Posts:
    11
    Hey, first of all, many thanks for the wonderfull library!

    I am unable to have a click stream for other buttons than the left mouse button.

    The following code does not work for the right button:

    Code (CSharp):
    1. var clickStream = this.OnMouseDownAsObservable()
    2.     .Where(_ => Input.GetMouseButtonDown(1)) // RIGHT
    3.     .Select((mousePosition) => Input.mousePosition)
    4.     .RepeatUntilDestroy(this)
    5.     .Subscribe((mousePosition) => Debug.Log("Mouse click at: " + mousePosition.ToString()));
    Is the code behind OnMouseDownAsObservable already filtering for the left mouse button, making it unable to get a right mouse button click stream using OnMouseDownAsObservable?

    EDIT: Doh, the OnMouseDownAsObservable is based the Unity event OnMouseDown which only acts on the left mouse button.

    Cheers,
    Rob
     
    Last edited: Jun 18, 2015
  48. RobGraat

    RobGraat

    Joined:
    Oct 12, 2014
    Posts:
    11
    To get functionality to detect non-left mouse clicks I made a new ObservableTrigger based on the OnMouseDownAsObservable extension:

    Code (CSharp):
    1. // Extensions for components.
    2. public static partial class ObservableTriggerExtensions
    3. {
    4.     /// <summary>
    5.     /// Attaches a ObservablePointerTrigger component to the
    6.     /// game object this component is attached to.
    7.     ///
    8.     /// Results in a stream of PointerEventData objects whenever
    9.     /// the pointer clicks the game object.
    10.     /// </summary>
    11.     public static IObservable<PointerEventData> OnPointerClickAsObservable(this Component component)
    12.     {
    13.         if (component == null || component.gameObject == null) return Observable.Empty<PointerEventData>();
    14.         return GetOrAddComponent<ObservablePointerTrigger>(component.gameObject).OnPointerClickAsObservable();
    15.     }
    16. }
    Code for the ObservablePointerTrigger component implementing the IPointerClickHandler interface. The other IPointer...Handler interfaces are implemented likewise.

    Code (CSharp):
    1. /// <summary>
    2. /// Implementation of IPointerClickHandler.
    3. /// </summary>
    4. public partial class ObservablePointerTrigger : ObservableTriggerBase,
    5.     IPointerClickHandler
    6. {
    7.     Subject<PointerEventData> onPointerClick;
    8.  
    9.     /// <summary>
    10.     /// OnPointerDown is called when pointer clicks while
    11.     /// over the game object or interface.
    12.     /// </summary>
    13.     public void OnPointerClick(PointerEventData eventData)
    14.     {
    15.         if (onPointerClick != null) onPointerClick.OnNext(eventData);
    16.     }
    17.  
    18.     /// <summary>
    19.     /// Streams a sequence of PointerEventData objects.
    20.     /// </summary>
    21.     /// <returns>Sequence of PointerEventData objects</returns>
    22.     public IObservable<PointerEventData> OnPointerClickAsObservable()
    23.     {
    24.         return onPointerClick ?? (onPointerClick = new Subject<PointerEventData>());
    25.     }
    26. }
    To be used like this:
    Code (CSharp):
    1. private void Start()
    2. {
    3.     var pointerDownStream = this.OnPointerClickAsObservable()
    4.         .Select((pointerEventData) => pointerEventData.button)
    5.         .RepeatUntilDestroy(this)
    6.         .Subscribe((button) => Debug.Log("User clicked " + button.ToString() + " mouse button."));
    7. }
    Cheers,
    Rob
     
    altschuler likes this.
  49. neuecc

    neuecc

    Joined:
    Apr 20, 2014
    Posts:
    114
  50. slimshader

    slimshader

    Joined:
    Jun 11, 2013
    Posts:
    187
    Hi, I have another question regarding PresenterBase: what is the usage pattern for the objects instantiated at run-time? At the moment after adding Presenter component to newly instantiated GO I am calling PropagateArgument() on this component. Is that the right way to go?

    And one more: I've noticed in your last presentation (fantastic stuff btw) that when creating custom Observables (DOTween sequence completed) instead of just returning 'subject' variable you return subject.AsObservabe() (I just noticed same thing in UniRx docs in
    LogCallbackAsObservable() method implementation), why is that? I mean why calling .AsObservable() on return value it already is an Observable?
     
    Last edited: Jun 27, 2015