Author Topic: Dynamic/complex objects  (Read 9378 times)

danfoo

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 2
  • Posts: 93
    • View Profile
Dynamic/complex objects
« on: February 13, 2014, 10:15:58 AM »
Hi,

Perhaps I have missed something in the docs or in the forum, but I have not seen any clear description of the best way to handle situations where you want to generate new content without relying on instantiation but still want to sync states.

For example, we have a set of managers who need to communicate certain data to clients. We also set up avatars using UMA dynamically. Both these cases represent instances where we do not want to instantiate things.

Can I safely assume that it is perfectly fine to:
- Do level loading manually and bring new clients up to speed after the level has been loaded
- Have a scene contain objects with tnobjects already in place with set manually allocated IDs (for managers)
- build new objects at runtime via code and manually add tnobject components with manually allocated ids

Thanks in advance!

danfoo

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 2
  • Posts: 93
    • View Profile
Re: Dynamic/complex objects
« Reply #1 on: February 14, 2014, 04:16:45 AM »
Another related question:
As far as I understand, when a new player connects, it will automatically receive saved instructions to create objects previously created in the existing session? Is it also correct that it will receive earlier RFCs?
If so, will it only receive the last RFC?

I am trying to figure out how to tackle brining new players up to speed with complex objects. For simpler games networking is relatively easy, so just creating an object and syncing its position and orientation is trivial. However, if you have a lot of states it becomes more complex.

I would think that in these cases it is best to not rely on the built in buffering of Tnet at all but rather to act on the broadcast fired when the new player connects and then manually send the info needed to that client. Would that be correct?

Thanks in advance!

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Dynamic/complex objects
« Reply #2 on: February 14, 2014, 06:26:55 AM »
Simply attach a TNObject script to whatever you want to sync, and give it a unique ID. Dynamically instantiated prefabs can have their TNObject ID remain at 0, but static, non-instantiated objects need to have a valid non-zero ID.

Yes, all create calls and associated RFCs are saved in the order that the were received. If you delete a dynamically created objects, its existence will be removed, and all future players will not even know it existed.

All RFCs arrive in the order that they were received by the server, but if you called the same RFC multiple times, only the last call is actually saved. (this all assumes that you are using Target.AllSaved or Target.OthersSaved). All created objects are guaranteed to be there before their RFCs begin.

danfoo

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 2
  • Posts: 93
    • View Profile
Re: Dynamic/complex objects
« Reply #3 on: February 14, 2014, 08:18:50 AM »
Thanks!

Regarding static, non-instantiated objects mixed with created objects: How would you recommend that we manage execution order?

In our case we have several manager objects which need to do certain things before any instantiated objects are created for the new client or any RFCs fired. Ideally, I would like to have the managers send RFCs to their counterparts first and then have the dynamic create/RFC process fire. Is that possible?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Dynamic/complex objects
« Reply #4 on: February 15, 2014, 02:19:04 AM »
If your static objects sent their RFCs to the server first, then they will also arrive on the new players first. Object creation is supposed to occur before everything else, however. What is it you're trying to sync before the object creation happens?

danfoo

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 2
  • Posts: 93
    • View Profile
Re: Dynamic/complex objects
« Reply #5 on: February 15, 2014, 04:07:30 AM »
If your static objects sent their RFCs to the server first, then they will also arrive on the new players first. Object creation is supposed to occur before everything else, however. What is it you're trying to sync before the object creation happens?
The scenes are dynamically created, so the scene generation algorithm and various other things need to happen first before the scene is ready to be populated by other dynamic objects and the player experience can start.
So we need the new player joining process to be fully controlled. I am not even sure I am comfortable with relying on a theoretical order of RFCs. Ideally I would like to send a bunch of RFCs first to the new player, then when everything is set allow for dynamic creation and saved RFCs.

Edit: I should add that the scene is in constant flux, so relying on the first sent RFC will not work either. The host needs to send RFCs with instructions on how to match the current state of the scene to the new player, and that information needs to be compiled at that time.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Dynamic/complex objects
« Reply #6 on: February 16, 2014, 03:39:31 AM »
Logically, the first RFC should be what causes the level to get created -- all you need to generate it. Future RFCs may modify the level, but not overwrite the initial RFC (so it should be a different RFC).

For example if you create a rocky mountainous terrain with a summer time climate, then that's one RFC.

If you then decide to change the climate to a winter time one, that's a separate RFC.

danfoo

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 2
  • Posts: 93
    • View Profile
Re: Dynamic/complex objects
« Reply #7 on: February 20, 2014, 04:04:09 AM »
With that approach, the RFCs and the order of them would have to be 100% solid. If the order is off the game would go down in flames.
Also, modification calls would need to be divided, so I would still have to find a way to send targeted RFCs to the joining player. There is no way around that.
Is this possible by sending RFCs to the new player in a OnPlayerJoined (or whatever it is called) and avoiding saving those RFCs?

danfoo

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 2
  • Posts: 93
    • View Profile
Re: Dynamic/complex objects
« Reply #8 on: February 20, 2014, 08:41:29 AM »
Another issue with the suggested workflow is that the scene generation takes a bit of time and must run as a coroutine. This means that if the initial scene-building related RFCs are acted upon and then immediately followed by object generation RFCs, the world will not be ready for the new objects. So I would really like to control the startup. Ie. exchange some info with the new player first, generate the scene and then let everything else sync up.
So, basically it all ends back at: Is there any way to pause or control the flow of RFCs sent to a new player?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Dynamic/complex objects
« Reply #9 on: February 20, 2014, 01:13:05 PM »
TNManager.isActive = false; will effectively pause processing of RFCs, letting you do whatever you want.

So if you want, you can do it like so:

1. First RFC that says "create my scene" arrives -- you set TNManager.isActive to false, do your thing.
2. Once you're done, TNManager.isActive = true, continue processing.

danfoo

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 2
  • Posts: 93
    • View Profile
Re: Dynamic/complex objects
« Reply #10 on: February 20, 2014, 02:54:37 PM »
TNManager.isActive = false; will effectively pause processing of RFCs, letting you do whatever you want.

So if you want, you can do it like so:

1. First RFC that says "create my scene" arrives -- you set TNManager.isActive to false, do your thing.
2. Once you're done, TNManager.isActive = true, continue processing.

That works? I have read about TNManager.isActive (in a thread about controlling scene loading) but I assumed setting isActive to false would come with the risk of "missing" other buffered RFCs sent during the inactive time. So that is not the case? The RFCs from the host will remain "in queue" until the new player has the TNManager set active again and resumes listening to RFCs?

As a helpful comment I would recommend you to add some form of writeup on the structure of TNet when you have time. Having a slightly more technical explanation of how the various parts of TNet interact would definitely help new adopters like myself. :)


ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Dynamic/complex objects
« Reply #11 on: February 21, 2014, 11:22:29 AM »
Yeah setting isActive to false simply pauses message processing. They will be queued until you set isActive to true.

danfoo

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 2
  • Posts: 93
    • View Profile
Re: Dynamic/complex objects
« Reply #12 on: February 22, 2014, 04:29:41 AM »
Yeah setting isActive to false simply pauses message processing. They will be queued until you set isActive to true.
Ok, great!
Another related question: It looks as if we may have to split the early data into several RFCs (the info is relatively complex). This means pausing after the first RFC is not viable.
Would the following work:
- Host reacts to OnNetworkPlayerJoin and fires of a series of RFCs to the new player specifically.
- On receiving the last of these, isActive is set to false to create the new player's scene
- when done, isActive set to true to receive buffered RFCs and create additional objects

Now, this makes a couple of assumptions:
1) The order of RFCs can be guaranteed
2) OnNetworkPlayerJoin is fired before buffered RFCs are sent by the host
3) RFCs sent in the call chain triggered by OnNetworkPlayerJoin will be sent and processed before older, buffered RFCs

My guess is that the above will not fly - that buffered RFCs will arrive first and that the order is not 100% certain. If that is the case, could you recommend another approach to transmit a larger bunch of complex data before dealing with buffered RFCs?

Thanks in advance and thanks for your help this far!

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Dynamic/complex objects
« Reply #13 on: February 22, 2014, 11:40:59 AM »
I wouldn't do it like that. Reason being, nothing is preventing RFCs to arrive after the player's channel joined notification and before the host's messages arrive -- so you may be getting RFCs from objects that have not yet been created because you haven't executed your logic yet. Waiting on a host to do something is not a good idea. RFCs should already be there when the new player joins.

danfoo

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 2
  • Posts: 93
    • View Profile
Re: Dynamic/complex objects
« Reply #14 on: February 23, 2014, 09:17:32 AM »
I wouldn't do it like that. Reason being, nothing is preventing RFCs to arrive after the player's channel joined notification and before the host's messages arrive -- so you may be getting RFCs from objects that have not yet been created because you haven't executed your logic yet. Waiting on a host to do something is not a good idea. RFCs should already be there when the new player joins.

I am not sure we understand each other. The host is the player who has created and "owns" the scene. What needs to happen when a new player joins is that the (relatively complex) information about how to recreate the world is sent to the new player and executed before he is receiving buffered RFCs from objects in play.
Frankly, I do not quite understand how to control flows like these in TNet and I have not found any documentation that hints at it. All the examples I have seen are very simple and may apply well to simple "level based" games. There were a similar thread where someone wanted to transmit custom information about level destruction and he did not find a solution either as far as I could tell.

So, given the current state of TNet, how would you suggest we transmit information needed by the new player before buffered RFCs arrive? If that is not possible or recommended we are left with two options, neither of which are optimal:
- Block action on newly instantiated objects that rely on the world until it has been built
- Ditch Tnet and go with another solution.

Again, thank you for your help but I would certainly value some recommendations on how to proceed, especially given the very sparse documentation available.