Author Topic: [Tutorial] TNAutoSync (Only for users who need this)  (Read 4293 times)

blueagardq15

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 23
    • View Profile
[Tutorial] TNAutoSync (Only for users who need this)
« on: July 30, 2015, 11:03:38 PM »
Hello, Are you having trouble with Autosync script? is it throwing errors?
Well recently I looked at a topic of the link : http://www.tasharen.com/forum/index.php?topic=12679.msg57597

Step 1: Open TNSutoSync Script

Step 2: Replace the Whole Script with these lines of code by ArenMook :)

Press Ctrl + A to Select All :)
---------------------------------------------------------------------------------------
  1. //---------------------------------------------
  2. //            Tasharen Network
  3. // Copyright © 2012-2015 Tasharen Entertainment
  4. //---------------------------------------------
  5.  
  6. using UnityEngine;
  7. using TNet;
  8. using System.Collections;
  9. using System.Reflection;
  10. using System.IO;
  11.  
  12. /// <summary>
  13. /// This script makes it really easy to sync some value across all connected clients.
  14. /// Keep in mind that this script should ideally only be used for rapid prototyping.
  15. /// It's still better to create custom to-the-point sync scripts as they will yield
  16. /// better performance.
  17. /// </summary>
  18.  
  19. [ExecuteInEditMode]
  20. public class TNAutoSync : TNBehaviour
  21. {
  22.     [System.Serializable]
  23.     public class SavedEntry
  24.     {
  25.         public Component target;
  26.         public string propertyName;
  27.     }
  28.  
  29.     /// <summary>
  30.     /// Serialized synchronized entries.
  31.     /// </summary>
  32.  
  33.     public System.Collections.Generic.List<SavedEntry> entries = new System.Collections.Generic.List<SavedEntry>();
  34.  
  35.     /// <summary>
  36.     /// Maximum possible number of updates per second. If the values don't change, nothing will be sent.
  37.     /// If to set it to zero, the value will only be synchronized when new players join.
  38.     /// </summary>
  39.  
  40.     public float updatesPerSecond = 10f;
  41.  
  42.     /// <summary>
  43.     /// Whether the result will be saved on the server or not. In most cases it should remain as 'true'.
  44.     /// In any case the values will be sent to newly joined players automatically.
  45.     /// </summary>
  46.  
  47.     public bool isSavedOnServer = true;
  48.  
  49.     /// <summary>
  50.     /// Whether only the object's owner can send sync messages. In most cases it should remain as 'true'.
  51.     /// </summary>
  52.  
  53.     public bool onlyOwnerCanSync = true;
  54.  
  55.     /// <summary>
  56.     /// Whether to send through UDP or TCP. If it's important, TCP will be used. If not, UDP.
  57.     /// If you have a lot of frequent updates, leave it as not important.
  58.     /// </summary>
  59.  
  60.     public bool isImportant = false;
  61.  
  62.     class ExtendedEntry : SavedEntry
  63.     {
  64.         public FieldInfo field;
  65.         public PropertyInfo property;
  66.         public object lastValue;
  67.     }
  68.  
  69.     class Par : IBinarySerializable
  70.     {
  71.         public object[] vals;
  72.  
  73.         public void Serialize(BinaryWriter writer)
  74.         {
  75.             if (vals != null)
  76.             {
  77.                 int len = vals.Length;
  78.                 writer.Write((byte)len);
  79.                 for (int i = 0; i < len; ++i) writer.WriteObject(vals[i]);
  80.             }
  81.             else writer.Write((byte)0);
  82.         }
  83.  
  84.         public void Deserialize(BinaryReader reader)
  85.         {
  86.             int len = reader.ReadByte();
  87.  
  88.             if (len != 0)
  89.             {
  90.                 if (vals == null || vals.Length != len) vals = new object[len];
  91.                 for (int i = 0; i < len; ++i) vals[i] = reader.ReadObject();
  92.             }
  93.             else vals = null;
  94.         }
  95.     }
  96.  
  97.     [System.NonSerialized]
  98.     List<ExtendedEntry> mList = new List<ExtendedEntry>();
  99.     [System.NonSerialized]
  100.     Par mCached = null;
  101.  
  102.     /// <summary>
  103.     /// Locate the property that we should be synchronizing.
  104.     /// </summary>
  105.  
  106.     void Awake()
  107.     {
  108. #if UNITY_EDITOR
  109.         if (!Application.isPlaying)
  110.         {
  111.             TNAutoSync[] tns = GetComponents<TNAutoSync>();
  112.  
  113.             if (tns.Length > 1 && tns[0] != this)
  114.             {
  115.                 Debug.LogError("Can't have more than one " + GetType() + " per game object", gameObject);
  116.                 DestroyImmediate(this);
  117.             }
  118.         }
  119.         else
  120. #endif
  121.         {
  122.             // Find all properties, converting the saved list into the usable list of reflected properties
  123.             for (int i = 0, imax = entries.Count; i < imax; ++i)
  124.             {
  125.                 SavedEntry ent = entries[i];
  126.  
  127.                 if (ent.target != null && !string.IsNullOrEmpty(ent.propertyName))
  128.                 {
  129.                     FieldInfo field = ent.target.GetType().GetField(ent.propertyName, BindingFlags.Instance | BindingFlags.Public);
  130.  
  131.                     if (field != null)
  132.                     {
  133.                         ExtendedEntry ext = new ExtendedEntry();
  134.                         ext.target = ent.target;
  135.                         ext.field = field;
  136.                         ext.lastValue = field.GetValue(ent.target);
  137.                         mList.Add(ext);
  138.                         continue;
  139.                     }
  140.                     else
  141.                     {
  142.                         PropertyInfo pro = ent.target.GetType().GetProperty(ent.propertyName, BindingFlags.Instance | BindingFlags.Public);
  143.  
  144.                         if (pro != null)
  145.                         {
  146.                             ExtendedEntry ext = new ExtendedEntry();
  147.                             ext.target = ent.target;
  148.                             ext.property = pro;
  149.                             ext.lastValue = pro.GetValue(ent.target, null);
  150.                             mList.Add(ext);
  151.                             continue;
  152.                         }
  153.                         else Debug.LogError("Unable to find property: '" + ent.propertyName + "' on " + ent.target.GetType());
  154.                     }
  155.                 }
  156.             }
  157.  
  158.             if (mList.size > 0f)
  159.             {
  160.                 if (updatesPerSecond > 0f)
  161.                     StartCoroutine(PeriodicSync());
  162.             }
  163.             else
  164.             {
  165.                 Debug.LogWarning("Nothing to sync", this);
  166.                 enabled = false;
  167.             }
  168.         }
  169.     }
  170.  
  171.     /// <summary>
  172.     /// Sync periodically.
  173.     /// </summary>
  174.  
  175.     IEnumerator PeriodicSync()
  176.     {
  177.         for (; ;)
  178.         {
  179.             if (TNManager.isInChannel && updatesPerSecond > 0f)
  180.             {
  181.                 if (mList.size != 0 && (!onlyOwnerCanSync || tno.isMine) && Cache()) Sync();
  182.                 yield return new WaitForSeconds(1f / updatesPerSecond);
  183.             }
  184.             else yield return new WaitForSeconds(0.1f);
  185.         }
  186.     }
  187.  
  188.     /// <summary>
  189.     /// If this values are not saved on the server, at least send them to the newly joined player.
  190.     /// </summary>
  191.  
  192.     void OnNetworkPlayerJoin(Player p)
  193.     {
  194.         if (mList.size != 0 && !isSavedOnServer && TNManager.isHosting)
  195.         {
  196.             if (Cache()) Sync();
  197.             else tno.Send(255, p, mCached);
  198.         }
  199.     }
  200.  
  201.     /// <summary>
  202.     /// Immediately cache all synchronized values and return whether something actually changed.
  203.     /// </summary>
  204.  
  205.     bool Cache()
  206.     {
  207.         bool initial = false;
  208.         bool changed = false;
  209.  
  210.         if (mCached == null)
  211.         {
  212.             initial = true;
  213.             mCached = new Par() { vals = new object[mList.size] };
  214.         }
  215.  
  216.         for (int i = 0; i < mList.size; ++i)
  217.         {
  218.             ExtendedEntry ext = mList[i];
  219.  
  220.             object val = (ext.field != null) ?
  221.                 val = ext.field.GetValue(ext.target) :
  222.                 val = ext.property.GetValue(ext.target, null);
  223.  
  224.             if (!val.Equals(ext.lastValue))
  225.                 changed = true;
  226.  
  227.             if (initial || changed)
  228.             {
  229.                 ext.lastValue = val;
  230.                 mCached.vals[i] = val;
  231.             }
  232.         }
  233.         return changed;
  234.     }
  235.  
  236.     /// <summary>
  237.     /// Immediately synchronize all data by sending current values to everyone else.
  238.     /// </summary>
  239.  
  240.     public void Sync()
  241.     {
  242.         if (TNManager.isInChannel && mList.size != 0)
  243.         {
  244.             if (isImportant) tno.Send(255, isSavedOnServer ? Target.OthersSaved : Target.Others, mCached);
  245.             else tno.SendQuickly(255, isSavedOnServer ? Target.OthersSaved : Target.Others, mCached);
  246.         }
  247.     }
  248.  
  249.     /// <summary>
  250.     /// The actual synchronization function function.
  251.     /// </summary>
  252.  
  253.     [RFC(255)]
  254.     void OnSync(Par par)
  255.     {
  256.         if (enabled)
  257.         {
  258.             int len = (par.vals != null) ? par.vals.Length : 0;
  259.  
  260.             if (mList.size == len)
  261.             {
  262.                 for (int i = 0; i < len; ++i)
  263.                 {
  264.                     ExtendedEntry ext = mList[i];
  265.                     ext.lastValue = par.vals[i];
  266.                     if (ext.field != null) ext.field.SetValue(ext.target, ext.lastValue);
  267.                     else ext.property.SetValue(ext.target, ext.lastValue, null);
  268.                 }
  269.             }
  270.             else Debug.LogError("Mismatched number of parameters sent via TNAutoSync!");
  271.         }
  272.     }
  273. }
  274. [code]
  275.  
  276.  
« Last Edit: July 31, 2015, 05:53:28 AM by blueagardq15 »

neeraj

  • Newbie
  • *
  • Thank You
  • -Given: 7
  • -Receive: 1
  • Posts: 38
    • View Profile
Re: [Tutorial] TNAutoSync (Only for users who need this)
« Reply #1 on: June 12, 2016, 03:58:06 AM »
I am using TNET 3.0, i am still getting an error for player Object. Should i use this or is there something i am doing wrong?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: [Tutorial] TNAutoSync (Only for users who need this)
« Reply #2 on: June 12, 2016, 04:02:07 AM »
You will need to elaborate about the errors at least.

I don't advise using the AutoSync script beyond the learning stage for the most part. It's better to do synchronization via custom RFCs as you can control exactly when and how they are sent.

neeraj

  • Newbie
  • *
  • Thank You
  • -Given: 7
  • -Receive: 1
  • Posts: 38
    • View Profile
Re: [Tutorial] TNAutoSync (Only for users who need this)
« Reply #3 on: June 12, 2016, 04:46:29 AM »
Hello ArenMook, Sorry for not explaining it properly earlier.

I am using AutoSync just for the initial setup, i will change it after doing the basic game loop.
Well i am trying to Sync Player rotation, for some reason the error has stopped but the player rotation does not sync.

The Transform component that i want to sync is the child of TNetBehaviour which has the auto sync script on it.

I have attached a screenshot.

Thank you! :)
« Last Edit: June 12, 2016, 04:54:28 AM by neeraj »

neeraj

  • Newbie
  • *
  • Thank You
  • -Given: 7
  • -Receive: 1
  • Posts: 38
    • View Profile
Re: [Tutorial] TNAutoSync (Only for users who need this)
« Reply #4 on: June 12, 2016, 07:40:26 AM »
I am using a RFC now, its working properly but for some reason AutoSync does not work.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: [Tutorial] TNAutoSync (Only for users who need this)
« Reply #5 on: June 12, 2016, 09:41:19 AM »
TNAutoSync needs to be attached to the same game object as your TNObject script, which in turn should be on the root object. I don't even see a TNObject in your screenshot.

neeraj

  • Newbie
  • *
  • Thank You
  • -Given: 7
  • -Receive: 1
  • Posts: 38
    • View Profile
Re: [Tutorial] TNAutoSync (Only for users who need this)
« Reply #6 on: June 12, 2016, 10:02:16 AM »
Oh ok i wanted the child to sync..TNobject was in the parent. Ok anyways its working with RFC now. Thanks.