Тема: Пишемо онлайн гру на Unity з власним сервером на Java
Це не повний тутор і не повна статя, а тема, в котрій я буду хвалитись тим, що роблю, і жалітись, якщо щось не виходе.
Справа така, що я зараз пишу онлайн гру, але вже за гроші. Це не якась ммо, а turn-based пошагова стратегія (чи тактекія, не знаю, що тут краще примінити - стратегія, чи тактика).
В грі буде реєстрація з логіном, тому потрібна база даних, і все таке.
Пароль буде генеруватись на стороні серверу і відправлятись користувачу на мило, тому усіляке php йде котові під хвіст.
Поки що мені потрібно зробити лише реєстрацію і логін, і я почав з наймешного:
1. Створити найпростіший сервер, котрий би просто приймав підключення і дані від клієнтів
2. Створити клієнта, спроможного підключитись до серверу та відправити дані
Я зайшов на півкроку далі, і відправляю отримані від клієнта дані назад до клієнта.
В якості мережевої бібліотеки на стороні серверу використовую Netty.
Спершу нехай буде код серверу, бо він страшний.
Я розумію далеко не кожний рядок, тому що лише переписував з офіційного туторіалу намагаючись розібратись, але чим далі, тим зрозуміліше буде, як то все працює.
Озьдо туторіал
http://netty.io/wiki/user-guide-for-4.x.html
озьдо клас обробник
дані приходяться в метод channelRead, отримані дані виводяться в консоль, а потім відправляються клієнту
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.buffer.ByteBuf;
public class DiscardServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg){
ByteBuf msg1 = (ByteBuf)msg;
System.out.println(msg1.toString(io.netty.util.CharsetUtil.US_ASCII));
ctx.writeAndFlush(msg1);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause){
cause.printStackTrace();
ctx.close();
}
}
озьдо клас, де сервер збирається до купи
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class DiscardServer {
private int port;
public DiscardServer(int port)
{
this.port=port;
}
public void run() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try{
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>(){
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new DiscardServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
}
finally{
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
а озьдо туто воно все запускається
public class Main {
public static void main(String[] args) throws Exception
{
int port;
if(args.length>0){
port = Integer.parseInt(args[0]);
}
else{
port = 8050;
}
new DiscardServer(port).run();
System.out.println("end");
}
}
Як бачите, сервер слухаю 8050 порт.
А от скрипт на клієнті
using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System;
using System.Text;
public class TacticsNet : MonoBehaviour {
private TcpClient client;
void Awake()
{
client = new TcpClient();
}
void Start()
{
Connect();
}
void Connect()
{
client.Connect("localhost", 8050);
Debug.Log("Connected");
Send();
}
void Send()
{
byte[] data = Encoding.UTF8.GetBytes("hello server, glad to feel you <3");
try {
client.GetStream().Write(data, 0, data.Length);
}
catch(Exception ex)
{
Debug.LogError(ex.Message);
}
Debug.Log("Data has been sent");
Receive();
}
void Receive()
{
byte[] data = new byte[1024];
int dataLength = client.GetStream().Read(data, 0, data.Length);
string message = Encoding.UTF8.GetString(data, 0, dataLength);
Debug.Log(message);
Disconnect();
}
void Disconnect()
{
client.Close();
Debug.Log("Disconnected");
}
}
Підключаємось, відправляємо, приймаємо. Все в одному потоці, тому й так просто виглядає.
І от скрін роботи
зліва клієнт, справа сервер