void Awake()
    {
        // We abuse unity's matchmaking system to pass around connection info but no match is ever actually joined
        networkMatch = gameObject.AddComponent <NetworkMatch>();

        // Use reflection to get a reference to the private m_ClientId field of NetworkClient
        // We're going to need this later to set the port that client connects from.
        // Even though it's called clientId it is actually the transport level host id that the NetworkClient
        // uses to connect
        clientIDField = typeof(NetworkClient).GetField("m_ClientId", BindingFlags.NonPublic | BindingFlags.Instance);

        natHelper = GetComponent <NATHelper>();
        singleton = this;

        scriptCRCCheck            = false;
        NetworkCRC.scriptCRCCheck = false;

        System.Type type       = typeof(UnityEngine.Networking.NetworkManager);
        var         baseMethod = type.GetMethod("Awake", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

        if (baseMethod != null)
        {
            baseMethod.Invoke(this, null);
        }
    }
 public void Reconnect()
 {
     NATNetworkManager.connectedToFac  = rakPeer.GetConnectionState(facilitatorSystemAddress) == ConnectionState.IS_CONNECTED ? true : false;
     NATNetworkManager.connectedToFac2 = rakPeer2.GetConnectionState(facilitatorSystemAddress2) == ConnectionState.IS_CONNECTED ? true : false;
     NATNetworkManager.relayStatus     = NATNetworkManager.relayStatus == 2 ? 2 : ((NATNetworkManager.singleton.relayClient != null && NATNetworkManager.singleton.relayClient.isConnected) ? 1 : 0);
     if (NATNetworkManager.connectedToFac)
     {
         NATNetworkManager.singleton.MyConnectToRelay();
         if (!NATNetworkManager.connectedToFac2)
         {
             ConnectFac2();
         }
         StartCoroutine("WaitForRelay");
     }
     else
     {
         StopAllCoroutines();
         NATNetworkManager.RefreshInfo();
         StartCoroutine("WaitForNetwork");
     }
 }
    IEnumerator connectToNATFacilitator2()
    {
        // Start the RakNet interface listening on a random port
        // We never need more than 2 connections, one to the Facilitator and one to either the server or the latest incoming client
        // Each time a client connects on the server RakNet is shut down and restarted with two fresh connections
        StartupResult startResult = rakPeer2.Startup(2, new SocketDescriptor(), 1);

        if (startResult != StartupResult.RAKNET_STARTED)
        {
            Debug.Log("Failed to initialize network interface: " + startResult.ToString());
            yield break;
        }

        // Connect to the Facilitator
        ConnectionAttemptResult connectResult = rakPeer2.Connect(facilitatorIP, (ushort)facilitatorPort, null, 0);

        if (connectResult != ConnectionAttemptResult.CONNECTION_ATTEMPT_STARTED)
        {
            Debug.Log("Failed to initialize connection to NAT Facilitator: " + connectResult.ToString());
            yield break;
        }

        // Connecting, wait for response
        Packet packet;

        while ((packet = rakPeer2.Receive()) == null)
        {
            yield return(new WaitForEndOfFrame());
        }

        // Was the connection accepted?
        if (packet.data[0] != (byte)DefaultMessageIDTypes.ID_CONNECTION_REQUEST_ACCEPTED)
        {
            Debug.Log("Failed to connect to NAT Facilitator: " + ((DefaultMessageIDTypes)packet.data[0]));
            NATNetworkManager.RefreshInfo();
            yield break;
        }

        // Success, we are connected to the Facilitator
        guid2 = rakPeer2.GetMyGUID().g.ToString();
        Debug.Log("Connected: " + guid2);
        NATNetworkManager.connectedToFac2 = true;

        // We store this for later so that we can tell which incoming messages are coming from the facilitator
        facilitatorSystemAddress2 = packet.systemAddress;

        // Now that we have an external connection we can get the externalIP
        externalIP2 = rakPeer2.GetExternalID(packet.systemAddress).ToString(false);

        NATNetworkManager.RefreshInfo();

        if (firstTimeConnect2)
        {
            firstTimeConnect2 = false;

            // Attach RakNet punchthrough client
            // This is really what does all the heavy lifting
            natPunchthroughClient2 = new NatPunchthroughClient();
            rakPeer2.AttachPlugin(natPunchthroughClient2);
            // Punchthrough can't happen until RakNet is done finding router port stride
            // so we start it asap. If we didn't call this here RakNet would handle it
            // when we actually try and punch through.
            natPunchthroughClient2.FindRouterPortStride(facilitatorSystemAddress2);
        }
        else
        {
            // If this is not the first time connecting to the facilitor it means the server just received
            // a successful punchthrough and it reconnecting to prepare for more punching. We can start
            // listening immediately.
            StartCoroutine(waitForIncomingNATPunchThroughOnServer2(onHolePunched2));
        }

        isReady2 = true;
    }