Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Falagard

Pages: [1]
1
Hi ArenMook,

Out of curiosity, does the new version of TNet support asynchronous loading of resources?

For example, instead of using Resources.Load, use Resources.LoadAsync?

If not, I may have to modify the source to support it.

With the existing code I have, it would involve making TNManager.OnCreateObject start a coroutine to execute its functionality, and then also make the onLoadGameObject delegate in TNManager return an IEnumerator so it can be called as a coroutine.

*Edit*

Yikes, it's worse than that, TNManager.objectOwnerID is being used as a sort of global loading variable to the owner id of the object currently being created and referenced from TNObject.Awake to set the object's owner, which assumes that Create is being called synchronously. I'll need to investigate more.

Couldn't I just make objectOwnerID have a setter, and then from the CreateGameObject function set the owner ID after it is created?

*End Edit*

I'd also have to make a delegate for OnLoadLevelCoroutine so I could assign my own level loading code.

And then I'd have to be change the code to load from asset bundles asynchronously for both level load and asset loading. But I'm guessing things have changed in your latest version since you mention UnityTools LoadBinary, LoadResource, etc. which I don't have in my version of TNet.

When is the latest version coming out?

Thanks!


2
Quote
Yes, I understood that. That's exactly what DataNode was designed for. If you watch that vid I linked, I add a new playable vehicle to the game without patching the game itself. The exported file is what you want it to be -- be it an entire model with all the necessary assets or the entire scene.

I've watched the video, it looked very good, but as I've explained it is unfortunately not what I need.

Quote
That sounds like it will get hairy quickly... bundles referencing other bundles? What happens when you update bundle A forgetting about all the other bundles that depend on it? Better design is to have self-contained modules that have everything they need inside them, and when loading check to see if the asset within has already been loaded from somewhere else, and if so -- simply skip loading it and reuse the existing one (which is what DataNode serialization does).

The basic idea is that you rebuild all your asset bundles any time you want to deploy changes. The asset bundle build system only rebuilds bundles that have changed, and keeps track of dependencies. You re-upload your asset bundles to the server. There is no "forgetting" bundles that depend on other bundles, as they rebuild themselves as necessary and keep track of versions. This is all built into Unity's new Asset Bundle system.

In my system (Unity's asset bundle system actually), the scene I'm loading only ever has serialized data with references to assets, not the assets embedded themselves. Each scene is in an asset bundle itself that only contains the scene file and no additional assets. To reiterate, there's an asset bundle per scene that only includes the scene. It should be the size of the scene file itself and nothing else, but it also contains metadata that indicates what other asset bundles it depends on.

When I request to load a scene, the asset bundle manager checks locally to see if it has already downloaded the scene's asset bundle. If not, it fetches it from the server. The scene asset bundle has a list of dependent asset bundles based on which assets were used in the scene. It then downloads those asset bundles as well if they don't already exist locally.

After all dependent asset bundles have been downloaded, it loads the scene.

This means the scene file itself doesn't have meshes, textures, etc. in it.

Now, if I was going to go the route of using my own asset loading system, I would do what I've done in the past for a C++ game I wrote, which is a similar two step process. The custom scene file would only have references, it would be downloaded, then each reference would be checked to see if it exists locally and if not, it would be downloaded.

I definitely would not embed assets in the custom scene file itself.

Long story short, Unity already has the system I want and I'm going to use it. It might bite me in the ass, we'll see.

Quote
The objects list isn't needed, and is only there as a legacy functionality. Just use the resource paths as if you were loading stuff via Resources.Load. TNet is designed in such a way that you can even place external assets (think My Documents/Your Game/Prefabs or something similar) and TNet will load them the same as if they were a part of the Resources folder. This includes textures (.png), text assets (.txt), binary assets (.bytes) and of course DataNode exports.

I personally can't load data using Resources.Load and need to continue using the Objects list or something similar. I could perhaps modify TNet to support loading from asset bundles directly though via an asset reference. Though in the meantime I hope you don't remove the legacy functionality.

3
It's not that simple.

The whole purpose of Asset Bundles is to update game content without patching the game. I could simply patch the game frequently to add new assets to the Resources folder, or embedded in the game data, but I'm trying to avoid that so I can potentially target non-patchable platforms like mobile. My whole architecture is based on the ability to have game logic in assets using FSMs/Behavior Trees, so I can include them in Asset Bundles and update actual game logic without patching the game executable.

I wouldn't want to embed binary assets, such as Meshes, Textures, Sounds, Particle Systems, etc. in an external scene format like NodeData or any other system, I'd prefer to reference them using prefabs or paths to the resource folder, like you mentioned, but I can't update the resources folder without patching the game.

You are correct that there is a problem with embedding shaders, but it's on Unity's list of things to fix as per this thread:

http://forum.unity3d.com/threads/loading-assets-from-assetbundles-makes-assets-appear-pink-in-editor.326541/

Apparently the problem is that shaders get precompiled per platform, and it is loading the wrong shader in the editor. I think this problem will go away soon due to shaders no longer being precompiled and instead the shader source will be included and compiled dynamically on each platform.

As far as assets referencing assets in other bundles, my understanding is that as long as each asset belongs to an asset bundle, a reference and dependency is used instead. For example, a texture in bundle A is used in a material on a mesh in bundle B, the second bundle will not embed the texture but instead have a reference to the texture in bundle a and there is then a dependency to bundle A added to bundle B, such that when bundle B is downloaded it also downloads bundle A. The system should work like this, and if it doesn't then it's a bug and will eventually get fixed, hopefully long before I launch my game.

So, can we leave that alone for now and answer my questions about how to work within the constraints of my game architecture?

Can I dynamically add and remove prefabs from the TNManager.objects list for each channel I join? So, before joining a channel, I populate the objects list with one that is specific to the scene that will be loaded?

I think the answer is yes, with caveats that if the object list changes that any TNManager.Create'd objects already in the channel will have problems, so I'll avoid that.

I also believe I'll be able to integrate the AssetBundleManager.LoadLevelAsync call to replace the Application.LoadLevelAsync call within TNManager.

Thanks, and hopefully I don't sound too confrontational. I really like TNet's design, I bought it quite a while back and have been basing my networking system on it from a design perspective, so now I just have to go in and start implementing it.

To be clear, I'm making a persistent multiplayer world, and TNet's channels, saved RFCs, etc. are all very elegant for handling a non authoritative multiple scene based world. Most of my logic executes on the client, and the idea of having a semi-authoritative host is perfect for what I need. Much better than other networking systems because of how simple yet powerful it is. I'm using my own system for persistence, using REST calls to a web server to query and store persistent data and also perform some of the more secure logic like applying experience points, leveling up characters, and giving out loot to the player, and am also using socket.io for sending messages back to the client from the web server and for chat.

I should also say that I've been lurking for a while, and some time back you mentioned the idea of having sub channels within a channel that would allow you to join multiple sub channels to segregate messages. I can't remember the exact terminology you used, but the idea is that as you walk around in a scene, you could be joining and leaving channels based on your location so you only receive messages from objects within your vicinity. Now, to me this sounds like a great idea but I'm not sure how you'd handle "host" migration because at the moment I think you base the migration on the assumption that every player has all data synchronized, so a client can take over as "host" at any time. Anyhow, the concept sounded great - any progress on this?

My game wouldn't be possible without TNet, so thanks!

4
Thanks for the answers ArenMook.

1. My scenes are created by hand in the editor, however I'll be using something similar to the AutoCreate script meaning that they will be instantiated dyamically. You didn't really answer my question here about TNObject IDs being unique across all channels, but I dug into the code and determined they're unique within a channel.

2. Ah thanks I wasn't aware of playerDataNode, I've taken a look at it now. Am I correct in assuming that every player in a channel has all other player's data synced as well? So for example, I can get some other player's data using playerID?

3. "Asset bundles are a very bad idea as they differ with each platform."

While I don't like all the decisions Unity made with Asset Bundles and I'll likely hit some major problems down the road with them, I don't think that the biggest problem is that they differ for each platform. To me that's pretty minor as I can simply build bundles for every platform and then based on the platform download the platform specific bundles. The biggest problem is integrating with assets such as TNet that assumes I'm not going to use Asset Bundles :-)

I may take a look at using DataNode, but I doubt I'll use it. I've investigated writing my own scene serializer, as well as using existing ones (Easy Save 2, etc.), and thrown out the idea due to complications. A simple example is saving any custom types of objects, maintaining references between instances, or even something as simple as NavMesh data that I use in my levels for pathfinding, or Lightmaps (which I don't use but it's another example of potential problems). I could change my workflow to use different libraries such as Aron Grenberg's AStar, or work around the problems but why should I if I can use the existing .scene format with Asset Bundles instead?

So, assuming I need to use Asset Bundles, does the solution I presented make sense?

5
Hi, sorry if these have been answered before, I tried searching and reading existing posts.

I'm building a game where the player moves from scene to scene as they move through the overall game world. Each scene will be obviously be a different channel.

The vast majority of objects in a scene won't be network aware, but some objects in a scene need to be networked because they have states such as a treasure chest which might be opened or closed. I'm planning on using Asset Bundles.

1. My assumption is that TNObject IDs should be unique across all channels, so the best way of handling my situation rather than assigning manual IDs is instantiating the network aware prefabs using something like the AutoCreate script so their IDs are automatically generated. That way in the editor I can place a treasure chest, add a script, and not worry about it. Does this sound like the right way to handle it?

2. Each player will obviously be a networked object and will also have state. For example, a player may have their color changed to red through a saved RFC, which will set an internal variable called "color" to "red". If the current player leaves a scene and joins another scene, what process should I use to keep that state?

My assumption is that saved RFCs are tied to a channel and that the player's TNObject should be non persistent, so it will be destroyed as I leave one channel and join the next. For this reason I should store state information (color = red) separately, join a different channel, then dynamically create a new object, and call a saved RPC on it to set its state again (or perhaps use parameters passed to the Create function - I need to investigate). Does this sound correct?

3. This might be a tricky question since not many people have a good grasp of Asset Bundles, but here's my plan.

I can't use the Resources folder to load objects, and I also can't add all prefabs to TNManager.objects list in the start scene.

I'm using Asset Bundles to be able to add new content without patching the game. Instead of adding all possible prefabs to the TNManager's objects list, I'm hoping to dynamically add and remove objects from this list before I attempt to create an object using TNManager.Create.

For asset bundles, I'll modify TNManager so instead of calling Application.LoadLevelAsync in LoadLevelCoroutine it calls a delegate to a different function I'll create which will download the necessary asset bundles then calls Application.LoadLevelAsync when they're ready.

Before the current player joins a scene, I'll call TNManager.LeaveChannel (if in a channel) to leave the current channel, and empty the TNManager.objects array, load a staging level which will which shows loading progress bars, etc. then call TNManager.JoinScene, updates progress bars downloading asset bundles and loading the level, etc. and finally the level is loaded via the modified TNManager LoadLevelCoroutine.

The scene will have its own list of prefabs that need to be dynamically instanced by the TNManager, so I'll create something like a TNSceneManager with its own objects list, that is only within that scene (destroyed when the scene is unloaded). The TNSceneManager Start it will set the TNManager's objects list to the same values as those on the TNSceneManager so any calls to TNManager.Create will subsequently use this prefab list.

Since the RequestCreate/ResponseCreate send the index into the TNSceneManager's object list, and they will always be sent within a channel, I don't think this will cause a problem.

I'll delay the creation of dynamic TNManager.Create'd objects until after the TNManager's objects are set properly for the current scene.

Am I crazy?

Thanks,
Clay







Pages: [1]