Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Official DOTS Development Status And Next Milestones - December 2021

Discussion in 'Entity Component System' started by LaurentGibert, Dec 9, 2021.

Thread Status:
Not open for further replies.
  1. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Not if you're dealing with pure components, which is the case in my situation. I need pure components because I would have serious instantiation costs without those. My use case is more complex than the score example; basically when I click on an object in my game, I need to generate a UI that displays all the properties of that object, based on what kinds of stats it has. Kinda like an in-game inspector. So this UI window that displays all kinds of stats isn't something that can be pre-built; each object stat UI entry is generated at runtime.

    I'm not against the idea of polling, but if using a polling approach, each stat display UI element would have to know which stat Entity it has to observe the value of. But that's not a possibility since it's not safe to store Entity fields in monobehaviours (as far as I know). We'd need some kind of companion Entity for each stat UIs, and that companion Entity would need to hold a reference to the Entity of the observed stat, as well as the managed UI Text reference. A main thread system would iterate on those companion entities, and update the UI Text value based on its assigned Stat Entity value

    So this is possible right now, but not possible if managed components go away. Being able to store Entities in monobehaviours would solve our problems though

    And now imagine that I have the option of incrementing/decrementing some of these stats using UI buttons. Button click events happen in monobehaviour land only, so how can we mod a value on a specific stat Entity assigned to that button when it is clicked? Once again, it's like we'd need to be able to store Entities in Monobehaviours

    Our alternative is to work with stat ids and dictionaries/utils that allow us to retrieve a stat entity or stat UI display based on an id, but this has a high maintenance cost (gotta make sure to manually assign stat ids to everything) and it's a lot more work than it should be

    Just one main thread system at the end of the frame would do the trick, it's a sync point we'd still have either way due to end frame command buffer systems
     
    Last edited: Jan 22, 2022
  2. TieSKey

    TieSKey

    Joined:
    Apr 14, 2011
    Posts:
    219
    Mmmm afaik it is safe to store the entity struct in managed land as long as u keep track of the life cycle yourself. What I mean is, unity won't change an entity id and version unless u destroy the entity and it gets recycled (version should change anyway, only ids get recycled).

    I have my own kind of DoD outside of ECS and what I do for UI sometimes is to use a visitor pattern where small pieces of code look for the presence of certain data to write/draw something and do nothing if it's not present. U could do something similar with 1 visitor per component and storing the entity refs on managed land.
     
  3. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    I'm pretty sure this just refers to the AddHybridComponent<T>(component) method in conversion systems.
     
  4. JesOb

    JesOb

    Joined:
    Sep 3, 2012
    Posts:
    1,081
    Regardless of decision unity will made for ECS we always can store direct reference to managedComponent inside pure struct storing it as IntPtr i.e. Int64 and convert back to ManagedReference on use from managed system
     
  5. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Indeed.
     
  6. TWolfram

    TWolfram

    Joined:
    Aug 6, 2017
    Posts:
    75
    Is it not? I've been using entity references in GOs for my own hybrid approach and have only found it to cause bugs when I enable play mode options (domain/scene reload); anything I should be aware of that would make this an unsafe approach?
     
  7. equal

    equal

    Joined:
    Dec 14, 2012
    Posts:
    77
    Damn that is one HOT CAKE over here, it feels like we are deciding at this very moment what Unity will do for us!

    Personally i would love to have a way to go Pure ESC/Dots mode in the Editor and the only reason for that is that it would act like a chain on the project, forcing me to find Solution for the Problem in ESC/Dots only.
    I would be able to sleep at night, knowing there is no non-ESC/Dots thing i overlooked or have done by misstake, knowing if i follow a tutorial and it works, it must be ESC/Dots too.
     
  8. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    939
    Your more complex exemple seem to rely on the player selecting an entity first.

    So you could have a dedicated "Inspected entity" component on your player that is populated and depopulated based on user selection and have you UI monobehavoir query through entity manager that component. As a result you would either have entity null (hide all item inspection ui) or have an entity that you can inspect. After that you just need to query the entity data through entity manager to display it. You can rely on the archetype to define. What parts of the ui should be displayed or not.

    As for updating the values your ui components know have a "dynamic" reference to the values to update so you should be fine.

    Finally if the entity to inspect becomes invalid you can detect that in the monobehavior and hide the ui and depopulated the inspected entity component of your player.
    It's not because the value you want to display belong to an entity that the ui should belong to it too. You can decouple these and have the ui react based on the selected entity.
     
  9. kite3h

    kite3h

    Joined:
    Aug 27, 2012
    Posts:
    192
    I'm glad it wasn't cancelled.
    Developing a game with DOTS is not just about changing the coding style.
    For example, we have been using quaternion key animations for many years. But is that really true? If you have to use a control rig anyway, wouldn't it be much better to just use the position key?
    You should think about whether it would be more efficient to change all of the modeling style and uv mapping style , etc.
     
    bb8_1 likes this.
  10. kite3h

    kite3h

    Joined:
    Aug 27, 2012
    Posts:
    192
    Perhaps the questioner's intention was different.
    Before OOP became common, the biggest reason for introducing OOP was GUI. MFC and OWL are typical examples.

    DOD is not a silver bullet, I think it is true that applying DOD to UI is a bad idea.
    But I feel the need to make the UI asynchronous.


    Is there any way to make Unitask easier to use?
     
  11. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    908
    Have there been any changes to DynamicBuffers in 0.5 or are there any planned for 1.0?

    First, in-chunk dynamic buffers have a huge overhead for data acquisition or getting the NativeArray. Why that is, I never found out.
    Second, for larger dynamic buffers, they are moved as individual array to Heap memory. I hope this works different in the future. Having N entities and N amounts of arrays in heap isn't great. Some kind of chunked list that at least is able to optimize the data over some amount of frames would be appreciated. This is a rather complicated problem to get right but I think it would be worth the investment in the long run.
    DBs are great on paper but in practice they are limited, don't have good performance characteristics while still feeling very integral to the usage of Entities.
    As developers we can solve the problem with our own data containers but I think we are all doing the same thing over and over again and instead could make a great generic system for it with enough engineering brain power.
     
    Anthiese and Tony_Max like this.
  12. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    I'm trying to understand what all this will mean for our particular project. Would appreciate if anyone can clear it up for me.

    Some facts about the project:
    - It's using Unity 2020 LTS and Entities 0.14
    - Only a core set of Entities features are used - creating components, systems. No SubScene or any of the Hybrid stuff.
    - The entire client side of things relies on GameObjectEntity for a hybrid approach (which can't even be added, we have to copy it from other prefabs). So everything visible is a normal GameObject with MeshRenderer etc, but interaction with ECS world is done via client-side ECS systems that use GameObjectEntity for update GameObjects state based on ECS state.
    - The project is very complex and deep into production (hard-launched).

    Now we always try to update to the next LTS version as soon as they are released and proven stable. So given all the above, I have questions:

    1) Is it possible to update to 2021 LTS and keep using Entities 0.14-0.17 ?
    2) Is there any plans to release all the currently "hidden" versions between 0.17 and 0.50? If not, then what is the reasoning behind such restriction? Having bug fixes from later versions would really help.
    3) If we update to 0.50, how much the API will be changed? Most importantly, will GameObjectEntity (and all the EntityManager's "ComponentObject" stuff) continue to work?

    Thanks in advance.
     
    bb8_1 and apkdev like this.
  13. TieSKey

    TieSKey

    Joined:
    Apr 14, 2011
    Posts:
    219
    Iirc, no u can't. 2022 something introduced breaking changes in preparation for 0.50 and it was backported to 2021. But check it out, maybe u can dodge the bullet since you are not using all packages.
     
    bb8_1 and phobos2077 like this.
  14. s_schoener

    s_schoener

    Unity Technologies

    Joined:
    Nov 4, 2019
    Posts:
    81
    None that I am aware of. If you run into serious performance issues, we'd appreciate a bug report.
    You can try, but there is no intention to support 0.14-0.17 on 2021 LTS and it is likely that you will run into breakage.

    There are no such plans right now. The issue with releasing these versions is that each release comes with a lot of work required for testing compatibility of the packages among each other and QA'ing these releases properly. So it's not that we have 10 package versions that we just didn't release, but rather that the few "version numbers" that we have in between 0.17 and 0.50 are just snapshots without any of the extra work and fanfare that you'd usually need around a release.

    As of writing, GameObjectEntity and ComponentObject both still exist and are supported to the same extend that they were before 0.50. There are no concrete plans to elaborate on GameObjectEntity and right now I'd (personally) consider it a fringe feature. The feature is still actively exercised by our tests for the moment. That said, this may still change for the eventual release of 0.50 or later versions.
     
  15. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    246
    Are there any plans to prevent ragdolls in Unity Physics from polluting the entities window with root-level entities? Like perhaps treating entities with Parent and LocalToWorld and without LocalToParent as if they are root-level entities (have them translate, rotate, and scale in world-space)?
     
    thelebaron likes this.
  16. OrientedPain

    OrientedPain

    Joined:
    Mar 26, 2018
    Posts:
    37
    Should I wait for ECS 1.0v to start my new project?

    If yes, that means I should wait until the 1st quarter of 2023, right?

    The ECS 1.0v target the FPS game types or similar and not MMORPG, right?
     
  17. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,131
    We hear you. No, no, no
     
  18. PolarTron

    PolarTron

    Joined:
    Jun 21, 2013
    Posts:
    87
    I don't know how you managed to arrive at this assumption. An Entity Component System doesn't care what type of game you're making.
     
  19. OrientedPain

    OrientedPain

    Joined:
    Mar 26, 2018
    Posts:
    37
    I mean that if the Netcode (for entities) that depends on ECS can load 1000s of NPCs (monsters) and 1000s of players simultaneously at the 1st release (ECS 1.0v)?
     
  20. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,327
    I don't know about Unity's netcode, but current ECS is already fast enough to have millions of networked objects.
     
    bb8_1 likes this.
  21. OrientedPain

    OrientedPain

    Joined:
    Mar 26, 2018
    Posts:
    37
    All thanks to you. :)
     
  22. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,327
    Not really. More thanks to DOTS/ECS architecture.
    There aren't any special tricks required, it's really that fast.
     
    bb8_1 likes this.
  23. PolarTron

    PolarTron

    Joined:
    Jun 21, 2013
    Posts:
    87
    Simple answer: Yes.

    Longer answer: I'm making my own open source netcode plugin for Entities.

    upload_2022-1-31_18-21-31.png

    If I can easily get 1000 entities in a single snapshot with delta compression at 64 ticks per second then I'm pretty sure Unity can get something similar going on with their implementation. I'm on my first iteration.

    I don't know what their final version (or vision) of Netcode for Entities would look like. The Transform package seems pretty stable. But what I can say for sure is that Burst, Jobs & Native Collections in its current state is already enough to have servers supporting thousands of entities and players.

    It's all data transformations anyways and DOTS is getting pretty good at doing them. By default you have insane speed improvements.
     
    phobos2077, bb8_1 and Krajca like this.
  24. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,983
    Nice! Out of curiosity, what networking architecture are you implementing?
     
    PolarTron likes this.
  25. PolarTron

    PolarTron

    Joined:
    Jun 21, 2013
    Posts:
    87
    Everything I can learn from the Overwatch Networking GDC Talk, Glenn Fiedler articles and Unity FPSSample deep dive video.

    Once 0.5 hits I'll be able to release a preview version of it. I'm using a custom fork of some of the DOTS packages (manually upgraded) to be able to use the latest versions of some of them, like Transport 1.0.

    Copy paste from my private github repo

    Main Features
    • Clientside Prediction & Server Reconciliation
    • Public and Private Snapshots
    • Delta Compression
    • Spatial Hashing
    • Bit Compression
    • Code Generation
    • Tick Synchronization and Tick Dilation
    TODO
    • Implement RCON protocol.
    • Use the ProfilerRecorder API to display stats in the profiler.
    • Snapshot Prediction as described in the Unity FPSSample Deep Dive video.
    • LZM or DEFLATE compression of predicted snapshots.
    • Wrapper around the Unity Physics Package to use it for physics simulation.
    • Hybrid read-only way for "attaching" gameobjects to networked entities.
    • Unity Relay Service
     
    foobee, MehO, ThatDan123 and 5 others like this.
  26. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,983
    I'm quite inexperienced with networked games so don't mind me if what I say doesn't make any sense. But one of the major barriers for me to learning to develop networked games is that most netcode packages seem to use two separate data transfer mechanisms, snapshots and RPCs. And the timing between the two and when to choose one over the other is always underspecified which to me just feels like trying to write multi-threaded code without synchronization primitives.

    Anyways, if you manage to make the API fully existence-based processing or solve this problem some other way, that would be a pretty massive breakthrough and I would do what I can to support you!
     
  27. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    When it comes to netcode, if Unity can pull off float determinism, then we can have a netcode solution where the user never has to think about netcode at all, and can just program games as though it was single player, and it magically can turn into an online game if you want to.

    This is the case with Photon Quantum; it's basically a whole deterministic game engine made for networked games. It serves as a proof that deterministic networking is the key to making networked games accessible to everyone. I know the whole "you don't have to think about netcode anymore" sounds like a ridiculous hyperbolic statement, but it is the truth, and I've experienced it first-hand in practice. I've made a whole online game in Quantum, and there is not a single point in the code where I had to define what gets synced or how it gets synced. And the end result is a fully client-predicted lag-compensated online game with low bandwidth consumption, so it's suitable for networking games with tons of actors

    Maybe this kind of full-world deterministic rollback solution is not the best fit for ALL games, but it would be plenty sufficient for most indie devs I'm sure. The main drawback of this approach is that depending on ping and tickrate, it can multiply the CPU cost of your simulation by x5-x10. Deterministic rollback offloads a lot of bandwidth cost to CPU cost, but CPU performance happens to be what DOTS is extremely good at. So it's a great match

    This is why I really hope to hear more about whether or not determinism in DOTS is still something that is being worked on. It would be the key to making a game-changer netcode solution that turns Unity into the go-to engine for online games
     
    Last edited: Feb 1, 2022
  28. OndrejP

    OndrejP

    Joined:
    Jul 19, 2017
    Posts:
    296
    When you have non-deterministic game, both mechanisms are needed. One is for transferring state, other is for transferring events. It seems there's overlap, because you can transfer state through events, but it really isn't that big.

    I think about it like this:
    When new player joins mid-game, he should get everything he needs through state.
    The events are used for sending input to server and other fire-and-forget things
    - particle effects, which are not included in state
    - animations (eg. player gestures)

    Sometimes you have a choice, lets consider weapon with reload animation.
    The weapon starts reloading, when it finishes state is modified and transferred.
    When the reload animation starts, server can send RPC, but you can also decide to make it part of the state.

    When the client presses reload button, input is sent to server through RPC as well (client-server RPC is usually called Command and it's validated by server). Also client does not typically "own" or send state to server, at best client can send command saying: I'd like to modify state of this object like this and it's up to server what does with such information.
     
    bb8_1 likes this.
  29. TheOtherMonarch

    TheOtherMonarch

    Joined:
    Jul 28, 2012
    Posts:
    791
    Another way to think about it is that snapshots are sent unreliably with delta compression. Every so often you send the whole game state so that your delta snapshots don't keep increasing. The deltas are encoded based on the last full game state because you may not received all the snapshots.

    Things that change quickly like quaternions do not get as good compression ratios and the longer you wait before sending the whole game state the worse the efficiency will be. You can use lossy smallest three compression for quaternions. But I am not sure if I would try that.

    RPCs on the other hand are reliable and get resent if they are not received. They can be inputs from the clients or events sent out by the server that need to be guaranteed to be received by the clients.

    With determinism you can recreate the game state just from the inputs. So you don't need to send Events or game state. Except if someone joins then you need to send the game state or rerun the simulation from the start using inputs.

    -----------------------------------------------------------------------------------------------------------------------
    It is very hard to determine bandwidth requirement because of this.

    Uncompressed game state for 1000 entities sent to 6 player at 60 FPS
    quaternion orientation: 128 bits
    float3 velocity: 96 bits
    float3 position: 96 bits

    Bandwidth (128 + 96 + 96) * 6 * 60 * 1000 = 115.2 Mb per second upload without packet header requirements and RPC events etc. Stuff like starting and stopping shooting are not included etc.

    Probably you can get a 25-50 time reduction with delta compression in the best case when most of the entities are static. So 4.608 + 115.2 / 60 = 6.528 Mb per second upload. In reality you will need probably more like 10 Mb to account for RPCs, packet headers, more complex entities, start and stop shooting messages etc.

    10 Mb is a lot of bandwidth for only 6 players and it may not be enough because it assumes that maybe only 10-20% of the entities are moving. I personally think that you would want a 20 Mb upload speed for the server maybe more because all your units could be moving and shooting. In the USA broadband is defined as 25/3. A reasonable requirement for a game would be 3 Mb upload with a actual over the wire requirement of 1.5 Mb.
     
    Last edited: Feb 2, 2022
    Menion-Leah, MehO and phobos2077 like this.
  30. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    823
    Will EntityManager ever be burst-able?
     
  31. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    Most of it already is, that's how ISystem[State] can work

    They have all methods marked with it's burst state

    upload_2022-2-2_12-34-8.png
     
  32. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,983
    As far as I am aware, it is on the backburner. And while I have a lot of thoughts on this, I will save them for someone who is actively working on a Quantum-like product.

    @OndrejP @TheOtherMonarch
    Thanks for trying to explain this to me. However, you misunderstood me, which is mostly my fault for not being more specific. I'm familiar with the concepts of networking architectures, such as authoritative servers, client-side prediction, misprediction rollback, delta compression, spatial priorities, tick dilation, ect. I've done enough research on these topics to not be intimidated by them. They are not what is stopping me.

    My issue is the implementation architecture of any given solution. In other words, my issue is how I make my custom game code operate correctly with the netcode solution. I have to know every sequence of things that can go wrong and how I handle them for every aspect of the game. I recognize most people just ignore this and firefight the common issues with sufficient success, but that's just not how I reason about problems.

    Let's say I have the typical FPS authoritative server and client-side prediction solution like Unity's Netcode. I need to send the authoritative server state from the server to the client. It seems there are two channels to send data from the server to the client. One is via snapshots. The other is via RPC.

    Snapshots make sense to me. There's going to be some sequence of schemes for handling bandwidth reduction, out-of-order and dropped packets, ect. But every once in a while, the client is going to need a complete snapshot of the entire game state in order to play the game. So what purpose does RPC provide here?

    What's more confusing is that RPC doesn't seem to be synchronized to any particular snapshot, and can arrive at any time in any order. But without a valid snapshot of the game state, the client can't play, so what good is the RPC anyway? Yet every example I come across involves using an RPC to load a level or spawn a player. That just doesn't make sense when I can package my events with snapshots and have hard guarantees as to the execution order of things because the data is resolved in the snapshot reassembly and rollback code. Sure, propagating events as state might be unintuitive, but that's already the ECS way of doing things. So that's what I mean by "existence-based processing". I want one channel of data from the server to the client where the client either has a complete snapshot or a partial snapshot with incremental data.

    Now about client to server transfers. I want to send an abstract representation of actions as well as some client state to the server. RPCs almost make sense for this, until you remember what RPC stands for, Remote Procedure Call. Why the heck am I trying to call a function on another device in a data-oriented ECS? Just let me send a message from the client, and let the server batch-process those messages jobified and parallel. You know, using existence-based processing.

    I guess this turned into a rant against RPCs. I don't really see the use case for them and instead they just seem like a lazy programmer convenience that opens the door to out-of-sequence execution bugs. Am I missing something?
     
    Krajca likes this.
  33. TheOtherMonarch

    TheOtherMonarch

    Joined:
    Jul 28, 2012
    Posts:
    791
    I don't really like the client server with RPC and snapshots that much myself. Because it takes a lot more bandwidth for the same results. With ECS you have already done most of the work to get a determinist architecture working anyway.

    RPCs use much less bandwidth then snapshots. You can have a event like die, kick player, start firing weapon, stop firing weapon, fire single shot, start burning, open door, get into vehicle, text message etc. One way you can save bandwidth is by sending the server start and stop firing weapon events for example instead of sending a message for each projectile. Since hit detection is done on the server the client can just fire a fake graphic.

    Traditional client server is not perfectly synchronized unlike a determinist lock step architecture. It just needs to be good enough to fool the player most of the time and when it fails you get lag.

    You probably don't want a true pure lock step determinist architecture. Because there will be a delay from networking. So, you will still need client side prediction and roll back. But you will have a ground reality that is lock step deterministic in a separate world instead of being on the server if that makes sense.

    Some games have client side prediction. Some people think this is the same as dead reckoning prediction but it is actually different. Counter Strike's client side prediction keeps using the inputs it sends to the servers and runs the full simulator code that is also running on the server using those inputs. Other players snap shots are delayed by 100 milliseconds and used for interpolation. That means that even on the server there is a additional fake 100 milliseconds delay. Naturally you need to also have anti-lag compensation for this to work well.
     
    Last edited: Feb 2, 2022
    phobos2077 likes this.
  34. Ashkan_gc

    Ashkan_gc

    Joined:
    Aug 12, 2009
    Posts:
    1,102
    @DreamingImLatios I agree that this could be confusing before you start practicing it. If you haven't watched the I shot you first video from Halo 3 on GDC vault to see how many latencies you have to hide and how much you need to make a different decision based on each ability and perceived behavior of it by the clients. the perceived word is the keyword here. However this said the RPCs from server are much less used from server to client and generally for those events which happen very infrequently but clients need to know about them as soon as they happen. each value add to the snapshot needs a bitmask in the delta and this adds up so usually the main/most important state of the game is sent using snapshots only. you can also look at source code of older open source shooters to see how they do it and why.

    It would be great if everything in the real-world could be represented using a very clean and easy to understand abstraction but it is exactly the point of DOD to not do that and look at the data and see what mechanism is best for each data. The fact that race conditions and order issues happen between RPCs and snapshots is not an easy thing to handle and for sure should be minimized. Also some network games don't use RPCs which are essentially messages for any game related events either so it is possible for some games in some situations, specially those which don't much too much one off events and special states. Also the networking white paper of Dongeon seige is a very good resource on this on how they ended up implementing this. Not all games end up using delta compression either and there the snapshot/message containing state line is even more blurred.
     
    phobos2077 likes this.
  35. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,983
    Very little of DOTS is actually ready to be deterministic, even if Burst supported deterministic floats. Unless you work on Quantum or are building an equivalent, let's keep determinism out of the discussion.

    Events can be packed into snapshots as state just fine. In fact including them all in one snapshot provides more opportunity to compress them and reduces the amount of packet headers you need to construct. It is also less volatile to traffic spikes. While I am inexperienced with game netcode, I'm not inexperienced with realtime inter-device communication.

    I think you missed my point again. I'm not trying to synchronize the client and the server. I'm just trying to synchronize all data generated on the same server tick so that the client sees it all together. In other words, if the server sends a snapshot on tick 23 and on that same tick sends events Y and Z, then if I send Y and Z as RPC, they might arrive at the client before snapshot 23 arrives, or they might arrive after. And it could be that Y is supposed to execute before Z, but Z arrives first and gets executed before Y, causing the client to see an opponent fire a single round of a rifle and then switch to a rocket launcher only to die to an explosion. Sure, you can add defensive code everywhere in your simulation to mitigate this, but this sort of thing isn't a problem if all your events are embedded in the snapshot and you have a good snapshot reconstruction mechanism which I would expect a good Netcode solution to have.

    Got any examples of when this is the case? I just can't think of a use case when this alternate channel from server to client is actually necessary.
    I'm guessing you are using more explicit definitions of "snapshot" and "delta" than I am. I use the term snapshot to refer to some or all of the server game state for a particular tick that is sent to the client. Deltas are just partial states dependent on previous data. It is just a compression technique. But overall this state transfer is all part of one mechanism which handles grouping packets to their tick, checksums, writing the total or partial snapshot state to the client game state, forcing rollback if necessary, ect. And I can't understand why you would need a second mechanism such as RPC alongside this. And if it isn't, can I have an Entities Netcode package and example that doesn't use RPCs? Even if it isn't optimal, it is way easier for me to reason about which will more than make up for the inefficiencies.
     
  36. Ashkan_gc

    Ashkan_gc

    Joined:
    Aug 12, 2009
    Posts:
    1,102
    @DreamingImLatios Well you mean you want everything to be state synchronization and without RPCs. UE3 tried that and that's a real pain to handle some things with it.
    You have assumptions which don't hold up in the real world and some assumptions which are easily fixed.

    1- you think two RPCs cannot be part of the same frame and all state are always sent in a single frame.
    For many games everything that happend cannot be sent in a single network tick and you have to put things in priority lists and choose to send what is most important first so you have to deal with the fact that some state might arrive later in a client than when it happend in a server. For the most important data, no matter if RPC or state synchronizationi, you can make their priority the highest so you reduce the chance. This is true about all but simplest of games and yes for simpler games you can have simpler solutions.

    Examples of things which don't easily happen without RPCs, Imagine a player punched twice and this changes the punched state twice from false to true and between these no network tick is sent to the client. you have two options, only send one of them or send punch as an event in the state.
    Now if the number of events is high then you cannot send them all in a single network tick or you have to make the network ticks low frequency and send the data for each one in multiple frames and reconstruct at the other side which means less updates and more latency.
    To make it worse some clients receive that update and some others miss the whole thing instead of missing a few RPCs/state syncs because their connection was acting up. then they'll see the game as something that prefers players with better bandwidth much more than it has too.

    So A you cannot group all state and events into one big and nice message because for congestion control and keeping the quality of the experience high under bad conditions you need to divide your state to more important and less important parts and B because some events happen multiple times between two sends of this from the server to the client and handling them correct is not that intuitive in this way.

    You can talk about B but A is physical reality of the way network connections and the physical universe work so you have to deal with it. Yes it means you'll either have a lock step game and have to do lots of rollbacks or you need to deal with the fact that somethings will deliver out of order and late and for the things which absolutely have to be ordered, you use an ordered channel and deal with the latency of it.
     
    Last edited: Feb 2, 2022
  37. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    This is news to me... :)

    Let's take a step back. We built DOTS with determinism as a core principle. There are 2 parts to this, lets be clear on what we are talking about:

    1. Code execution / default way of writing game code & engine code results in deterministic execution on the same CPU
    2. Across different CPU architectures, floating point operations result in deterministic output.

    We currently shipping with support for #1, we currently do not have support for #2.

    Even down to the job system by default enforcing that all access is in fact deterministic through the ruleset it enforces. And we generally build all functionality to enable fully deterministic behavior. Burst currently doesn't support cross platform determinism, but it does support determinism on the same CPU architecture. Physics has been specifically built to support determinism including rollback determinism. I have personally spent a week building a physics based GGPO net-code game at a hack-week using entities a while back and it worked very well. Of course it's not magic. It means you need to separate simulation world from presentation world and deal with copying the simulation -> presentation state from those worlds yourself. But you can rollback the entire state of a world with utility methods in DOTS and execution itself is deterministic as long as all the inputs are the same. And of course with the default way of writing game code in DOTS, you generally get this kind of world isolation / input isolation if you follow some simple rules.

    I am sure that at some point we will productize such a GGPO / lockstep deterministic net-code architecture ourselves but it is currently not the focus for Entities 1.0. Once we do that, we will add native support for deterministic floating point math directly into the burst compiler.

    In the short term, our focus for Entities 1.0 is purely on productizing client / server net-code architecture, well integrated end to end. And for that cross platform determinism is not required.

    We are aware that a large part of the value of determinism comes to play once we add full cross platform floating point determinism to Burst. It is not something we have not forgotten, just postponed till after the Entities 1.0 release. So to be clear. Cross platform Burst float determinism is not part of the Entities 1.0 delivery. Simply because we need to focus and we decided to focus on workflow / iteration / debugging improvements for burst instead.
     
    Last edited: Feb 2, 2022
  38. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    823
    Would custom methods like these be burst able just because I tagged them as such? They only use functions that already exists on the original methods they were derived from.
    Code (CSharp):
    1.         [BurstCompatible(GenericTypeArguments = new[] { typeof(BurstCompatibleComponentData) })]
    2.         public static void SetComponentDataReinterpret<T, E>(this EntityManager aThis, Entity entity, E Value) where T : struct where E : struct {
    3.             SetComponentDataReinterpret(aThis, TypeManager.GetTypeIndex<T>(), entity, Value);
    4.         }
    5.         [BurstCompatible(GenericTypeArguments = new[] { typeof(BurstCompatibleComponentData) })]
    6.         public static void SetComponentDataReinterpret<T>(this EntityManager aThis, int typeIndex, Entity entity, T Value) where T : struct {
    7.             unsafe {
    8.                 EntityDataAccess* ecs = aThis.GetCheckedEntityDataAccess();
    9.                 ecs->EntityComponentStore->AssertEntityHasComponent(entity, typeIndex);
    10.                 ecs->EntityComponentStore->AssertZeroSizedComponent(typeIndex);
    11.  
    12.                 if (!ecs->IsInExclusiveTransaction)
    13.                     ecs->DependencyManager->CompleteReadAndWriteDependency(typeIndex);
    14.  
    15.                 var ptr = ecs->EntityComponentStore->GetComponentDataWithTypeRW(entity, typeIndex,
    16.                    ecs->EntityComponentStore->GlobalSystemVersion);
    17.                 UnsafeUtility.CopyStructureToPtr(ref Value, ptr);
    18.             }
    19.         }
    20.         [BurstCompatible(GenericTypeArguments = new[] { typeof(BurstCompatibleComponentData) })]
    21.         public static E TryGetComponentDataReinterpret<T, E>(this EntityManager aThis, Entity entity) where T : struct where E : struct {
    22.             return GetComponentDataReinterpret<E>(aThis, TypeManager.GetTypeIndex<T>(), entity);
    23.         }
    24. [BurstCompatible(GenericTypeArguments = new[] { typeof(BurstCompatibleComponentData) })]
    25. public static T GetComponentDataReinterpret<T>(this EntityManager aThis, int typeIndex, Entity entity) where T : struct {
    26.     unsafe {
    27.         EntityDataAccess* ecs = aThis.GetCheckedEntityDataAccess();
    28.         ecs->EntityComponentStore->AssertEntityHasComponent(entity, typeIndex);
    29.         ecs->EntityComponentStore->AssertZeroSizedComponent(typeIndex);
    30.  
    31.         if (!ecs->IsInExclusiveTransaction)
    32.             ecs->DependencyManager->CompleteWriteDependency(typeIndex);
    33.  
    34.         var ptr = ecs->EntityComponentStore->GetComponentDataWithTypeRO(entity, typeIndex);
    35.  
    36.         T value;
    37.         UnsafeUtility.CopyPtrToStructure(ptr, out value);
    38.         return value;
    39.     }
    40. }
    41.  
    If these are actually burstable it will open me a whole new world of possibilities. But I don't see how the job that uses this would ever be able to tell the other jobs it's dependencies, since I can use whenever TypeIndex I feel like. The compiler would also not be able to tell
     
  39. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,983
    Sorry. I'm speaking in context. Determinism type 1 for debugging and testing is awesome and I rely on it regularly. However, Intel, AMD, and the ARM manufacturers can't even maintain floating point determinism between generations of their own chips let alone each other. So determinism type 1 is only useful for netcode on console (unless you rewrite the entire transform system to use integers). I can't target console, so I'm stuck with needing type 2 determinism if I want a deterministic netcode experience (I don't btw, at least not for most of my projects). That means I'm waiting for DOTS 1.0 to be released. Then waiting for Burst deterministic floats. And then I'm waiting for either the Unity engine to be deterministic or for the entire simulation to be run 100% in Burst nonstop. That's far from ready if you ask me.

    Not quite. It is moreso that I can't tell on the client side how old an RPC is and if I'm missing one.
    Not all state. Just the important state. State that can be extrapolated easily on the client or has less impact on the player's decisions an be transferred less often.
    This is an interesting example, so let me tell you my thought process on how I would solve it and perhaps you can point out some flaws in my reasoning. First off, I am assuming this is an action game where each player plays against the world state "in the past" which is common in FPS titles from what I understand. So if a character needs to be able to punch twice in two adjacent ticks (that's really fast), then I need to write my game code and data to understand that. So I make it a rule that a client can assume two true states in separate ticks correspond to two separate actions. Now let's compare that to RPCs in the case where the packet containing the second punch gets lost. When using tick state, the client can detect that it is missing some state that was supposed to be sent for that tick. If the state is critical, some level of redundancy, rollback, and increased latency can resolve the issue. And the client code can compensate with some custom extrapolation and smoothing in the meantime to mitigate the surprise to the player once the data finally arrives. Now with RPCs, what happens is that the client has no idea it is missing the second punch. Then when the punch comes later, the client has no idea when that punch was supposed to arrive. Suddenly a punch->punch->kick sequence can become a punch->kick->punch sequence on the client. Even if you encode the tick in the RPC, iwhen the client receives the kick RPC, it still has no idea that there was supposed to be a punch RPC before it, so it can't adapt. Players understand lag. Players don't understand actions happening out of order.

    If it is not obvious, this is what I want. I'm willing to sacrifice the amount of dynamic state (and number of players) in a game and sacrifice latency if it means I can make assumptions about the order of things and make my game a more predictable and less buggy experience. And because it is much easier for me to reason about, I can ship faster too, or focus more effort on optimizing the state that needs to be transferred.

    Being Bursted and using them in a job are two separate things. If you want to use EntityManager in a job, you need to use ExclusiveEntityTransaction. With that you can access any component type, since it will force all component types as a dependency. Here's an example of using EET to instantiate entities in batch inside a job:
    https://github.com/Dreaming381/Lati.../InstantiateCommandBufferUntyped.cs#L252-L269
     
  40. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    No. These tags are just used by unity in unit tests. You can make methods busted though using function pointers.
     
  41. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,653
    Well, not only, direct burst methods call is a thing already for a long time ;)
     
  42. TheOtherMonarch

    TheOtherMonarch

    Joined:
    Jul 28, 2012
    Posts:
    791
    I don't think snapshot deltas will help you here. They can arrive out of order or not at all. If they arrive out of order you can just throw them out.

    You need an ordered reliable channel. Most networked fighting games and combo attack RPGs use lock step determinism without prediction. Fighting games especially are often only 2 players.

    RPCs are just syntactic sugar on top of an ordered reliable channel. I personally have always just used an ordered reliable channel directly and sent the bits. Remember you have many different channel types in reality and quality of service setting like Nagle, send priority and resend rate. You commonly have at least.

    -unreliable
    -unreliable ordered (stuff like delta snapshots you can just drop old out of order packets.)
    -reliable
    -reliable ordered (stuff like RPCs. This has the worst latency because you need to wait for the resent dropped and out of order packets)
     
    Last edited: Feb 2, 2022
    phobos2077 likes this.
  43. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,327
    The idea is to send the delta snapshot based on the last acked one.
    This is kind of like a reliable channel, but only reliable for the most recent snapshot at a time as there's no point in resending any older state.
    Basically quake networking :)
     
    bb8_1 likes this.
  44. TheOtherMonarch

    TheOtherMonarch

    Joined:
    Jul 28, 2012
    Posts:
    791
    That would not work for a bool that gets set true > false > true. If you miss the "false" snapshot you miss the event. Snapshots are for syncing stuff like positions where you don't care about the history. It will not work well for a enum either. Unless you can infer the history from the current value.

    Tribes networking was a little different in that it did not send the whole game state as a single snapshot and had per object priority and synchronization. With is fine for some types of games where you only care about what is happening near the player but terrible for say a RTS.
     
    Last edited: Feb 3, 2022
    Anthiese likes this.
  45. Ashkan_gc

    Ashkan_gc

    Joined:
    Aug 12, 2009
    Posts:
    1,102
    @DreamingImLatios and others, we are using this thread for something it is not related to. PM me here and we can setup a time for a call/chat to talk about this. In short with today's connections and for some types of games and for a portion of the potential player base you can do that. many games including world of warcraft use TCP, Guild wars as well and they have mandatory ordered messages for everything. Fast pace shooters lend themselves not as good to this but still not impossible with limited number of objects and if you are ok to sacrifice players with lower quality connections and also if your game can deal with this economically too. However these are not assumptions which unity's NetCode can make. They should provide all mechanisms needed for the situation in the usual sense and for lower quality connections and higher object counts and you are free to not use all features of course.
     
  46. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,983
    Sorry about that. This all started by me expressing a pain point I had with Unity's Netcode and encouraging an open source alternative while we wait for 0.50. I've sent you a PM, as I'm still not convinced two separate exposed data transfer mechanisms are necessary in a mid to high-level Networking abstraction, and I invite anyone else to also PM me if they would like to change my mind and bridge some gap in understanding I seem to have.

    Anyways, is anyone else here hoping 0.50 fixes transform hierarchy performance/robustness and/ resolves the detectability of chunk in-place archetype changes for change filtering?
     
    Krajca likes this.
  47. MNNoxMortem

    MNNoxMortem

    Joined:
    Sep 11, 2016
    Posts:
    723
    @LaurentGibert are there any plans to make it easier to figure out which Dots packages are compatible with each other in 0.5 or 1.0? Just tested some package upgrades and right now it is more or less a bruteforce search to find what is compatible with each other: e.g. VMRange is in Collections 0.17 but was removed later, and is still required by the last available version of Entities 0.17.0-preview.42.

    I know this is still in 0.* space and I am not really complaining.
    SemVer 0
    However, currently it is just a pain. I have Collections 1.0.0 installed, but need 0.15. My manifest.json contains the correct version, but currently installed remains 1.0, drawn in by the Jobs package I have updated, which is not compatible. Yes I can find that by going through each package and the dependency window, but it is cumbersome.
    Code (CSharp):
    1. "com.unity.collections": "0.15.0-preview.21",
    upload_2022-2-4_10-32-8.png
    And this causes the code to not compile.
    Code (CSharp):
    1. Library\PackageCache\com.unity.entities@0.17.0-preview.42\Unity.Entities\Serialization\BinarySerialization.cs(47,81): error CS8377: The type 'T' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'NativeList<T>'
    Edit: I am aware of https://forum.unity.com/threads/dots-releases-latest-release-dots-0-17.1044523/ but hope the future is more bright than this post :p
     

    Attached Files:

    Last edited: Feb 4, 2022
    phobos2077 likes this.
  48. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    The plan is to release them at the same time with the same version number. (0.50) With the exception of collections.
     
  49. MNNoxMortem

    MNNoxMortem

    Joined:
    Sep 11, 2016
    Posts:
    723
    Sounds like a good plan ;) Thanks Joachim. Really looking forward to it.
     
  50. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    702
    Is there now a more precise estimate of when to expect 0.50? Days? Weeks? Months?

    0.17 is super robust and works for us on PC, PS4/PS5, XB1/S and Switch. Both in 2020.3 and 2021.2. Is there any feature in 0.50 that could potentially make it less stable across platforms in comparison to 0.17?
     
    Last edited: Feb 4, 2022
    tbg10101_, deus0, Orimay and 11 others like this.
Thread Status:
Not open for further replies.