Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

UniRx - Reactive Extensions for Unity

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

  1. jwvanderbeck

    jwvanderbeck

    Joined:
    Dec 4, 2014
    Posts:
    825
    So yeah dumb newbie mistake, and the errors were just no helpful. The problem is I didn't have "async" on the method signature. Adding that fixed it.
     
  2. spvn

    spvn

    Joined:
    Dec 10, 2013
    Posts:
    80
    Can someone help me with a really basic question regarding the code to detect double clicks:

    Code (CSharp):
    1. var clickStream = Observable.EveryUpdate()
    2.                 .Where(_ => Input.GetMouseButtonDown(0));
    3.  
    4.             clickStream.Buffer(clickStream.Throttle(TimeSpan.FromMilliseconds(250)))
    5.                 .Where(xs => xs.Count >= 2)
    6.                 .Subscribe(xs => Debug.Log("DoubleClick Detected! Count:" + xs.Count));
    From what I can tell from documentation here and here, Throttle() propagates only the LAST event once 250ms is up. But the above code only makes sense if Throttle propagates ALL the events until 250ms has passed. Which is the case?

    Also more generally, is there some sort of overall API/documentation for all available functions for UniRx and Rx in general? It's hard to tell exactly what I can do with UniRx apart from the examples provided.
     
    Last edited: Mar 6, 2019
  3. sheepjeffery

    sheepjeffery

    Joined:
    Nov 3, 2016
    Posts:
    3
    need support for unity2019

    Assets\Plugins\UniRx\Scripts\Async\Internal\TaskTracker.cs(116,46): error CS0433: The type 'Action<T1, T2, T3, T4, T5>' exists in both 'Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920' and 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'
     
  4. RobGraat

    RobGraat

    Joined:
    Oct 12, 2014
    Posts:
    11
    It determines every 250 ms whether there were 2 or more clicks in the last 250 ms using the Buffer operator.

    This site helped me tremendously visualizing the operators: https://rxmarbles.com/
     
    gareth_untether likes this.
  5. snarai

    snarai

    Joined:
    May 24, 2017
    Posts:
    1
    I am interested in using a method similar to other Rx implementations of .Throttle(TimeSpan duration) which would fire the first event immediately, and then suppress subsequent events until duration has elapsed. In my case, this is to prevent mashing a Button from firing the same event multiple times.

    The current implementation of Throttle is more like Debounce, in that it waits until the duration has elapsed before firing even the first event, but this causes the UI to seem unresponsive and does not work for me.

    I have seen several other solutions for RxNet, however these require either the Publish(Func) syntax, or use of the Window function, neither of which appear to be implemented in UniRx.

    Are there any plans to support these functions? Alternatively, is there any other way within available UniRx API to achieve what I wish?

    Thanks
     
  6. jwvanderbeck

    jwvanderbeck

    Joined:
    Dec 4, 2014
    Posts:
    825
    I had a similar use case. In my case I wanted to deal with network events but filter out multiple events if they occurred in a short period of time. I don't know Rx very well so I just ended up doing what seemed to work (.Buffer) but it has the same problem of the first event being delayed so I can't use too high of a value.
     
  7. xpation

    xpation

    Joined:
    Mar 8, 2013
    Posts:
    9
    Is this framework still being developed / maintained? There hasn't been commits to GitHub in a very long time. Is it abandoned now with no plans to update to Unity 2019?
     
    andreiagmu, Braza and trojanfoe_ like this.
  8. shanecelis

    shanecelis

    Joined:
    Mar 26, 2014
    Posts:
    22
    `SendItself()` will send as class A because it's implemented in A and is effectively calling `Publish<A>(a)`. You could make it virtual, and override it with the same code in B. Or you could use an extension method that'll Publish with the concrete type like so.

    Code (CSharp):
    1. public static class MessageBrokerExtensions {
    2.   public void SendItself<T>(this T obj) {
    3.     MessageBroker.Default.Publish(obj);
    4.   }
    5. }
    Personally, I wouldn't try to engage in a lot of message object inheritance. You're probably better off treating them as Plain Old Data Objects and no inheritance despite it not being DRY because the broker isn't going to respect any kind of inheritance hierarchy. (You could rewrite it to respect inheritance but that'll alter its performance negatively.) If you `Publish<object>(a)` then you'll only `Receive<object>()` regardless of what the type of 'a' actually is.
     
    Last edited: May 3, 2019
  9. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    Just FYI, disposing a Subject with 7000 subscriptions will allocate 150MB of memory.
    UniRx is using ImmutableList in ListObservers, which creates a copy of the list everytime you subscribe or dispose a single Subscription.
     
    andreiagmu likes this.
  10. MechEthan

    MechEthan

    Joined:
    Mar 23, 2016
    Posts:
    166
    andreiagmu likes this.
  11. Jialiang_Lu

    Jialiang_Lu

    Joined:
    Dec 9, 2018
    Posts:
    2
    Hi everyone,

    I have an object in my scene that I want to move every n ms where n is a ReactiveProperty. Another object moves every n ms where n decreases/increases over time. I feel that Observable.Generate with the timeSelector should be the best way to achieve this. Unfortunately, it's not implemented yet. Does anyone know the best solution for this, either implementing Generate myself from Create or find some other workarounds?

    Thanks!
     
  12. Favo-Yang

    Favo-Yang

    Joined:
    Apr 4, 2011
    Posts:
    464
    How to write a setter for ReactiveProperty?

    I have an energy property and limited to a max value. Without UniRx I can do

    Code (CSharp):
    1. public float energy
    2. {
    3.     get { return _energy; }
    4.     set { _energy = Mathf.Min(value, energyMax); }
    5. }
    6. private float _energy;
    With UniRx, something like this?

    Code (CSharp):
    1. public FloatReactiveProperty energy = new FloatReactiveProperty(
    2.     setter: v => Mathf.min(v, energyMax)
    3. );
     
  13. Ekzalphantoss

    Ekzalphantoss

    Joined:
    Sep 27, 2016
    Posts:
    11
    Hi,
    we updated our project to a newer version of Unity and replaced all our texts with TMPro. We encountered a problem with that the TMP_InputField does not have the option of OnValueChangedAsObservable() unlike the regular InputField. Are there plans to add this functionality in the next update?
     
  14. Tempest74

    Tempest74

    Joined:
    May 17, 2017
    Posts:
    133
    Hey, how can I learn how to use it? every tutorial I found is on javascript. I want to see someone who already used this. I find kind of useless the documentation, I do not understand a word
     
  15. toomasio

    toomasio

    Joined:
    Nov 19, 2013
    Posts:
    198
    Code (CSharp):
    1. /// <summary>Observe onEndEdit(Submit) event.</summary>
    2.     public static IObservable<string> OnEndEditAsObservable(this TMP_InputField _inputField)
    3.     {
    4.         return _inputField.onEndEdit.AsObservable();
    5.     }
     
    EthanFischer and andreiagmu like this.
  16. wechat_os_Qy04Id7iTsPXpB9Y6wRowIy-E

    wechat_os_Qy04Id7iTsPXpB9Y6wRowIy-E

    Joined:
    Oct 14, 2019
    Posts:
    1
    TakeWhile doesn't work as expect.
    I want to make it : when mouse down, stop a stream without any help of another stream.
    so i try to use method TakeWhile, but it seems not to work.
    TakeWhile only works well when the Observable is a List of object ( eg. Range(1,10))

    if there are some other ways to do so?

    Code (CSharp):
    1. public class MyTakeWhile : MonoBehaviour
    2. {
    3.     void Start()
    4.     {
    5.         Observable.EveryUpdate()
    6.             .TakeWhile(_ => Input.GetMouseButtonDown(0))
    7.             .Subscribe(_ => Debug.Log(_ + "Mouse haven't down yet!"), () => Debug.Log("already down!"));
    8.  
    9.         //output : not work as expect
    10.         // already down! (however I didn't press any mouse button,it just outputs as soon as game plays)
    11.         //
    12.  
    13.  
    14.        
    15.        
    16.         var stream = Observable.EveryUpdate()
    17.             .Where(_ => Input.GetMouseButtonDown(0));
    18.  
    19.         IDisposable disposable = null;
    20.         disposable = Observable.EveryUpdate()
    21.             .TakeUntil(stream)
    22.             .Subscribe(_ => Debug.Log(_ + " :Mouse haven't down yet!"),
    23.             () =>
    24.             {
    25.                 Debug.Log("already down!");
    26.                 disposable.Dispose();
    27.             }
    28.             );
    29.  
    30.         //output: work as expect but seems not so convenient
    31.         //0 :Mouse haven't down yet!
    32.         //1 :Mouse haven't down yet!
    33.         //...
    34.         //already down!
    35.  
    36.     }
    37. }
     
  17. Zimb000

    Zimb000

    Joined:
    Nov 23, 2017
    Posts:
    1
    I'm not sure if it is supposed to work nor do I know the intricacies of TMP interactions . But feels a bit strange that as I have a stream observing changes in my InputField and a prefix parameter and combines them into text. With TeshMeshPro the text overlaps strangely, but with normal Text component, it works fine. I'm using normal Subscribe for both. Don't really need a fix for this, but just reporting it. As normal Text works in my case just fine, just using mostly TMP.

    var stream = PlayerNameInputField.onValueChanged.AsObservable().Select(_ => PlayerNameInputField.text)
    .Subscribe(_ => PlayerNameTitleText.text = $"{ LocalizationManager.TitlePlayerNamePrefix} {_}");

    TextMeshPro:
    upload_2020-1-31_15-3-24.png

    Text:
    upload_2020-1-31_15-6-42.png
     
  18. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,459
    On the description is written "GameLoop(every Update, OnCollisionEnter, etc), Sensor(like Kinect, Leap Motion, etc) is all of event."

    I have a sensor that I would like to get data from. Does anyone know how UniRX actually work for this kind of situation. What does the code look like.

    Cheers
     
  19. VacuumBreather

    VacuumBreather

    Joined:
    Oct 30, 2013
    Posts:
    68
    Is there any documentation on the operators
    EveryUpdate, EveryFixedUpdate, EveryEndOfFrame, EveryGameObjectUpdate, EveryLateUpdate, ObserveOnMainThread, NextFrame, IntervalFrame
    TimerFrame, DelayFrame, SampleFrame, ThrottleFrame, ThrottleFirstFrame, TimeoutFrame, DelayFrameSubscription, FrameInterval, FrameTimeInterval, BatchFrame

    That is a bit lacking in the package. Some of these are pretty obvious, some are not obvious at all and they mostly do not have any documentation headers, nor are they explained in the wiki?
     
  20. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    Could you please add an extension for AddressableAssets.Load?
     
  21. Braza

    Braza

    Joined:
    Oct 11, 2013
    Posts:
    136
    TL;DR - how to make late subscribers receive previously emitted messages?

    Anyone knows how I can use Replay with MessageBroker.Publish() ? I guess this should do the trick.

    ----------

    I try to make sure my network-dependent objects initialize after the data arrived.

    Some of my objects get created and Subscribe later than MSGPlayerDataLoaded actually fired thus never proceed to OnPlayerDataLoaded.

       protected virtual void Awake()
    {
    MessageBroker.Default.Receive<BaseMessage>().Where(msg => msg.id == GameController.MSGPlayerDataLoaded).Subscribe(msg => OnPlayerDataLoaded());
    }


    Is it possible to look into the past and grab old events since the creation of MessageBroker?
     
    Last edited: Apr 13, 2020
  22. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,225
    I love the style of code, concise, easy to read.
    What are the use cases for making games? The more obvious example would be managing enemy and player damage hiding the mesh and wait for a moment to let particle evaporate before recycling the gameobject. Timed events seem very well suited to this.
    Also how are performances?
    I ran 100k enemies on sample12Scene
    could you help me understand where the hiccup come from?
    upload_2020-5-26_1-31-13.png
    Code (CSharp):
    1. // for uGUI(from 4.6)
    2. #if !(UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5)
    3.  
    4. using System;
    5. using UnityEngine;
    6. using UnityEngine.UI;
    7. using System.Collections.Generic;
    8.  
    9. namespace UniRx.Examples
    10. {
    11.     public class Sample12_ReactiveProperty : MonoBehaviour
    12.     {
    13.         // Open Sample12Scene. Set from canvas
    14.         public Button MyButton;
    15.         public Toggle MyToggle;
    16.         public InputField MyInput;
    17.         public Text MyText;
    18.         public Slider MySlider;
    19.  
    20.         // You can monitor/modifie in inspector by SpecializedReactiveProperty
    21.         public IntReactiveProperty IntRxProp = new IntReactiveProperty();
    22.  
    23.         public int enemyCount = 1000;
    24.         List<Enemy> enemy = new  List<Enemy>();
    25.  
    26.         void Start()
    27.         {
    28.             for(int i = 0; i < enemyCount; i++)
    29.             {
    30.                 var e = new Enemy(1000);
    31.                 enemy.Add(e);
    32.                 // UnityEvent as Observable
    33.                 // (shortcut, MyButton.OnClickAsObservable())
    34.  
    35.                 // from RxProp, CurrentHp changing(Button Click) is observable
    36.                 //e.CurrentHp.SubscribeToText(MyText);
    37.                 e.IsDead.Where(isDead => isDead == true)
    38.                     .Subscribe(_ =>
    39.                     {
    40.                         MyToggle.interactable = MyButton.interactable = false;
    41.                     });
    42.                 MyButton.onClick.AsObservable().Subscribe(_ => e.CurrentHp.Value -= 99);
    43.             }
    44.  
    45.             // Toggle, Input etc as Observable(OnValueChangedAsObservable is helper for provide isOn value on subscribe)
    46.             // SubscribeToInteractable is UniRx.UI Extension Method, same as .interactable = x)
    47.             MyToggle.OnValueChangedAsObservable().SubscribeToInteractable(MyButton);
    48.  
    49.             // input shows delay after 1 second
    50.             MyInput.OnValueChangedAsObservable()
    51.                 .Where(x => x != null)
    52.                 .Delay(TimeSpan.FromSeconds(1))
    53.                 .SubscribeToText(MyText); // SubscribeToText is UniRx.UI Extension Method
    54.  
    55.             // converting for human visibility
    56.             MySlider.OnValueChangedAsObservable()
    57.                 .SubscribeToText(MyText, x => Math.Round(x, 2).ToString());
    58.  
    59.             // initial text:)
    60.             IntRxProp.SubscribeToText(MyText);
    61.         }
    62.     }
    63.  
    64.     // Reactive Notification Model
    65.     public class Enemy
    66.     {
    67.         public IReactiveProperty<long> CurrentHp { get; private set; }
    68.  
    69.         public IReadOnlyReactiveProperty<bool> IsDead { get; private set; }
    70.  
    71.         public Enemy(int initialHp)
    72.         {
    73.             // Declarative Property
    74.             CurrentHp = new ReactiveProperty<long>(initialHp);
    75.             IsDead = CurrentHp.Select(x => x <= 0).ToReactiveProperty();
    76.         }
    77.     }
    78. }
    79.  
    80. #endif
     
  23. digimbyte

    digimbyte

    Joined:
    Jun 23, 2012
    Posts:
    58
    I am struggling.
    I have several game objects that need an icon overlay, if the user clicks on the icon, the object needs to react
    so the icon is a Gui Image with a 2D collider, and using the example custom trigger, I do get mouse up/ mouse down
    the issue is, what now? I can't run the code inside mouse up/down as it doesn't have the scope of the main monobehaviour.

    do I use this to return when the mouse was up/down?
    I'm not even sure what this code even does
    Code (CSharp):
    1.         public IObservable<Unit> ObservableClickObservable()
    2.         {
    3.             Debug.Log("Observed");
    4.             return onLongPointerDown ?? (onLongPointerDown = new Subject<Unit>());
    5.         }
    because I'm really only interested in if the object was clicked
    void IPointerUpHandler.OnPointerUp(PointerEventData eventData)
     
    Ingeny likes this.
  24. joeee19

    joeee19

    Joined:
    Jul 14, 2012
    Posts:
    56
    Hi there.

    Please tell me about the values of OnDragAsObservable and Pairwise () of UniRX because they do not behave as expected.

    Code (CSharp):
    1.  
    2. using UniRx.Triggers;
    3. using UnityEngine.UI;
    4. [SerializeField] private Image swipeArea;
    5. swipeArea.OnDragAsObservable()
    6.     .Select(x => x.position)
    7.     .Pairwise()
    If so, it can be compared well with the previous value,but
    Code (CSharp):
    1.  swipeArea.OnDragAsObservable()
    2.     .Pairwise()
    When you compare the positions of x.Current and .Previous, the same value comes in and you cannot compare.

    Touch input is done from UnityRemote, and the platform is iOS.
    Both Unity and UniRX are the latest version.
    The same phenomenon occurs when the method of .Pairwise is changed to Buffer (2,1).
    Finally, I'm having a problem with Subscribe because I want PointerEventData for x.Current.

    Thank you.
     
    Last edited: Jun 8, 2020
  25. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Has anyone found a good way to cancel in-flight observables without doing nested subscriptions like switchMap does in rxjs? I'm trying to kick off a coroutine from a mouse click which works fine except I can't cancel a previous running coroutine.

    Code (csharp):
    1.  
    2. Observable.EveryUpdate()
    3.     .Where(_ => Input.GetMouseButtonUp(0))
    4.     .Select(_ => mainCamera.ScreenToWorldPoint(Input.mousePosition))
    5.     .Select(pos => new Vector3(pos.x, pos.y, 0))
    6.     .SelectMany(pos => Observable.FromCoroutine(_ => Move(pos), true))
    7.     .RepeatUntilDestroy(gameObject)
    8.     .Subscribe();
    9.  
     
  26. connectwithub

    connectwithub

    Joined:
    Jan 9, 2020
    Posts:
    3
    How can I switch observable when a subject emits?
     
  27. Asinkrit

    Asinkrit

    Joined:
    Aug 27, 2019
    Posts:
    1
    Hi everyone!
    Please tell me what I'm doing wrong. The task was to unload the prefabs of objects through the resources in the stream. The download is successful, but for some reason during the game there is a heavy load on the rendering and physics. In a normal off-stream load, these parameters are much lower.


    private void RXSpawnObjects(BuilderPathData priorityPathData, BuilderPathData secondaryPathData, ObjectPool objectPool, LoadInterface loadInterface)
    {
    GameObject instant = null;
    InstantiateArguments orguments = new InstantiateArguments();
    orguments.objectPool = objectPool;

    for (int i = 0; i < priorityPathData.GetObjectPath.Length; i++)
    {
    orguments.pathPrefab = priorityPathData.GetObjectPath[i];
    Resources.LoadAsync<GameObject>(priorityPathData.GetObjectPath[i])
    .AsAsyncOperationObservable()
    .Subscribe(x =>
    {
    if (x.asset != null)
    {
    count += 1;
    loadInterface.SetProcentProgress(count / priorityPathData.GetObjectPath.Length * 100);
    instant = x.asset as GameObject;
    ObjectPool.InstantiateObjectPoolObjectWithoutAwake(SetOrguments(instant, orguments), photonID, out photonID);

    if (count == priorityPathData.GetObjectPath.Length)
    {
    isReady = true;

    for (int j = 0; j < secondaryPathData.GetObjectPath.Length; j++)
    {
    orguments.pathPrefab = secondaryPathData.GetObjectPath[j];
    Resources.LoadAsync<GameObject>(secondaryPathData.GetObjectPath[j])
    .AsAsyncOperationObservable()
    .Subscribe(y =>
    {
    if (y.asset != null)
    {
    instant = y.asset as GameObject;
    ObjectPool.InstantiateObjectPoolObjectWithoutAwake(SetOrguments(instant, orguments), photonID, out photonID);
    Debug.Log(instant);
    }
    });
    }
    }
    }
    });
    }
    }

    I apologize for the code I wrote.
    And thanks in advance!
     
  28. HedgehogNSK

    HedgehogNSK

    Joined:
    Jun 3, 2017
    Posts:
    24
    It's hard to find perfomance problem. But I have a few advices. First of all don't use subscribe inside subscribe. UniRx provides several methods to join streams. Second you should follow KISS principle - keep it simple stupid: so your spaghetti code should be divided in smaller logical parts.

    At the end your function will be look similar like this:
    Code (CSharp):
    1.  
    2. private void RXSpawnObjects(BuilderPathData priorityPathData, BuilderPathData secondaryPathData, ObjectPool objectPool, LoadInterface loadInterface)
    3. {
    4. GameObject instant = null;
    5. InstantiateArguments orguments = new InstantiateArguments();
    6. orguments.objectPool = objectPool;
    7.  
    8. var loadSequence = Observable.Empty<string>();
    9. for (int i = 0; i < priorityPathData.GetObjectPath.Length; i++)
    10. {
    11. orguments.pathPrefab = priorityPathData.GetObjectPath[i]; //I can't imagine fast where I have to move this operation. But I'm pretty sure that you will figure it out by your own;)
    12.  loadSequence  = loadSequence.Merge(Resources.LoadAsync<GameObject>(priorityPathData.GetObjectPath[i])
    13. .AsAsyncOperationObservable()); // We are creating stream that loads objects one by one.
    14. }
    15. var loadStream = loadSequence.Select(GetGameObject) //We need to proccess result of async operation here.
    16. //Implement function GameObject GetGameObject(Task or whatever argument ). Just use "ctrl+." in visual studio.
    17. //If you need additional parameters you can write like this Select(x=> GetGameObject(x, param1, param2...))
    18. .Do(SetProgress)// Implement procedure void SetProgress(GameObject go) that will apply changes to progress
    19. .Where(_ => count == priorityPathData.GetObjectPath.Length) // When condition is true load other objects.
    20. //Obiviously it won't work like this. I inserted this line for you to easy understand what line in code I reference to.
    21. //Equality can be replaced with a function bool Condition(GameObject go)
    22. .Select(LoadSubObjects) //implement here function to return list of subobjects
    23. .Subscribe(/*Any other actions*/);
    24. ...
    25.  
    This template for sure will not work at first, but my idea was to show, how to write it a little bit cleaner. In this way you will have opportunity to test simple functions.
    Also you should use UniRx .Debug function and .Catch, .CatchIgnore function to debug your code.
    I hope it will helps you a little.:)
     
    Last edited: Dec 1, 2020
  29. MagicianArtemka

    MagicianArtemka

    Joined:
    Jan 15, 2019
    Posts:
    46
    Hi guys. I love the UniRx as well as UniTasks. But seems UniRx was abandoned (the last commit is almost 1 year ago).

    Does the UniRx have a future? Or it already works as well as possible and devs have nothing to add/fix? If the UniRx is dead and not recommended to use - do you know any alternatives that are compatible with the latest versions of Unity (2020.3.1, for example)?
     
  30. BoteRock

    BoteRock

    Joined:
    Jan 10, 2013
    Posts:
    9
    Some of those projects get to a point where there is no more else to add. They are stable and feature complete, so one gets the impression that they are abandoned, when they haven't been updated, but that's because there is no need.
     
    Elhimp and rus89 like this.
  31. marrobin

    marrobin

    Joined:
    Oct 1, 2020
    Posts:
    7
    What's the equivalent of the of function in UniRx? I want to do something like this
    of(1)
    to create a stream that emits a single value. How do I achieve this with UniRx?
     
  32. Jelmer123

    Jelmer123

    Joined:
    Feb 11, 2019
    Posts:
    243
    I only know C# within Unity. I'm trying to add this project to my Unity project, and it uses System.Reactive. Reactive does not exist in Unity.

    I thought that by adding UniRX, I could fix it, but nothing changes. I also tried adding using UniRX; in the scripts that rely on System.Reactive, but it won't help.
    Could someone enlighten me? :)
     
  33. Tetsuya_OYA

    Tetsuya_OYA

    Joined:
    Jul 20, 2013
    Posts:
    13
    Hello.
    I have a large project using UniRx
    We are trying to optimize it.

    When moving the scene
    UniRx's "MainThreadDispatcher.AsObservableCore" calling
    GC.Alloc () "2.3 million times" per frame,
    And this causes a large spike of 6,300 ms.
    (Below image. that Captured from Galaxy A51.)

    Q. What could be the reason
    why "MainThreadDispatcher.AsObservableCore" calls GC.Alloc () ?

    I would appreciate it if you could give me a hint.

    Profiler_Spike_2020_0204.png
     
  34. Ishnubarak

    Ishnubarak

    Joined:
    Aug 28, 2019
    Posts:
    6
    I have created an issue on https://github.com/neuecc/UniRx/issues/510, but figured I'd cross post here in case there is a quick workaround...

    In Unity 2021.2.12 (and also happening on 2022.1.0b8), the extension methods in ObservableExtensions are conflicting with the extension methods pulled in by System.Reactive.

    Various error messages along the lines of: The call is ambiguous between the following methods or properties: 'UniRx.ObservableExtensions.Subscribe<T>(System.IObservable<T>)' and 'System.ObservableExtensions.Subscribe<T>(System.IObservable<T>)' are now appearing whenever there is the using UniRx; using System; appearing in the same file.

    Is there a suggested workaround / solution to this issue?
     
  35. castor76

    castor76

    Joined:
    Dec 5, 2011
    Posts:
    2,517
    I have similar problem, and I went hard way of renaming the UniRx extension method's names. Which kinda works on Windows platform, but when I try to build for the other platforms such as PS4 or Switch etc, it complains that it is missing the System.Reactive.Core (or not allowed)...

    I am using Unity 2021.2.12f1 and full .net targeting.

    Any idea? I mean, for windows build, I can see System.Reactive.Core.dll being included in the build...?

    ArgumentException: The Assembly System.Reactive.Core is referenced by Assembly-CSharp ('Library/PlayerScriptAssemblies/Assembly-CSharp.dll'). But the dll is not allowed to be included or could not be found.
    UnityEditor.AssemblyHelper.AddReferencedAssembliesRecurse (System.String assemblyPath, System.Collections.Generic.List`1[T] alreadyFoundAssemblies, System.String[] allAssemblyPaths, System.String[] foldersToSearch, System.Collections.Generic.Dictionary`2[TKey,TValue] cache, UnityEditor.BuildTarget target) (at <fd31656715644602a83e3fdfaefdee5d>:0)
    UnityEditor.AssemblyHelper.FindAssembliesReferencedBy (System.String[] paths, System.String[] foldersToSearch, UnityEditor.BuildTarget target) (at <fd31656715644602a83e3fdfaefdee5d>:0)
    UnityEngine.GUIUtility:processEvent(Int32, IntPtr, Boolean&)
     
  36. manuelgoellnitz

    manuelgoellnitz

    Joined:
    Feb 15, 2017
    Posts:
    397
    I have the same problem.
    My solution was to remove "using System;" from every class where this occured.

    After fixing all the compile errors, I discovered that this Unity update changed some other things as well. Some of the code in our app now behaves differently then before.
     
  37. hornetfire

    hornetfire

    Joined:
    Mar 24, 2017
    Posts:
    5
    I'm also trying to move a project from unity 2018 to 2020.xxx and am getting similar issues.
     
  38. MagicianArtemka

    MagicianArtemka

    Joined:
    Jan 15, 2019
    Posts:
    46
    Do you guys interested in creating a fork of UniRx and pushing it forward? Since UniRx author doesn't approve PRs and does not react to issues or forum, I can assume that project is dead.
     
    Njordy likes this.
  39. halfblue3

    halfblue3

    Joined:
    Mar 5, 2019
    Posts:
    11
    Dear sir, can I have a sample code for a very simple subject observable for a primitive variable? I really can't figure out how to use the library even thought I used RxJs before
     
  40. PAU_L

    PAU_L

    Joined:
    Feb 19, 2021
    Posts:
    11
    Forking and bring this repo up to date sounds interesting and I would like to support this initiative.
     
    Njordy and Rademanc123 like this.
  41. PAU_L

    PAU_L

    Joined:
    Feb 19, 2021
    Posts:
    11
    First clone (or download) the repo and open it as a Unity project. Look inside the
    Plugins\UniRx\Examples
    folder for examples on how to use it, there are a couple of scenes that you can open and look at usages.
     
  42. thePostFuturistUnity

    thePostFuturistUnity

    Joined:
    Nov 16, 2012
    Posts:
    53
    I'm trying to convert a project that is event driven into Observables. I see that I can convert an event into an Observable and then fire the *Observable*, but I don't get a result when I fire the *event*. Is there a way I can make the Subscriber listen to the event:


    Code (CSharp):
    1. public event Action<int> FooFoo;
    2. Subject<int> onBarBar = new Subject<int>();
    3. public IObservable<int> OnBarBar { get { return onBarBar; } }
    4.  
    5.  
    6. void Awake()
    7. {
    8. Observable.FromEvent<int>(
    9.         h => FooFoo += h, h => FooFoo -= h)
    10.     .Subscribe()
    11.     .AddTo(disposables);
    12.  
    13.  
    14. OnBarBar.Subscribe().AddTo(disposables);
    15. OnBarBar.Subscribe(mI => Debug.Log(mI));
    16.  
    17. }
    18.  
    19. private void Start()
    20. {
    21.     FooFoo.Invoke(2);
    22. }
     
  43. shanecelis

    shanecelis

    Joined:
    Mar 26, 2014
    Posts:
    22
    Hi valentin-simian,

    I edited your code so that it's doing what you want. Basically you want to put something in the subscribe body to activate when the observable is activated.

    Code (CSharp):
    1.   void Awake() {
    2.     Observable.FromEvent<int>(
    3.       h => FooFoo += h, h => FooFoo -= h)
    4.       .Subscribe(i => {
    5.         Debug.Log("Got " + i + ".");
    6.         onBarBar.OnNext(i);
    7.       })
    8.       .AddTo(disposables);
    9.  
    10.     OnBarBar
    11.       .Subscribe(mI => Debug.Log(mI))
    12.       .AddTo(disposables);
    13.   }
    This will be functional. But there is another way of doing this that seems simpler. Instead of instantiating a subject that you have this observable pump its values to, you could do this:

    Code (CSharp):
    1. using System;
    2. using UniRx;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6.  
    7. public class Example2 : MonoBehaviour {
    8.   private CompositeDisposable disposables = new CompositeDisposable();
    9.   public event Action<int> FooFoo;
    10.   public IObservable<int> OnBarBar;
    11.  
    12.   void Awake() {
    13.     OnBarBar = Observable.FromEvent<int>(h => FooFoo += h, h => FooFoo -= h);
    14.  
    15.     OnBarBar
    16.       .Subscribe(mI => Debug.Log(mI))
    17.       .AddTo(disposables);
    18.   }
    19.  
    20.   private void Start() {
    21.     FooFoo.Invoke(2);
    22.   }
    23.  
    24.   private void OnDestroy() {
    25.     disposables.Dispose();
    26.   }
    27. }
     
  44. thePostFuturistUnity

    thePostFuturistUnity

    Joined:
    Nov 16, 2012
    Posts:
    53
    Thank you 10x for your detailed explanation @shanecelis .
     
    Last edited: Jan 5, 2023
    shanecelis likes this.
  45. dimitroff

    dimitroff

    Joined:
    Apr 3, 2013
    Posts:
    131
    Does anybody knows how to Subscribe to a ReactiveProperty through Reflection. My problem is the following:

    Code (CSharp):
    1.  
    2. public enum SomeEnum {
    3.        One,
    4.        Two
    5. }
    6.  
    7. public class SomeObject {
    8.       public ReactiveProperty<SomeEnum> Something { get; set;} = new ReactiveProperty<SomeEnum>(default);
    9. }
    10.  
    11. ....
    12. var obj = new SomeObject();
    13.  
    14. var prop = obj.GetType().GetProperty("Something");
    15. var propValue = prop.GetValue(obj);
    16.  
    17. // This is not working, but I have no idea how to do it
    18. ReactiveProperty<Enum> genericEnum = propValue as ReactiveProperty<Enum>;
    19.  
    20. genericEnum.Subscribe(newValue => {
    21. // something here
    22. });
    23.  
    I will have a lot of different enum types and I don't want to manually handle all of them, but I could not find a way to make this generic.

    Thanks in advance!
     
  46. slimshader

    slimshader

    Joined:
    Jun 11, 2013
    Posts:
    187
    Don't think you can do that with reflection, it is not great with generics as it mostly operates on the level of objects and strings (for identifiers). I'd try going with Source Generators (https://docs.unity3d.com/Manual/roslyn-analyzers.html), this should allow you to generate necessary generic code.
     
    dimitroff likes this.
  47. dimitroff

    dimitroff

    Joined:
    Apr 3, 2013
    Posts:
    131
    Thanks, I will explore that direction!
     
  48. Njordy

    Njordy

    Joined:
    Mar 31, 2019
    Posts:
    24
    Are there any updates? Or project is still kinda dead-ish? Ж(
     
  49. s1m0n1stv4n

    s1m0n1stv4n

    Joined:
    Sep 14, 2012
    Posts:
    16
    There are some forks on github.
    Although I'm still using unirx in all my projects and still works. At least on mobile platforms.

    It would be great, if someone could carry on this project.
     
  50. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    Why do you need updates? Isn't it working on all Unity versions?