Not only do we get fantastic content on the video topic but you throw in wonderful tidbits like that Rider tip for reformatting your code and detected the code style for future reformatting.
It's the third time in a row now that I picked up a topic and a week later you release a video on it. It's like you're using my browsing history as an inspiration 😂 I've been teaching myself software development for the better part of two decades now, and your videos on unity are without a doubt the best on this platform, and some of the best programming videos I've come across in general. Keep the good work up, man!
Oooh this one is exciting. Awesome topic. I wish I had known about this months ago. Not sure I will use it since I'm sort of settling into my event system right now. At the least this is getting some QT in a side project. Love this!
Regarding the downsides of reactive programming. I was an engineer for some 7 years ago on a project with 500+ engineers where the client was built with reactive programming. Really interesting. I was excited to see it in action. Eventually, the project caused thousands of memory leaks and zombies... Why? Reactive programming raises the required experience level for programmers. No junior was able to handle it, and only a few seniors. At the end, the client team depended on me and another very experienced coder. Not every paradigm or framework is meant for production. But it is certainly an interesting concept and Swift/iOS managed to handle it better, and easier for junior to seniors.
Impressive at 3:08 how it's able to infer the type of the `clicks` array on line 31 based on the callback provided to `Where` on line 28. Seems like a really well designed library, thanks for the video!
This is super super cool!! and really thanks a lot for the video as you are making it simple for ppl like me to learn! You always boils down the heavy concepts really simple!! ❤
I always wondered how something like at 10:30 is possible - that's genius! Thanks for this very valuable introduction - every other video expanding on the concepts of reactive programming is highly appreciated!!
I used UniRx a lot in the past. It's useful having reactive properties and event wrappers for common unity methods like triggers and collisions. It's main strength was for UI though, which has been made largely redundant with UI Element property binding. Ultimately I stopped using it because, like many frameworks, it tried too hard to be "standalone" implementation instead of, you know, a well integrated Unity solution. As soon as a Unity framework says "Supports multiple platforms" that is a red flag.
I have fairly high confidence that this particular author is keeping Unity as a top priority, but split his library to also solve 'real world' issues at the same time since Reactive Extensions has been lacking in .NET development.
to add to this, the developers are a subsidary of Cygames, Cysharp. Cygames is a reall big multimedia company in Japan. They also make games and own "everything" in regards to it (music production, art, game design, etc.), their main(?) engine is Unity. So yes, they focus a lot on it. They got a lot of other great packages too.
Saying everything can be Observable is quite dangerous. With my last project I went Observable-crazy, and now my app's an unmanageable beast. Not every property needs to be observable. Not sure how it is with R3, but Reactive extensions can create swaths of small objects, which can really tank your GC.
Excellent video! Since your main subject is programming and gameplay patterns, I was wondering if you had heard about the Unity App UI package? It may interest you !
R3 sounds great to me, but is there a way to do advanced conditioning, for example if i had multiple buttons and variables with different subscriptions each but all of them should not work if the game isnt started and some if the player level is below 10. well we can add conditions for each button and variable but that will cause a lot of code duplication and coupling if the project get complex.
To handle advanced conditioning in R3 while avoiding code duplication and coupling, you can use a combination of shared observables and conditional operators to centralize your conditions and reuse them across multiple subscriptions. You can define observables for the conditions that need to be checked frequently, such as whether the game is started or the player’s level. You can combine these conditions using operators like CombineLatest or WithLatestFrom, and use the Where operator or similar to filter events or button actions based on the shared conditions observable.
I've been saying nugget for the past 7 years... In my defense, English is my second language. On the other hand, first time I used NuGet I most likely had B2 English proficiency at least...
It's very common, but mostly because people don't know where the names comes from which was the earlier "Nupack" project, where "Nu" was a playful take on "new." Kind of like how some people say 'toople' instead of 'tuple'.
Great video. Question though, when you change to a DisposableBag around 14:09, you still have disposable?.Dispose(); in the on destroy. I assume you can just change that to d?.Dispose();?
That's true, but keep in mind that using that token you don't have granular control over when and how the cancellation should occur, and is only effective for managing tasks that are related to the lifetime of the MonoBehaviour itself.
Could this library replace the event bus pattern? I have an inner feeling that it could, but I haven't yet figured out how exactly. And I'm very used to scriptable object event buses, are they adequate to use alongside the library?
Maybe, but these are 2 different things. An Event Bus will allow your GameObjects to be very decoupled, only interacting when events are fired. Reactive Extensions will require you to maintain a reference to the thing being observed, and will have slightly more overhead which you need to keep an eye on. In a project, I would try to throttle R3 for performance reasons as much as possible, but with an Event Bus, I would be less concerned. I think both have their place.
This library was designed to work independent of MonoBehaviours, and in fact in many other systems outside of Unity. It should work the same in any class.
The Do operator in R3 is used to perform side effects (like logging) without modifying the data stream or terminating it. It's often placed in the middle of a chain to observe or log values, handle errors, or perform other actions whenever an event occurs, without consuming or stopping the observable sequence. It is not the same thing as creating a Subscription.
@@git-amend Also note, that whatever you put inside Do() will be executed in every stream resolution, since one stream, can have multiple subscribers and thus can be resolved multiple times. Which could be good for debugging, if for example your stream is not being is not being solved too many times.
Is learning this programming paradigm worth the time spent on it? This paradigm is not used in our company and I don't know how common this paradigm is in the computer games industry?
I guess that depends on you! Some people find it difficult and feel like they will never use it. Some people think it's fantastic, but only use it once in a while. And so on... you decide. I would not say it is extremely common because most indie game devs don't like memory management.
At the very beginning of the video you said that R3 replaces Unirx. But after watching whole video I did not find out why should I? I as Unirx big fan and permanent user, did not see any difference between them except that R3 is a lot longer to setup) Can you clarify for me. What's the main difference? And what's the R3 and Unirx pros and cons? And I saw you installed both, and as for me it's quite overkill. Thanks.
UniRx has been deprecated by the developer, and won't receive any further development. I'm sure it's still fine to use in current projects, and probably will be for some time. If you want specific details on the improvements between R3 and UniRx, you should read the blog post from the author here: neuecc.medium.com/r3-a-new-modern-reimplementation-of-reactive-extensions-for-c-cf29abcc5826 I did not install both R3 and UniRx in the project, but maybe you meant UniTask. R3 is focused on reactive programming, handling event-driven data streams with observables, while UniTask is designed for efficient, lightweight asynchronous programming using tasks and awaits.
@@foolishelephant4902 Regarding micro coroutines, I can't say for sure. It's not mentioned anywhere and I haven't dived far enough into the code to be able to answer that. For the most part, R3 has it's own player loop system that is injected into the main loop so that it can properly act during different phases like Update and Fixed Update for frame based operations, the same way that UniTask does.
Great question. In my mind, the advantage of using R3 over an event bus system is that it provides a more declarative and composable approach to handling events, which gives you better management of asynchronous operations, state changes, and complex event sequences. Additionally, it gives you built-in operators and extensions for filtering, transforming, and combining events, reducing the amount of code you need to write and improving maintainability.
@@git-amend agreed, Am thinking of turning this into a universal event bus combine both advantages and remove dependencies xD don't know if this is possible
As much as these extensions are a fun idea, they've make large projects virtually unmaintainable as the knowledge to use them properly is not common knowledge creating complete havoc and spaghetti code. I wish this library didn't exist.
I feel this is quite far away from the standards of making good games, I get that this helps the observer pattern but has quite lots of complications in real world production: For example when a co-worker wants to do the same adjustments made on variable 'X' to the new variable 'Y' they will have to carefully track where every single observer was tracking/adjusting this 'X' variable to do the same with the new 'Y' variable which makes a mess and needs lots of thinking to manage it properly. For me "that I haven't trield this yet but" I don't find the pros greater than cons in this scenario (Talking game dev especially a lot of them come from amateur programming experience when it comes to building an indie studio/team) Idk if AAA studios do this as well
Happy Sunday everyone! I had a lot of fun this week playing with R3, and I hope this video inspires you to do the same! 👍
Not only do we get fantastic content on the video topic but you throw in wonderful tidbits like that Rider tip for reformatting your code and detected the code style for future reformatting.
Glad you enjoyed it!
It's the third time in a row now that I picked up a topic and a week later you release a video on it. It's like you're using my browsing history as an inspiration 😂
I've been teaching myself software development for the better part of two decades now, and your videos on unity are without a doubt the best on this platform, and some of the best programming videos I've come across in general. Keep the good work up, man!
Thanks, that made my day!
@@git-amend just like your video made mine :)
Oooh this one is exciting. Awesome topic. I wish I had known about this months ago. Not sure I will use it since I'm sort of settling into my event system right now. At the least this is getting some QT in a side project. Love this!
Awesome! I think I will be using it more as well.
Nice!
Regarding the downsides of reactive programming. I was an engineer for some 7 years ago on a project with 500+ engineers where the client was built with reactive programming. Really interesting. I was excited to see it in action. Eventually, the project caused thousands of memory leaks and zombies... Why? Reactive programming raises the required experience level for programmers. No junior was able to handle it, and only a few seniors. At the end, the client team depended on me and another very experienced coder. Not every paradigm or framework is meant for production. But it is certainly an interesting concept and Swift/iOS managed to handle it better, and easier for junior to seniors.
Impressive at 3:08 how it's able to infer the type of the `clicks` array on line 31 based on the callback provided to `Where` on line 28. Seems like a really well designed library, thanks for the video!
You're welcome!
This is super super cool!! and really thanks a lot for the video as you are making it simple for ppl like me to learn! You always boils down the heavy concepts really simple!! ❤
Thank you! Glad to hear that!
Oh man I was literally looking for this kind of video 2 weeks ago and gave up, returning to regular C# events lmao.
Never too late!
I always wondered how something like at 10:30 is possible - that's genius! Thanks for this very valuable introduction - every other video expanding on the concepts of reactive programming is highly appreciated!!
You're very welcome!
I would be really happy if a sample project was released.
I used UniRx a lot in the past. It's useful having reactive properties and event wrappers for common unity methods like triggers and collisions. It's main strength was for UI though, which has been made largely redundant with UI Element property binding. Ultimately I stopped using it because, like many frameworks, it tried too hard to be "standalone" implementation instead of, you know, a well integrated Unity solution.
As soon as a Unity framework says "Supports multiple platforms" that is a red flag.
I have fairly high confidence that this particular author is keeping Unity as a top priority, but split his library to also solve 'real world' issues at the same time since Reactive Extensions has been lacking in .NET development.
to add to this, the developers are a subsidary of Cygames, Cysharp. Cygames is a reall big multimedia company in Japan. They also make games and own "everything" in regards to it (music production, art, game design, etc.), their main(?) engine is Unity. So yes, they focus a lot on it. They got a lot of other great packages too.
as soon as I said "isn't it pronounced nugget?" you answered lmao
😄
as always, high quality unity tutorial. great job!
Much appreciated!
Happy Sunday! Excellent video :)
Thank you! You too!
Saying everything can be Observable is quite dangerous. With my last project I went Observable-crazy, and now my app's an unmanageable beast. Not every property needs to be observable. Not sure how it is with R3, but Reactive extensions can create swaths of small objects, which can really tank your GC.
Excellent video! Since your main subject is programming and gameplay patterns, I was wondering if you had heard about the Unity App UI package? It may interest you !
I have heard about it. Might make a good future video!
Your videos are excellent! ❤
Thank you so much!
R3 sounds great to me, but is there a way to do advanced conditioning, for example if i had multiple buttons and variables with different subscriptions each but all of them should not work if the game isnt started and some if the player level is below 10.
well we can add conditions for each button and variable but that will cause a lot of code duplication and coupling if the project get complex.
To handle advanced conditioning in R3 while avoiding code duplication and coupling, you can use a combination of shared observables and conditional operators to centralize your conditions and reuse them across multiple subscriptions. You can define observables for the conditions that need to be checked frequently, such as whether the game is started or the player’s level. You can combine these conditions using operators like CombineLatest or WithLatestFrom, and use the Where operator or similar to filter events or button actions based on the shared conditions observable.
I've been saying nugget for the past 7 years... In my defense, English is my second language. On the other hand, first time I used NuGet I most likely had B2 English proficiency at least...
It's very common, but mostly because people don't know where the names comes from which was the earlier "Nupack" project, where "Nu" was a playful take on "new." Kind of like how some people say 'toople' instead of 'tuple'.
@@git-amend oh I see! Like nu metal
Great video. Question though, when you change to a DisposableBag around 14:09, you still have disposable?.Dispose(); in the on destroy. I assume you can just change that to d?.Dispose();?
Oh, yeah I guess I missed that while I was recording. Good catch! Yes, a DisposableBag can be disposed in the same way.
More awesomeness! Thanks!
You bet!
You can make use of the MonoBehaviour destroyCancellationToken to avoid creating your own cts all the time.
That's true, but keep in mind that using that token you don't have granular control over when and how the cancellation should occur, and is only effective for managing tasks that are related to the lifetime of the MonoBehaviour itself.
Could this library replace the event bus pattern? I have an inner feeling that it could, but I haven't yet figured out how exactly. And I'm very used to scriptable object event buses, are they adequate to use alongside the library?
Maybe, but these are 2 different things. An Event Bus will allow your GameObjects to be very decoupled, only interacting when events are fired. Reactive Extensions will require you to maintain a reference to the thing being observed, and will have slightly more overhead which you need to keep an eye on. In a project, I would try to throttle R3 for performance reasons as much as possible, but with an Event Bus, I would be less concerned. I think both have their place.
You are amazing.
Too kind
How does this work with ScriptableObjects, particularly when using SO's as global variables (i.e. player health, game settings and the like)?
This library was designed to work independent of MonoBehaviours, and in fact in many other systems outside of Unity. It should work the same in any class.
15:35 why out of a sudden we're using Do instead of Subscribe?
The Do operator in R3 is used to perform side effects (like logging) without modifying the data stream or terminating it. It's often placed in the middle of a chain to observe or log values, handle errors, or perform other actions whenever an event occurs, without consuming or stopping the observable sequence. It is not the same thing as creating a Subscription.
@@git-amend Also note, that whatever you put inside Do() will be executed in every stream resolution, since one stream, can have multiple subscribers and thus can be resolved multiple times. Which could be good for debugging, if for example your stream is not being is not being solved too many times.
Good video. I will try the observable as scriptable objects. Is there any example like that?
Yup, should work in any class. R3 is not tied to MonoBehaviour at all.
@@git-amend 👍 Thanks for sharing the knowledge, dude.
Is learning this programming paradigm worth the time spent on it? This paradigm is not used in our company and I don't know how common this paradigm is in the computer games industry?
I guess that depends on you! Some people find it difficult and feel like they will never use it. Some people think it's fantastic, but only use it once in a while. And so on... you decide. I would not say it is extremely common because most indie game devs don't like memory management.
Very Nice interesting topic
Glad you liked it
Nice! Can you make a video about "Cysharp/MessagePipe"?
Maybe, but I think I might do one on Cysharp/MemoryPack first!
@@git-amend awesome
I switched from MessagePipe to VitalRouter. No regret.
It avoids ending with "Event Spaghetti" by design.
@@ClayManLanDay it sounds nice, i'll learn about it. Thanks
nICE!
Thank you! Cheers!
At the very beginning of the video you said that R3 replaces Unirx. But after watching whole video I did not find out why should I? I as Unirx big fan and permanent user, did not see any difference between them except that R3 is a lot longer to setup) Can you clarify for me. What's the main difference? And what's the R3 and Unirx pros and cons? And I saw you installed both, and as for me it's quite overkill. Thanks.
UniRx has been deprecated by the developer, and won't receive any further development. I'm sure it's still fine to use in current projects, and probably will be for some time. If you want specific details on the improvements between R3 and UniRx, you should read the blog post from the author here: neuecc.medium.com/r3-a-new-modern-reimplementation-of-reactive-extensions-for-c-cf29abcc5826
I did not install both R3 and UniRx in the project, but maybe you meant UniTask. R3 is focused on reactive programming, handling event-driven data streams with observables, while UniTask is designed for efficient, lightweight asynchronous programming using tasks and awaits.
Oh, it was unitask. I see. No more questions on that point) But final one) Does R3 uses micro corutines at the background as well?
Thanks for the blog post btw!
@@foolishelephant4902 Regarding micro coroutines, I can't say for sure. It's not mentioned anywhere and I haven't dived far enough into the code to be able to answer that. For the most part, R3 has it's own player loop system that is injected into the main loop so that it can properly act during different phases like Update and Fixed Update for frame based operations, the same way that UniTask does.
Thanks a lot! @@git-amend
Great one , but what is the advantage of this over bus event system
Great question. In my mind, the advantage of using R3 over an event bus system is that it provides a more declarative and composable approach to handling events, which gives you better management of asynchronous operations, state changes, and complex event sequences. Additionally, it gives you built-in operators and extensions for filtering, transforming, and combining events, reducing the amount of code you need to write and improving maintainability.
@@git-amend agreed, Am thinking of turning this into a universal event bus combine both advantages and remove dependencies xD don't know if this is possible
Cool.
Thanks for watching!
4:50 I have been doing it wrong my entire life🤯😅
😄 The name actually comes from an earlier project 'Nupack' where Nu was a play on the word 'new'.
How is the performance on this? Some numbers would be great, like how does it compare to other observer patterns
Nugget
As much as these extensions are a fun idea, they've make large projects virtually unmaintainable as the knowledge to use them properly is not common knowledge creating complete havoc and spaghetti code. I wish this library didn't exist.
For your double click coin animation example, is this more performant with using Unity Update() or R3 subscription?
I feel this is quite far away from the standards of making good games, I get that this helps the observer pattern but has quite lots of complications in real world production:
For example when a co-worker wants to do the same adjustments made on variable 'X' to the new variable 'Y' they will have to carefully track where every single observer was tracking/adjusting this 'X' variable to do the same with the new 'Y' variable which makes a mess and needs lots of thinking to manage it properly.
For me "that I haven't trield this yet but" I don't find the pros greater than cons in this scenario (Talking game dev especially a lot of them come from amateur programming experience when it comes to building an indie studio/team)
Idk if AAA studios do this as well
Can't find the source code on github