This is what I’m actually planning to use to my advantage the fact that objects could literally only be on the client and not be made on the server. And this could also allow us to use this way along with streaming enabled.
Also I noticed that quote didn’t show up here you can read it better here if you haven’t already
The way CS works is that models are only streamed in on the client. When the game initially starts, they don’t exist on the server at all - only anchor points which indicate where the models should be streamed too. Based on proximity to anchor points, the models are streamed in.
That is why, in the Example Place, the workspace looks like:
but when players join and run around, they start to see houses appear (the distance ranges are set to make the streaming very obvious, versus how a real game would tailor the distances to be more subtle)
Looping back to your question, there ends up never being cases where the server is doing something with a part that the client can’t see (unless it’s a moving part, which is a slightly different case). However, if that was important, it wouldn’t be hard to accomplish this with minimal networking. For example, if I wanted to change the color of a house on the server and have that replicate to all players (I’d envision something based on attributes of anchor points and slight modification of the signal methods to also include the anchor point - that way models could be updated based on anchor point characteristics and keep things in sync with the server).
Touching quickly on how streaming sets the parent to nil - thanks for that, I wasn’t sure how it literally got handled so that’s great. To address it quickly since you are making something similar, that approach would not work with something like CS - models should be destroyed. This is because models are cloned and streamed in and then destroyed when streamed out. Each time it streams in, it’s a new model. There’s some accidental pros to this - for example, if someone used a btools exploit to destroy a segment of a wall, walked away causing it to cull back, and then walked back within culling range, then a new wall would be generated, since it’s cloned each time in. Setting to nil would cause lots of lingering in memory, since StreamingEnabled essentially streams ‘the’ model in/out, whereas CS does not. Neither is right or wrong, it’s just a difference in approach and there’s pros/limitations to both.
very very well done I like it even more your system. now here’s another new question if your system destroys objects and clones then back in what happens when its doing this to around 50 objects at a time or its doing many of them at a time wouldn’t that be really bad and cause strain on the client because you are making 50 objects have to be cloned and then rendered back in? setting something to nil would allow for faster loading I believe and less issues of having to clone many objects in if you are dealing with games with many many objects secondly, then again by setting it to nil the instance is still in the game leading to memory usage still, its just not rendered in. but ya I understand I guess there’s just trade offs at points if you do it one way compared to another way. Also like the quote
said here. wouldn’t yours be disconnecting those object signals leading to destroy events going off child removed events going of and even descendant removing events going off if people have them connected plus variables having those instances would then be nil as the instance no longer exists, just from destroying the instance. This also means we can’t actually store data on the object itself that changes over time like attributes unless we put it in a parent folder or unless your system remembers to add it back if not we then have to make another one that does it, when the new object gets added that seems like more of a hassle and possible performance issues just by doing that if many objects have information on them.
Great question. When I’ve set up games using CS, I’ve opted to take small things (like flowers, ivy, small rocks) in a close area and treat them as one entity. Breaking down those models to their functional level, which is decor, can point you in the direction of simply treating them as one single object, especially if they are close together (this is basically the idea for range folders, just within a single model). This way, when a player enters the range where the developer once these entities to be spawned in and visible, only one object is culled in/out as opposed to how ever many smaller models might collectively compose the decor (e.g., 50). At heart, you can avoid this dilemma through smart set-up.
This may be true, but load times are a micro-optimization comparisons are a micro-optimization. Since memory usage is remaining the same, its a moot point to really compare which loads in faster, especially because good culling set-up either happens without the player even noticing (i.e., cull things in within a 250 radius around the character, but tailor atmosphere + lighting and employ max zoom restrictions so the player maintains the illusion that the map is always spawned in). Alternatively, if culling is meant to be seen and contributes to a game’s aesthetic, then load times still don’t really matter - the player’s experience isn’t really affected if something could spawn in 0.1 seconds earlier or later (arbitrary number)
Correct, that definitely happens. All objects being culled in/out of the map are parented to a folder called CulledObjects
. Importantly, that allows for some selective listening for any Child/Descendant Added/Removed events (CDAR events, for short) (I don’t think it’s fantastic practice to connect CDAR events to the workspace as a whole, because it’s going to be firing very frequently, regardless of CS). Keeping everything being culled in/out in a single folder allows you to set up events looking for CDAR events and exclude that folder by looking running :IsDescendantOf
or only running CDAR events on other folders/models that aren’t affected by CS object streaming.
It is true that variables set to something that is culled in/out will be nil if that object is culled out. However, that would also be true in some circumstances with StreamingEnabled if that instance has not been initially streamed in for the client. Regardless, work with any kind of streaming necessitates that the code needs to be flexible in case the object does or does not exist (whether physically or actually in the workspace) when code runs.
Personally, I like to make most instances that touch my code not stream in/out at all, to avoid weird edge cases. CS helps me do that (and new ModelStreamingBehavior
properties for models help with that too), and I think that’s especially important in cases where you want to update the state of the object itself.
kk welp it was nice chatting with you and thanks for the ideas and chat, ill be working on my system now and ill be testing the 2 ways, yours and my own with the nil way I wanna see which would be the best for a game that has thousands of things needing to be streamed in and out. what makes a game. trial and error !
I’m back guess im not gonna be working on that system lol. just got fired from a company that stole all my work without paying me for it claiming they did hahahhaa. but other then that, I was able to make a small version of the system and here are the results, that system you made I made a version that sets stuff to nil. so the difference is not really noticeable however one will cause more memory usage the nil one but is a lot faster loading in and out buildings. but destroying system you have is more performant wise when it comes to memory use however rendering its not as fast.