Author Topic: Tnet 3.0 send to other player [RFC]  (Read 3252 times)

Elmo loves cookies

  • Jr. Member
  • **
  • Thank You
  • -Given: 60
  • -Receive: 1
  • Posts: 62
    • View Profile
Tnet 3.0 send to other player [RFC]
« on: May 25, 2016, 08:23:31 AM »
How can I send [RFC] to specific player(who in my Trigger, or rayCast detected)?

cmifwdll

  • Global Moderator
  • Sr. Member
  • *****
  • Thank You
  • -Given: 0
  • -Receive: 149
  • Posts: 285
  • TNet Alchemist
    • View Profile
Re: Tnet 3.0 send to other player [RFC]
« Reply #1 on: May 25, 2016, 12:33:02 PM »
  1. void OnTriggerEnter(Collider collider)
  2. {
  3.     TNObject otherTNO = collider.GetComponent<TNObject>();
  4.     if (otherTNO == null)
  5.         return;
  6.     tno.Send(0, Target.All, otherTNO.ownerID);
  7. }
  8.  
  9. [RFC(0)]
  10. public void SomeRFC(int id)
  11. {
  12.     if (id == tno.ownerID)
  13.     {
  14.         // do stuff
  15.     }
  16. }
  17.  

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Tnet 3.0 send to other player [RFC]
« Reply #2 on: May 26, 2016, 12:48:05 PM »
I wouldn't use RFC(0), but instead would suggest just using the function's name instead. Also note that collider.GetComponent implies that TNObject is on the collider. Generally it's on the rigidbody instead, so it would be collider.GetComponentInChildren<TNObject>() instead.

cmifwdll

  • Global Moderator
  • Sr. Member
  • *****
  • Thank You
  • -Given: 0
  • -Receive: 149
  • Posts: 285
  • TNet Alchemist
    • View Profile
Re: Tnet 3.0 send to other player [RFC]
« Reply #3 on: May 26, 2016, 01:36:26 PM »
I wouldn't use RFC(0), but instead would suggest just using the function's name instead. Also note that collider.GetComponent implies that TNObject is on the collider. Generally it's on the rigidbody instead, so it would be collider.GetComponentInChildren<TNObject>() instead.

Wellll, if we're going to nitpick, I'd say using the function's name is less efficient than a byte identifier. For one, using the ID reduces packet size (doesn't have to write the string). Secondly, when the packet arrives and execution occurs, it's less expensive to look up the ID than the name:
  1. if (ent.id == funcID)
  2. generates the following IL:
  3. ldloca.s CachedFunc
  4. ldfld System.Byte CachedFunc::id
  5. ldarg.1
  6. bne.un -> 49
  7.  
Compared to looking up the name:
  1. if (ent.func.Name == funcName)
  2. generates the following IL:
  3. ldloca.s CachedFunc
  4. ldfld System.Reflection.MethodInfo TNet.CachedFunc::func
  5. callvirt System.String System.Reflection.MemberInfo::get_Name()
  6. ldarg.1
  7. call System.Boolean System.String::op_Equality(System.String, System.String)
  8. brfalse -> 52
  9.  

String comparisons are always going to be more expensive than simple integer comparisons.

Granted, using a string adds a lot to convenience and readability, but you can do something like so to achieve similar results:
  1. public class NetworkManager
  2. {
  3.     public const byte NETID_COLLISION_OTHER = 1;
  4. }
  5. tno.Send(NetworkManager.NETID_COLLISION_OTHER, Target.All, otherTNO.ownerID);
  6.  
  7. [RFC(NetworkManager.NETID_COLLISION_OTHER)]
  8. public void RFCCollisionOther(int id)
  9. {
  10.     if (id == tno.ownerID)
  11.     {
  12.         // do stuff
  13.     }
  14. }
  15.  

Additionally, why stop at checking just children? Use the following extension method instead:
  1. public static T GetComponentAll<T>(this GameObject go) where T : Component
  2. {
  3.         T component = go.GetComponent<T>();
  4.         if (component == null)
  5.         {
  6.                 component = go.GetComponentInParent<T>();
  7.                 if (component == null)
  8.                 {
  9.                         component = go.GetComponentInChildren<T>();
  10.                         if (component == null)
  11.                                 return null;
  12.                 }
  13.         }
  14.         return component;
  15. }
  16.  

Though, TNObject does call FindParent in its Start() function, so you only really need to check downwards. Also, you were probably more suggesting to not use 0 in tno.Send as SendRFC checks if byte ID is 0, but that's more of a design flaw in my opinion. Shouldn't it check if id is -1 instead?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Tnet 3.0 send to other player [RFC]
« Reply #4 on: May 27, 2016, 09:46:48 PM »
Using an ID is more efficient, yes -- but unless the function is called very frequently, it's better to keep it as a string so that it's easier to find later. Keep in mind that the function names/methodInfos are cached in a dictionary, so finding by name is still quite fast and efficient.

The reason you shouldn't search for TNObjects on children is because TNObject only caches functions below it (belonging to its children). If you have multiple TNObjects in a hierarchy, only the top-most (parent-most) TNObject is actually used for communication.