#I do wish there were some better hybrid
1 messages ยท Page 1 of 1 (latest)
Honestly, the main use case for me is things like GetSingleton<Camera>(), or GetSingleton<UIReferences>()
why would you do that instead of Camera.main or similar
where UIReferences is some mono that stores references to my ui stuff
having things that are not available in current ECS:
- skinned mesh animations
- 2D
if it's really a singleton, and it's managed, a static variable works fine?
And getting my Animator on my main character
static variable sounds like it would work for that too?
Hmm I guess I haven't tried that. And this static variable is set in Awake or something?
yup, and the standard use is defintly awake if you want it the earliest :3
I just want my physics2d to work...
that is entirely separate
Feels weird to use static variables here. Like right now my game is singleplayer. But what if I later decide to make it multiplayer? Ideally I would iterate each Animator in a system and set the animation variables based on some ECS components.
how about a List<Animator>
or a dictionary, where the key is an entity or something
(or a networkid, whatever)
Suggestions aside, already merged into master I added SystemAPI.ManagedAPI, which will indeed help with accessing the ComponentObjects :3
yeah and i'm trying to dispel the idea that using normal c# and normal monobehaviour stuff is dirty in some way when you actually are sure you will never have more than a handful of these things, and it's managed and single-threaded anyway so you can't burst or jobify it
Nice. Getting component objects right now feels really clunky
With the assembly ref hack allowing for expanded companion GOs, hybrid kinda feels okay. The transform sync systems keep throwing errors but ignoring them works fine.
Also SystemAPI.Query support for MonoBehavoiur and ScriptableObjects (which btw already works today in IJobEntity)
Wait, does this work for scene game objects? Or only MonoBehaviours added to an entity as a managed component?
I've been using GetEntityQuery(typeof(MB)) to GetSingletonEntity to EntityManager GetComponentObject
...if you know it's a singleton you could just set it on a static variable...
that would literally be faster
both to code and to run
I've disabled domain reload. I don't want to deal with cleanup of static fields
errr... what's your idea about how a static field would be stale when the singleton entity wasn't
Yea, probably, but I use that for onstartrunning and store a local reference inside the systembase
I also use those queries in require system to run.
you could just check the static variable at the top of onupdate...
(that's literally what the require does, except it's slower)
Yea, a static class with the GO as a property is the C# way, and I have done that in my lighting system for the singleton compute buffers and material properties, but dots...
but NOT "but dots"! that's the disease i want to cure here. things do not get magically faster because they're part of the entities api!
Haha, true. But good luck.
Its not about the speed, its about the consistency
consistency is wildly overrated.
Yeah perhaps. But I did like how it felt when everything was done in systems and all data was on entities.
I'm not opposed to the static idea, btw. I'll give it a try and see how it feels. Thanks for the suggestion
๐ spread the word ๐
I believe you already suggested solving this with a static dictionary, but it does start to feel weird when you want to combine ECS components with mono behaviours on corresponding game objects. I want to write code like this:
foreach (Animator animator, Speed speed) {
// Set animation var based on speed, where speed is an ICD
}
This is doable if you can add the reference to the monos as mananged components to the entities. But setting this up in baking is difficult (basically recreating the companion link stuff). And it sounds like you are suggesting that we instead write code like this:
foreach (Entity entity, Speed speed) {
Animator animator = AnimatorStaticDictionary[entity];
// Set animation var based on speed, where speed is an ICD
}
I guess this isn't all that different than something like a ComponentLookup on another entity. And since the mono lives on a game object and not the entity, it is doing a similar thing.
Alright, I think I'm coming around to this
it also makes it make more sense because baking has to exist in order to get the entity data in order for runtime. but the managed monobehaviour stuff is already in order, and doesn't need any baking; so shoehorning it into baking is quite unnatural
I have another solution rather than storing on static field:
Create an object field in World using asm ref and then use it through casts
this way it'll be World singleton and not static
yet fast access
Personally I disagree with statics because it limits ability of running multiple clients in isolation
I don't have 1 camera, I have 1 camera per world
It still seems non trivial to set up this mapping from entity to monobehaviour. Either doing some runtime instantiation or some ugly baking thing. Similar to the options I outlined. Am I missing some obvious easy way?
errr, you do? isn't only one of them rendering to the screen?
aha, that's interesting. however, should also be covered by a 2 element dictionary where the key is the world
it's true, the mapping thing is a bit interesting and i can see how you could argue baking or some step in that area should be related somehow.
my game doesn't actually do splits creen, this is just for testing but it even auto splits each client world into mini windows
and i can focus each client separately to test multiplayer interactions
one of my biggest gripes at work has been how annoying testing multiplayer features are
my trick is to have 2 copies of the project open in 2 editors
then you never have to make a build ๐
thats great until your project reaches 200gb+ ๐ข
indeed sir
the iteration benefits are so huge that i might consider another ssd for it though...
my recent issue has been more on the memory side of things
(i'm not saying it's great, of course. just my personal hack)
32gb just isn't cutting it anymore...
yeah that's low for a big project like that with 2 editors
Seems like the best option here (with what we have available) is to instantiate some prefab game object for each entity that needs one. But at that point, I can just store a ref to the mono directly in an ICD on the entity. Maybe you would still argue for using statics for slightly better performance, but the point is that the hybrid setup is still kind of annoying.
anyway i actually have minimal complaints about hybrid, i just dislike the use of statics in general but if it works for people then good enough
however i don't really understand benefit of a static mapping for say animators when you could just bind the animator directly to the entity
there's also the point that this specific thing will be solved one day by dots animation, but that won't be the end of needing to interop with monobehaviours
Right, that's what my original message was about. Doing so is awkward and non-trivial since we can't have cross scene refs between our subscene entities and the game objects in our main scene. We are forced to instantiate a prefab at runtime or do some baking thing with hidden game objects and clean up.
so the instantiating at runtime thing i agree is not super amazing, but also we know for sure that whatever solution we come up with here won't scale anyway
๐คทโโ๏ธ that's what i do (prefab referenced stored i baking and initialized at runtime) but no one really seems to onboard with it, but it's been working amazing for me
in 0.51 i had my own entity picking scripts that would actually pick skinned mesh renders attached to entities but select the entity instead
prefab stored and referenced where?
On managed comp?
i posted my full source here, to answer the question though yes just a managed comp
Sure, instantiating at runtime works fine, so long as you don't need that prefab to be referencing anything else in the scene.
funny enough that isn't even that hard to solve
i have a full cinemachine wrapper that allows targets/follow to be setup
which are referencing other game objects
What you're describing sounds like a custom solution to hybrid
(i did notice a sneaky cinemachine.dots package which i am looking forward to)
what's the case where you need it to be referencing stuff? i followed the animator example, but i didn't see where that required scene references
my only use case was cinemachine targets/follow. none of my regular hybrid stuff i have bound ever needed to reference other things
i guess targets/follow for cinemachine makes sense
I don't have a great example for that. Maybe UI references, but static would work find there.
posted this ages ago but this is how my hybrid ends up in game
https://www.youtube.com/watch?v=ZR7thzYQPmw
all cinemachine, 4 different virtual cameras from memory, follow entities
it converts (this was 0.51) off the existing components
you can't even tell it's hybrid, nothing in hierarchy etc
you just write to unmanaged components and it's handled for you
i'm hoping if/when an actual native cinemachine support comes i can just swap my own components for that implementation (might be wishful thinking =D)
continuing to ponder, some of this is an artifact of the fact that entities fundamentally is a complete hack, a hopefully reasonably successful attempt to staple an entirely unrelated engine model to the inside of an existing engine
some people like to complain and wish it was completely standalone but personally i think that's unrealistic
can you imagine how long it would take to rewrite all the tooling alone
i was working on that for a while, because tiny was basically that ๐ but indeed it did not get enough buy-in, maybe for good reasons
anyway, while i agree that this stuff is ugly, i'm not 100% sure if it would help if we made a thing to conceal its ugliness and slowness and unscalability
maybe if we put it in a class called UglySlowUnscalableHacksForHybridInterop ๐
the thing i'm really hanging out for is dots animation coming back and maybe a way to call vfx graph natively because as far as i can tell it really doesn't need to be tied to a gameobject, it's all native calls anyway except the use of transform.
whenever animation package returns it'll remove a high % of hybrid stuff for me
Well hopefully its less ugly haha
yeah it's definitely coming. people actively typing on it as we speak
That was a reply to the vfx graph comment, right?
dots animation. i'm not aware of people actively working on a dots-specific vfx graph
but i get the impression there are bigger fish to fry with graphics before that
Got it. Thought you were replying to me at first. My "hopefully less ugly" comment was about your "UglySlowUnscalableHacksForHybridInterop" name.
i'm a bit confused about the usage of statics. with domain reload disabled they always make problems. sometimes they even make problems when initialized. i never found out the real cause and just didn't bother with them. well, not totally true because i used [ClearOnReload] from the unity-domain-reload-helper plugin.
on the topic of hybrid/companion objects. it should be possible to add any kind of component/monobehaviour on entities. the rest, if unity doesn't want to deal with it, which is understandable to some point, remove all stuff having to do with companion linking and leave it to the community
i'd say it depends on your exact usage. if you set them anew on awake(), i would think you would get that called when you enter playmode irrespective of domain reload, and that would reset the state
I'm also guilty of avoiding statics because of not understanding what I could or couldn't do with domain reloads. I just never bothered to learn and it was easy to just not use statics.
Related to hybrid, it does feel weird how we can add monobehaviours to our subscene game objects and they will just silently do nothing if there is no baker defined. I know its wishful thinking, but it would be awesome if these monobehaviors were automagically added as component objects to the entity if there is no baker defined
Although, it would need some kind of big warning to prevent people from thinking they are converting to fast ECS components when they really aren't
why the push then to move system data out of systems? unity could easily provide us the ISystem struct, yet it was moved to SystemHandles which prevents us from this. accessing system data instead of going through an entity singleton is quite a bit faster and more direct
I thought you could get struct too now, no?
with UnmanagedWorld you can get ref struct
ah, wasn't aware. let me see
basically, the singleton pattern allows us to provide reasonable safety together with burstability, and it also opens the door, very theoretically, to swapping out a system in favor of another that writes the same data in a different way.
smth that has Resolve in it's name, don't quite remember exactly
we intentionally didn't make it super straightforward, because we do think it's a better idea in general to go through entity data. but let's be clear, that is not a hybrid issue; that's for when you're pedal to the metal bursting all the way down
ok, GetUnsafeSystemRef<T> /// This system reference is not guaranteed to be safe to use. If the system or world is destroyed then the reference /// becomes invalid and will likely lead to corrupted program state if used. /// /// Generally, instead of public member data, prefer using component data for system level data that needs to be /// shared between systems or externally to them. This defines a data protocol for the system which is separated /// from the system functionality. /// /// Private member data which is only used internally to the system is recommended.
thanks @celest solar at least that's still possible.
Maybe one day?
well hmm, that's a cool idea right there you have sir.
I'd think it will be as separate component, like physics shape
yep, that looks nice
Not sure I follow
So checkbox would be off by default to prevent stuff accidentally working in a slow path
one day we'll have animation package which won't be using Animator at all
oh yeah definitely. I just mean as a solution to monos without any baked version compatible with ECS
yeah, but in the meantime, and for components that don't have equivalent native dots functionality (like audiosources)
ima forward that image! the defaulting checkbox to off is the real kicker
I think its unrealistic to think this hybrid problem will go away once animation and cinemachine, and audio have dots native solutions. Although those are the biggest pain points.
yeah it'll be quite a while before we cover really everything
forwarded! we'll see what the baking people think when they wake up (i can't remember but i think they're either all or mostly in europe)
Awesome! I realize that the UX is only half of the problem so hopefully the baking people can figure out a way to make it work reliably under the hood.
indeed, that is the real trick. given various difficulties, i wouldn't be super surprised if it were pushed to after 1.0, but you never know
Now the question is, to which instance Animator would have to be on a GO?
Sorry, not sure I understand that question. What do you mean by instance?
It's not that I don't think it's a nice idea, I purely just think there's a lot of potential issues. Another, what would the Animator animate? A skinned mesh? Where does that live? Surely can't be on the GO you put in your SubScene as that will be converted to the entity comp version and Animator doesn't know how to talk to that. - Like, Managed Components which are not IComponentData, so e.g. Animator, Transform, MonoBehavoiurs etc. all need a reference to an actual instance. Where IComponentData also just happens to be that instance, that is not the case for UnityEngine.Objects 
Yeah that's a fair point. In the case of Animator, if it depends on transform, it means a transform syncing solution as well.
CompanionLink?
IIUC, the old companion link stuff was implemented by cloning the game object before converting the main one to an entity, and then the main game object is deleted. Not sure why it was done this way initially, but I would do it the opposite. If there are any monos on the game object with no baker defined and this check box is toggled on, then I would simply keep the authoring game object alive in the runtime world. No need to clone and fix references.
that's a such a cool concept, I don't see why it's not going into masses
But, I do concede the issue about a monobehavior using things like gameObject.transform and that possibly not working
I'll just add that even if that checkbox (or equivalent) doesn't make it, I hope we get a warning about no defined baker. Feels like a newbie trap right now
Yes! Agreed!
I think hybrid transform stuff will always be an unfortunately complicated thing to solve in a nice and automatic way. Maybe if any managed component checkbox is checked, a thing pops up near the transform asking how to sync the transform (either None, FollowEntity, or FollowGameObject)
Not sure I like it, but this is what I'm talking about (the new dropdown under the transform component)
It would only appear if you have a managed component being added
I dunno if I'm a tiny minority here but I use DOTS for these reasons:
- NetCode (that is somewhat capable, i.e. it has predicted physics)
- Easy queries & ECS code patterns (I don't need to follow references everywhere)
- Speed (when I need it, which I rarely do)
I use Unity because:
- I know it
- Asset Store
- Other people know it and can help me
So my use case for Unity DOTS really does not hinge on the performance aspect at all. I'm not making some massive game that requires DOTS scale speed as part of the core.
All I want from DOTS is a clean way to write well organized code that my sole indie brain can comprehend and easy interoperability with things I can get from the asset store like particle effects and animations. Consistency is not overrated when you are the only developer working on your project and you need to be able to remember how it all works.
The thing that really gets me about the DOTS development direction is that its balls to the wall looking for speed.
I do understand that there are a lot of people that want speed, but I'd argue that more people want a full game first.
And pretty much all games have animations, particle effects, audio, cameras and GUI, all of which doesn't mesh with DOTS well at all right now.
I'd love for there to be DOTS solutions to these things right now but even if there were, many would be using older stuff cos they depend on the asset store.
So I just don't see a world where good GameObject interop is absent from DOTS, well, for the next 5 years at least.
I tried a GUI like this once but it gets a bit messy with all the possibly combinations of translation, rotation, scale
... something something new transform system will help, maybe?
I think maybe checkbox or something next to each thing would be better?
Currently I use a single component for each, i.e. FollowRotation, FollowTranslation
But I definitely think its a good spot to put it
I dunno, its hell tricky cos of hierarchy
I'm kind of in the same camp. I didn't start using ECS because I had a slow game. In fact, I'd argue that it is practically impossible to add ECS to a game in an effort to speed it up. In those cases I would use the other parts of DOTS (jobs, collections, burst etc.). I started using ECS near the start of my current game because I wanted "performance by default". In my case, I am making a game that that needs to simulate thousands of objects at the same time, so performance does matter. But my first priority is finishing the game, not making the game as fast as possible. Nice workflows and easy to maintain code is more important to me than burst-everywhere-all-the-time-no-matter-what. I realize that performance-by-default relies on that, but we, unfortunately, need some amount of hybrid to make a complete game right now.
How would you specify the sync direction? Sometimes you want to follow the entity, other times you want the entity to follow the game object.
For example, an entity might need to drive the position of the skinned mesh, but a bone on that skeleton might need to drive the position of an entity.
Hmm that's a good point, I don't currently have animations driving the position of entities.
Yeah actually in my example, things would be very complicated. In order for the animator to write positions out to bones, they need to be game objects. That means the entire hierarchy of game objects would be needed at runtime.
What about this instead. Every UnityEngine.Component on the game object (including Transform) would have a new check box. This would be used to tell the baking system to add that component as a managed component to the companion entity. By default, all of these checkboxes would be off by default. If any are toggled on, the companion game object will be created and managed for you, but only with the components that you specified with the checkboxes.
With this, a user can keep a Transform while still baking out transform-related ECS components. They could do this on the entire hierarchy of a skeletal mesh. Then they can add specific ECS components to entities like FollowGameObject or FollowEntity to add the transform syncing where they need it.
Btw, I solved this exact problem (entity moves game object with animator, animator moves bone that moves an entity) in my project already. But I'm using a tag system to find and link the game objects and entities I care about. What I'm proposing here is solving the latter.
you can't have any monobehaviour without a transform, i would like to point out
Err, true. So I guess that would always be on the companion object. So if you clicked a checkbox on any other component, the checkbox for the Transform would be auto-checked and greyed out
That sounds pretty perfect to me.
it's possible that this is actually very similar to iconvertgameobjecttoentity and it's impossible to get it to be fast and incremental and reliable and so this idea is bad for the same reason that that was bad
Yeah it does seem like a similar problem
The alternative is that people are just rolling their own anyway
Or similar to the old ConvertAndInjectGameObject option
Somewhat related, but I think it would be cool to see the output of baking, broken down by component in the inspector. Previously, this didn't make sense because mono -> ICD wasn't one-to-many. You could have multiple monobehaviours all contributing to a single ICD. But the new Baker is always one-to-many. So I'm imagining that each game object Component has an area that shows the ICD types being added to the entity by baking. If there are none, you get a warning. This is also where the checkbox would be to add the mono as a managed component (which would then show in the list of types being added to the entity).
I'll make another mock up of this idea later today.
I'm essentially taking about making this Entity Baking Preview be broken down per game object Component. I feel like that would make it much more useful and would shed some light on the how the game object is being baked.
FYI, I created a thread with a new mockup here: https://forum.unity.com/threads/proposal-for-hybrid-interoperability.1345562/
Great write up!
Thanks! I may have gone a bit overboard with the photoshop mockup haha
I think when official working on this feature, needs to make it to game production level by default. You can make it like companion solution but better that internally u still instantiate game object and auto get all the required managed component ticked by user at baker and it supports game object pooling by default. On top of tat, it needs to support content delivery i.e. addressables.
But this comes out another question that in future will have dots addressables for content delivery of entity and subscene that becomes maintenance issue that need to maintain both addressables and dots addressables setup. It seems like needs to have unify authoring experience for addressables and dots addressables that only need to setup once. If not I afraid it will become yet another URP/HDRP/Built-In RP disaster.