Однажды я экспериментировал с сетевым кодом в Unity3d.
Как вы, возможно, знаете, существуют различные системы, помогающие нам создавать сетевые приложения в Unity, с различными подходами и возможностями.
Однако, если вы более знакомы с обычным API сокетов и/или вам просто нужно портировать немного существующего кода, вам, вероятно, удобнее было бы разобрать простую отправку/получение данных.
Данная запись именно это и демонстрирует средствами .NET System.Net.Sockets.UdpClient:
using System; using System.Net.Sockets; using System.Net; namespace UdpTest { class Program { static void OnUdpData(IAsyncResult result) { // это то, что было передано в BeginReceive в качестве второго параметра: UdpClient socket = result.AsyncState as UdpClient; // указывает на того, кто отправил сообщение: IPEndPoint source = new IPEndPoint(0, 0); // получить сообщение и IP отправителя: byte[] message = socket.EndReceive(result, ref source); // здесь можно делать с `message` всё что хотите: Console.WriteLine("Got " + message.Length + " bytes from " + source); // ожидаем следующую операцию приема после завершения чтения: socket.BeginReceive(new AsyncCallback(OnUdpData), socket); } static void Main(string[] args) { UdpClient socket = new UdpClient(5394); // можно не указывать порт `new UdpClient ()` для автоматического выбора порта // ожидаем первую операцию получения: socket.BeginReceive(new AsyncCallback(OnUdpData), socket); // отправка данных (для простоты отправим обратно): IPEndPoint target = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5394); // отправить пару примеров сообщений: for (int num = 1; num <= 3; num++) { byte[] message = new byte[num]; socket.Send(message, message.Length, target); } Console.ReadKey(); } } }
Используя этот подход, я смог создать сетевую систему в Unity, которая будет работать как для P2P-соединений между игровыми экземплярами, так и для подключения к внешним серверам.
Примечания:
- Отправка в этом примере происходит синхронно, но практически ничего не теряет (запись в сокет не занимает много времени, особенно с учетом ограничений на размер датаграмм UDP).
- AsyncResult.AsyncState может быть любого типа. В этом примере я использую его, чтобы легко получить сокет, на который пришли данные. Для более сложных систем может быть хорошей идеей создать "контекстный" класс, который будет содержать сам сокет (UdpClient) и любые другие значения, которые могут вам понадобиться.
- Из-за текущих ограничений потоков в Unity у вас может не быть доступа к функциям, связанным с движком (unityengine.*). Чтобы обойти это, поместите полученные сообщения в какой-нибудь список, а затем обработайте их в методе обновления MonoBehaviour (Update).
Удачи!
Помощь с переводом от Terisback.