Search Unity

Any Efficient Approach to STOP/START Systems ?

Discussion in 'Entity Component System' started by Opeth001, Sep 19, 2019.

  1. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    Hello Everyone,

    Can anyone point me to the best practice or any efficient approach to Create, Start & Stop systems without touching Systems Orders ?
    eg:
    a "ClientManagerSystem" which manages sent/received Packets between Client & Server. need to be executed only when the player is in Game.
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    You shouldn't have to stop and start systems, it's a indication of bad design.

    Systems simply work on data. If there is no data for then to work on then they won't run.

    Why would your client manager system have packets to work on when not in game.

    (the answer is just system.Enabled = false, but I'd heavily consider why you need to do this)
     
  3. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    Hi @tertle yep you are right.
    in this case the system will not run dependently on some Queries or CD but only when the player is in Game.
    so there is no reason for it to schedule Jobs and check the connection ... when the player is in main menu.

    do you have a good approach for this case ?
    Thanks!

    Code (CSharp):
    1. using System.Net;
    2. using UnityEngine;
    3. using Unity.Jobs;
    4. using Unity.Networking.Transport;
    5. using Unity.Collections;
    6. using Unity.Entities;
    7. using CWBR.ClientAndServer.Enums;
    8. using System.Threading.Tasks;
    9. using Unity.Networking.Transport.Utilities;
    10.  
    11. struct ClientUpdateJob : IJob
    12. {
    13.     public UdpNetworkDriver driver;
    14.     public NativeArray<NetworkConnection> connection;
    15.     public NativeArray<byte> disconectionRequested;
    16.     [ReadOnly]
    17.     public uint mySecretKey;
    18.    
    19.     public void Execute()
    20.     {
    21.         if (!connection[0].IsCreated)
    22.         {
    23.             if (disconectionRequested[0] != 1)
    24.                 Debug.LogError("Client: Oops Something Went Wrong in \"ClientUpdateJob\" !!!");
    25.             return;
    26.         }
    27.  
    28.         DataStreamReader stream;
    29.         NetworkEvent.Type cmd;
    30.  
    31.         while ((cmd = connection[0].PopEvent(driver, out stream)) != NetworkEvent.Type.Empty)
    32.         {
    33.             if (cmd == NetworkEvent.Type.Connect)
    34.             {
    35.                 Debug.Log("Client: Connected Server");
    36.                 // Identify my Self
    37.                 using (var writer = new DataStreamWriter(5, Allocator.Temp))
    38.                 {
    39.                     writer.Write(MessageBufferIndexes.IdentificationId);
    40.                     writer.Write(mySecretKey);
    41.                     // Send the Message
    42.                     connection[0].Send(driver, writer);
    43.                 }
    44.                 Debug.Log("Client: Identification Sent!");
    45.             }
    46.             else if (cmd == NetworkEvent.Type.Data)
    47.             {
    48.                 var readerCtx = default(DataStreamReader.Context);
    49.                 byte messageId = stream.ReadByte(ref readerCtx);
    50.  
    51.                 switch(messageId)
    52.                 {
    53.                     case MessageBufferIndexes.IdentificationSuccess:
    54.                         Debug.Log("Client: Server Accepted My identification");
    55.                         // Disconnect
    56.                         // And finally change the `done[0]` to `1`
    57.                         disconectionRequested[0] = 1;
    58.                         connection[0].Disconnect(driver);
    59.                         connection[0] = default(NetworkConnection);
    60.  
    61.                         break;
    62.                     case MessageBufferIndexes.IdentificationFailed:
    63.                         Debug.Log("Client: Server Rejected My identification");
    64.                         // Disconnect
    65.                         // And finally change the `done[0]` to `1`
    66.                         disconectionRequested[0] = 1;
    67.                         connection[0].Disconnect(driver);
    68.                         connection[0] = default(NetworkConnection);
    69.                         break;
    70.                     default:
    71.                         Debug.Log("Client: Oops Unknown Message");
    72.                         // Disconnect
    73.                         // And finally change the `done[0]` to `1`
    74.                         disconectionRequested[0] = 1;
    75.                         connection[0].Disconnect(driver);
    76.                         connection[0] = default(NetworkConnection);
    77.                         break;
    78.                 }
    79.                
    80.                
    81.             }
    82.             else if (cmd == NetworkEvent.Type.Disconnect)
    83.             {
    84.                 Debug.Log("Client: Got disconnected from server");
    85.                 connection[0] = default(NetworkConnection);
    86.             }
    87.         }
    88.     }
    89. }
    90. public class ClientManagerSystem : JobComponentSystem
    91. {
    92.     public UdpNetworkDriver m_Driver;
    93.     public NativeArray<NetworkConnection> m_Connection;
    94.     public NativeArray<byte> disconectionRequested;
    95.  
    96.     // this Key should be Passed from Nakama
    97.     public uint secretKey;
    98.  
    99.     private NetworkPipeline unreliablePipeline;
    100.     private NetworkPipeline reliablePipeline;
    101.  
    102.     string IP = "127.0.0.1";
    103.     ushort Port = 9000;
    104.  
    105.     private bool serverInit = false;
    106.  
    107.     protected override async void OnCreate()
    108.     {
    109.         await Task.Delay(10000);
    110.         Debug.Log("===========  Client Started!  ==============");
    111.        
    112.         //m_Driver = new UdpNetworkDriver(new SimulatorUtility.Parameters { MaxPacketSize = 200, MaxPacketCount = 30, PacketDelayMs = 25, PacketDropPercentage = 10 /*PacketDropInterval = 100*/}, new ReliableUtility.Parameters { WindowSize = 32 });
    113.  
    114.         m_Driver = new UdpNetworkDriver(new ReliableUtility.Parameters { WindowSize = 32 });
    115.         m_Connection = new NativeArray<NetworkConnection>(1, Allocator.Persistent);
    116.  
    117.         disconectionRequested = new NativeArray<byte>(1, Allocator.Persistent);
    118.         disconectionRequested[0] = 0;
    119.  
    120.         //unreliablePipeline = m_Driver.CreatePipeline(typeof(UnreliableSequencedPipelineStage), typeof(SimulatorPipelineStage));
    121.         unreliablePipeline = m_Driver.CreatePipeline(typeof(UnreliableSequencedPipelineStage));
    122.  
    123.         //reliablePipeline = m_Driver.CreatePipeline(typeof(ReliableSequencedPipelineStage), typeof(SimulatorPipelineStage));
    124.         reliablePipeline = m_Driver.CreatePipeline(typeof(ReliableSequencedPipelineStage));
    125.  
    126.  
    127.         if (NetworkEndPoint.TryParse(IP, Port,out var networkEndPoint))
    128.         {
    129.             m_Connection[0] = m_Driver.Connect(networkEndPoint);
    130.             if (m_Connection[0].IsCreated)
    131.             {
    132.                 Debug.Log("Client: Connection with Server Established!");
    133.                 serverInit = true;
    134.             }
    135.             else
    136.                 Debug.Log("Client: Connection with Server Cannot be Established!");
    137.         }
    138.          
    139.         // Test
    140.         secretKey = 10101;
    141.     }
    142.  
    143.     protected override void OnDestroy()
    144.     {
    145.         m_Driver.Dispose();
    146.         m_Connection.Dispose();
    147.         disconectionRequested.Dispose();
    148.     }
    149.  
    150.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    151.     {
    152.         if (serverInit == false)
    153.             return inputDeps;
    154.  
    155.         inputDeps = m_Driver.ScheduleUpdate(inputDeps) ;
    156.  
    157.         var clientUpdateJob = new ClientUpdateJob
    158.         {
    159.             connection = m_Connection,
    160.             disconectionRequested = disconectionRequested,
    161.             driver = m_Driver,
    162.             mySecretKey = secretKey
    163.         }.Schedule(inputDeps);
    164.  
    165.         return clientUpdateJob;
    166.     }
    167. }
    168.  
     
  4. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    So because of subscenes, I realized that loading non-subscene scenes additively is no longer necessary for me. So I built a framework for making entities react to non-subscene scene changes the same way GameObjects do. Paired with this, I have the ability to turn on or off ComponentSystemGroups based on what scene it is or some other global state. It decreases the complexity of queries with respect to global state and ends up removing a bunch of confusing boilerplate as things grow in complexity.
     
    Opeth001 and MostHated like this.