Author Topic: Manually Instantiating  (Read 2694 times)

Suvu

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 11
    • View Profile
Manually Instantiating
« on: June 13, 2013, 05:56:47 AM »
Hey all,

I've stumbled across an odd problem and can't seem to figure out whats going on here...

I need the ability to switch out part of my game logic at runtime into game modes (eg deathmatch, team deathmatch, capture the flag etc)

So here's a simplified version of the setup :


GameManager :
Contains core game logic and functionality that would be shared across all game modes.
Setup directly in the scene, with a TNO for network communication.
GameManager Script :
  1. public GameObject[] gameModePrefabs; //Drag gameMode prefabs here in the editor
  2. private GameObject mGameMode;
  3.  
  4. void Start()
  5. {
  6.    if(TNManager.isHosting)
  7.       tno.Send("StartGameMode", Target.AllSaved, 0); // 0 should really be the index/ID of the gameMode you want to instantiate
  8. }
  9.  
  10. [RFC]
  11. void StartGameMode(int modeID)
  12. {
  13.    mGameMode = Instantiate(gameModePrefabs[modeID]) as GameObject; // Yes, that is the unity Instantiate, but the prefab has a TNObject on it with the ID set manually
  14. }
  15.  

GameMode :
Contains logic and functionality specific to the gameMode.
NOT in the scene at startup, but instead stored as a prefab. Also has a TNObject with a manually set id (1000).
GameMode Script :
  1. void Start()
  2. {
  3.    if(TNManager.isHosting)
  4.       tno.Send("TestMessage", Target.AllSaved, "Message Received!");
  5. }
  6.  
  7. [RFC]
  8. void TestMessage(string msg)
  9. {
  10.    Debug.Log(msg);
  11. }
  12.  


What happens? :
Well, as the server, everything works as it should. The 'gameMode' is instantiated and the server get's the Debug.Log message.

Connecting as a client : the client gets the saved RFC to instantiate the 'gameMode' but, the saved RFC for the debug message doesn't trigger.
The strange thing is, the TNObjects on the runtime instantiated 'GameModes' do communicate (if you send a new message afterwards, it comes through as expected. it seems it's only the saved/buffered calls that don't get passed through for some reason...)

Any ideas as to whats happening here?

Cheers!

Update :
After doing a bit of poking around in the TNObject class, it looks like the client does in fact receive the "TestMessage" saved RFC... but before the TNObject has been registered.
It seems what happens is that the RFC call gets added to the delayed call list (mDelayed) until the corresponding TNObject exists/registers. But for some reason, these calls don't get excecuted even after the tno registers itself....
« Last Edit: June 13, 2013, 08:43:52 AM by Suvu »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Manually Instantiating
« Reply #1 on: June 13, 2013, 02:07:22 PM »
Instantiating a prefab with a manually-set ID is not the right way to go. You need to use TNManager to create objects.

Suvu

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 11
    • View Profile
Re: Manually Instantiating
« Reply #2 on: June 14, 2013, 01:36:29 AM »
Hey Aren!

Thanks for the reply, I got this working last night after having another look.

It's strange, there's the mDelayedCall list (In TNObject) to store a list of "calls that could not execute at the time of the call" as the comments say.
This list does get delayed calls added to it, but as far as I can tell, there's no code to execute these at any point. :/
So the delayed calls just sit in that list and no error/warning in Unity (which makes sense as it's not actually a problem... those calls should be executed in the future, when the correct TNO is available, it's just that this doesn't seem to happen)

So, my solution was to check the mDelayedCalls list, for any calls intended for this instance of TNObject (matching uid) at the end of the Register() Method.
If any calls are found, they are then executed using the appropriate FindAndExcecute() method, and then removed from mDelayedCalls

And that works just fine!

Anyways, hope this helps someone!

Cheers.

Owen
« Last Edit: June 14, 2013, 01:52:26 AM by Suvu »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Manually Instantiating
« Reply #3 on: June 14, 2013, 04:38:50 PM »
Hmm... Yeah I think the whole "delayed call" is a leftover feature from something I experimented with. I added it at one point but then I never encountered a use case for it. You found one, apparently. :)

Change the TNObject.Start() function to this:
  1.         void Start ()
  2.         {
  3.                 Register();
  4.                
  5.                 for (int i = 0; i < mDelayed.size; )
  6.                 {
  7.                         DelayedCall dc = mDelayed[i];
  8.  
  9.                         if (dc.objID == uid)
  10.                         {
  11.                                 if (!string.IsNullOrEmpty(dc.funcName)) Execute(dc.funcName, dc.parameters);
  12.                                 else Execute(dc.funcID, dc.parameters);
  13.                                 mDelayed.RemoveAt(i);
  14.                                 continue;
  15.                         }
  16.                         ++i;
  17.                 }
  18.         }
« Last Edit: June 14, 2013, 04:43:54 PM by ArenMook »