Lumieru的知识库

  • 首页

  • 标签

  • 分类

  • 归档

  • 搜索

网络物理模拟一之网络物理部分的简介

发表于 2019-05-20 | 更新于 2019-06-22 | 分类于 Multiplayer

译者:陈敬凤(nunu) 审校:崔国军(飞扬971)

大家好,我是格伦·菲德勒,是一位来自洛杉矶的职业游戏开发者。

我作为一名职业游戏开发者已经有15年了。而在这其中的十年时光里,我都是专门做网络编程的。在这期间我大部分的业余时间一直致力于研究网络物理模拟方面的问题。在这个系列文章中我的目标是分享我已经知道的一切有关网络物理模拟方面的知识。

写这些文章是一个工作量很大的工作,而且我完全是在我的业余时间里面来做这些事情的。如果有了你们的支持,我可以找时间来继续写这个系列的文章。如果可以的话,请通过 patreon 支持我的工作。

网络物理部分的入门是相当困难的。你可能想知道你的物理模拟是否需要确定性以便可以进行网络传输和通信?你应该通过网络来发送物体的物理状态么?或者你应该通过网络来发送一些诸如碰撞时间或者物体相互作用力这些东西么?你到底是应该通过UDP还是TCP来传送数据?你应该使用客户端/服务器通信模型还是点对点的通信模型? 你是否需要一个专门的服务器?如何隐藏播放动作的时候的延迟?如何不让玩家作弊?

人们经常问我这些问题。大多数情况下这些问题的正确答案依赖于他们所选用的网络模型。你可能甚至不知道你正在使用或计划使用的网络模型是什么,但事实是你必须选择一个网络模型并且你选择的这个网络模型会使某些事情变得容易,并使得另外一些事情变得困难。

在这个系列文章中我们将使用三种不同的方式来构建一个网络物理模拟的例子,并通过这些例子来对不同的网络模型展开一个讨论。我把这些基本技术称为“同步策略”。他们是:《确定性的帧同步》、《快照插值》和《状态同步》。

带宽是网络物理部分的另外一个重要方面。我该怎么做才能对所有这些对象进行同步状态?因此,我们打算花一整篇文章来进行介绍一个带宽优化的案例,向你展示如何将快照插值技术的带宽从每秒18m减少到每秒256k。

在选择了合适的同步策略以及合理的优化完带宽以后,我们现在准备讨论客户机/服务器与点对点对等网络之间的优劣性了。除了讨论利弊以外,我还将分享在艰苦的发布使用客户机/服务器网络模型的游戏和点对点对等网络模型的游戏的过程中学到的那些经验和教训。这篇文章会有你在其他地方找不到的非常具体、务实的信息。

最后,我们讨论构建在基本同步策略上的不同网络模型,这些网络模型的细节各有不同。在这里。你会发现你的网络物理模拟可以有许多不同的选择:《确定性帧同步网络模型》、《分布式权威网络模型》和《带有客户端预测的服务器仲裁网络模型》。

所以系上安全带准备出发了。我们还有一大堆材料需要学习!

接下来的这篇文章是:《物理模拟》

为什么格伦·菲德勒在Patreon上寻求自助?

嘿,大家好,我是格伦·菲德勒,网站gafferongames.com的作者。在过去的10年,我给大家分享了许多游戏开发方面的文章:《如何解决你的时间戳》、《整合基础》、《UDP与TCP》、《每个程序员都需要了解游戏开发网络方面的知识》以及其他一些文章。我还分享了《物理编程技巧》、《网络游戏编程的基础知识》和我的个人项目虚拟围棋。我想继续新的系列文章《网络物理模拟》以及《构建一个游戏网络协议》,但是我需要你的帮助!托管代码和文章需要费用,写这些文章需要花费大量的时间去研究和写作。如果你喜欢gafferongames.com上面的文章,请向我展现出你对我的支持并鼓励我写更多的文章并开放更多的源代码!

【版权声明】

原文作者未做权利声明,视为共享知识产权进入公共领域,自动获得授权。

如果你觉得这篇文章有价值,请在 patreon 上支持原作者。

游戏网络开发五之每个游戏开发者都需要知道的游戏网络知识

发表于 2019-05-20 | 更新于 2019-06-22 | 分类于 Multiplayer

原文

原文出处

Introduction

Hi, I’m Glenn Fiedler and welcome to Networking for Game Programmers.

Have you ever wondered how multiplayer games work?

From the outside it seems magical: two or more players sharing a consistent experience across the network like they actually exist together in the same virtual world.

But as programmers we know the truth of what is actually going on underneath is quite different from what you see. It turns out it’s all an illusion. A massive sleight-of-hand. What you perceive as a shared reality is only an approximation unique to your own point of view and place in time.

Peer-to-Peer Lockstep

In the beginning games were networked peer-to-peer, with each each computer exchanging information with each other in a fully connected mesh topology. You can still see this model alive today in RTS games, and interestingly for some reason, perhaps because it was the first way - it’s still how most people think that game networking works.

The basic idea is to abstract the game into a series of turns and a set of command messages when processed at the beginning of each turn direct the evolution of the game state. For example: move unit, attack unit, construct building. All that is needed to network this is to run exactly the same set of commands and turns on each player’s machine starting from a common initial state.

Of course this is an overly simplistic explanation and glosses over many subtle points, but it gets across the basic idea of how networking for RTS games work. You can read more about this networking model here: 1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond.

It seems so simple and elegant, but unfortunately there are several limitations.

First, it’s exceptionally difficult to ensure that a game is completely deterministic; that each turn plays out identically on each machine. For example, one unit could take slightly a different path on two machines, arriving sooner to a battle and saving the day on one machine, while arriving later on the other and erm. not saving the day. Like a butterfly flapping it’s wings and causing a hurricane on the other side of the world, one tiny difference results in complete desynchronization over time.

The next limitation is that in order to ensure that the game plays out identically on all machines it is necessary to wait until all player’s commands for that turn are received before simulating that turn. This means that each player in the game has latency equal to the most lagged player. RTS games typically hide this by providing audio feedback immediately and/or playing cosmetic animation, but ultimately any truly game affecting action may occur only after this delay has passed.

The final limitation occurs because of the way the game synchronizes by sending just the command messages which change the state. In order for this to work it is necessary for all players to start from the same initial state. Typically this means that each player must join up in a lobby before commencing play, although it is technically possible to support late join, this is not common due to the difficulty of capturing and transmitting a completely deterministic starting point in the middle of a live game.

Despite these limitations this model naturally suits RTS games and it still lives on today in games like “Command and Conquer”, “Age of Empires” and “Starcraft”. The reason being that in RTS games the game state consists of many thousands of units and is simply too large to exchange between players. These games have no choice but to exchange the commands which drive the evolution of the game state.

But for other genres, the state of the art has moved on. So that’s it for the deterministic peer-to-peer lockstep networking model. Now lets look at the evolution of action games starting with Doom, Quake and Unreal.

阅读全文 »

游戏网络开发四之基于UDP的可靠性与排序和避免拥堵

发表于 2019-05-20 | 更新于 2019-06-22 | 分类于 Multiplayer

原文

原文出处

Introduction

Hi, I’m Glenn Fiedler and welcome to Networking for Game Programmers.

In the previous article, we added our own concept of virtual connection on top of UDP. In this article we’re going to add reliability, ordering and congestion avoidance to our virtual UDP connection.

The Problem with TCP

Those of you familiar with TCP know that it already has its own concept of connection, reliability-ordering and congestion avoidance, so why are we rewriting our own mini version of TCP on top of UDP?

The issue is that multiplayer action games rely on a steady stream of packets sent at rates of 10 to 30 packets per second, and for the most part, the data contained is these packets is so time sensitive that only the most recent data is useful. This includes data such as player inputs, the position, orientation and velocity of each player character, and the state of physics objects in the world.

The problem with TCP is that it abstracts data delivery as a reliable ordered stream. Because of this, if a packet is lost, TCP has to stop and wait for that packet to be resent. This interrupts the steady stream of packets because more recent packets must wait in a queue until the resent packet arrives, so packets are received in the same order they were sent.

What we need is a different type of reliability. Instead of having all data treated as a reliable ordered stream, we want to send packets at a steady rate and get notified when packets are received by the other computer. This allows time sensitive data to get through without waiting for resent packets, while letting us make our own decision about how to handle packet loss at the application level.

It is not possible to implement a reliability system with these properties using TCP, so we have no choice but to roll our own reliability on top of UDP.

Sequence Numbers

The goal of our reliability system is simple: we want to know which packets arrive at the other side of the connection.

First we need a way to identify packets.

What if we had added the concept of a “packet id”? Let’s make it an integer value. We could start this at zero then with each packet we send, increase the number by one. The first packet we send would be packet 0, and the 100th packet sent is packet 99.

This is actually quite a common technique. It’s even used in TCP! These packet ids are called sequence numbers. While we’re not going to implement reliability exactly as TCP does, it makes sense to use the same terminology, so we’ll call them sequence numbers from now on.

Since UDP does not guarantee the order of packets, the 100th packet received is not necessarily the 100th packet sent. It follows that we need to insert the sequence number somewhere in the packet, so that the computer at the other side of the connection knows which packet it is.

We already have a simple packet header for the virtual connection from the previous article, so we’ll just add the sequence number in the header like this:

1
2
3
[uint protocol id]  
[uint sequence]
(packet data…)

Now when the other computer receives a packet it knows its sequence number according to the computer that sent it.

阅读全文 »

游戏网络开发三之基于UDP的虚拟连接

发表于 2019-05-19 | 更新于 2019-06-22 | 分类于 Multiplayer

原文

原文出处

Introduction

Hi, I’m Glenn Fiedler and welcome to Networking for Game Programmers.

In the previous article we sent and received packets over UDP. Since UDP is connectionless, one UDP socket can be used to exchange packets with any number of different computers. In multiplayer games however, we usually only want to exchange packets between a small set of connected computers.

As the first step towards a general connection system, we’ll start with the simplest case possible: creating a virtual connection between two computers on top of UDP.

But first, we’re going to dig in a bit deeper about how the Internet really works!

The Internet NOT a series of tubes

In 2006, Senator Ted Stevens made internet history with his famous speech on the net neutrality act:

“The internet is not something that you just dump something on. It’s not a big truck. It’s a series of tubes”

When I first started using the Internet, I was just like Ted. Sitting in the computer lab in University of Sydney in 1995, I was “surfing the web” with this new thing called Netscape Navigator, and I had absolutely no idea what was going on.

You see, I thought each time you connected to a website there was some actual connection going on, like a telephone line. I wondered, how much does it cost each time I connect to a new website? 30 cents? A dollar? Was somebody from the university going to tap me on the shoulder and ask me to pay the long distance charges? :)

Of course, this all seems silly now.

There is no switchboard somewhere that directly connects you via a physical phone line to the other computer you want to talk to, let alone a series of pneumatic tubes like Sen. Stevens would have you believe.

No Direct Connections

Instead your data is sent over Internet Protocol (IP) via packets that hop from computer to computer.

A packet may pass through several computers before it reaches its destination. You cannot know the exact set of computers in advance, as it changes dynamically depending on how the network decides to route packets. You could even send two packets A and B to the same address, and they may take different routes.

On unix-like systems can inspect the route that packets take by calling “traceroute” and passing in a destination hostname or IP address.

On windows, replace “traceroute” with “tracert” to get it to work.

Try it with a few websites like this:

1
2
3
4
5
traceroute slashdot.org  
traceroute amazon.com
traceroute google.com
traceroute bbc.co.uk
traceroute news.com.au

Take a look and you should be able to convince yourself pretty quickly that there is no direct connection.

阅读全文 »

游戏网络开发二之数据的发送与接收

发表于 2019-05-19 | 更新于 2019-06-22 | 分类于 Multiplayer

原文

原文出处

Introduction

Hi, I’m Glenn Fiedler and welcome to Networking for Game Programmers.

In the previous article we discussed options for sending data between computers and decided to use UDP instead of TCP for time critical data.

In this article I am going to show you how to send and receive UDP packets.

BSD sockets

For most modern platforms you have some sort of basic socket layer available based on BSD sockets.

BSD sockets are manipulated using simple functions like “socket”, “bind”, “sendto” and “recvfrom”. You can of course work directly with these functions if you wish, but it becomes difficult to keep your code platform independent because each platform is slightly different.

So although I will first show you BSD socket example code to demonstrate basic socket usage, we won’t be using BSD sockets directly for long. Once we’ve covered all basic socket functionality we’ll abstract everything away into a set of classes, making it easy to you to write platform independent socket code.

Platform specifics

First let’s setup a define so we can detect what our current platform is and handle the slight differences in sockets from one platform to another:

1
2
3
4
5
6
7
8
9
10
11
12
13
// platform detection  

#define PLATFORM_WINDOWS 1
#define PLATFORM_MAC 2
#define PLATFORM_UNIX 3

#if defined(_WIN32)
#define PLATFORM PLATFORM_WINDOWS
#elif defined(APPLE)
#define PLATFORM PLATFORM_MAC
#else
#define PLATFORM PLATFORM_UNIX
#endif

Now let’s include the appropriate headers for sockets. Since the header files are platform specific, we’ll use the platform #define to include different sets of files depending on the platform:

1
2
3
4
5
6
7
8
9
10
11
12
#if PLATFORM == PLATFORM_WINDOWS  

#include <winsock2.h>

#elif PLATFORM == PLATFORM_MAC ||
PLATFORM == PLATFORM_UNIX

#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>

#endif

Sockets are built in to the standard system libraries on unix-based platforms so we don’t have to link to any additonal libraries. However, on Windows we need to link to the winsock library to get socket functionality.

Here is a simple trick to do this without having to change your project or makefile:

1
2
3
#if PLATFORM == PLATFORM_WINDOWS  
#pragma comment( lib, "wsock32.lib" )
#endif

I like this trick because I’m super lazy. You can always link from your project or makefile if you wish.

阅读全文 »

游戏网络开发一之TCPvsUDP

发表于 2019-05-18 | 更新于 2019-06-22 | 分类于 Multiplayer

原文

原文出处

Introduction

Hi, I’m Glenn Fiedler and welcome to Networking for Game Programmers.

In this article we start with the most basic aspect of network programming: sending and receiving data over the network. This is perhaps the simplest and most basic part of what network programmers do, but still it is quite intricate and non-obvious as to what the best course of action is.

You have most likely heard of sockets, and are probably aware that there are two main types: TCP and UDP. When writing a network game, we first need to choose what type of socket to use. Do we use TCP sockets, UDP sockets or a mixture of both? Take care because if you get this wrong it will have terrible effects on your multiplayer game!

The choice you make depends entirely on what sort of game you want to network. So from this point on and for the rest of this article series, I assume you want to network an action game. You know, games like Halo, Battlefield 1942, Quake, Unreal, CounterStrike and Team Fortress.

In light of the fact that we want to network an action game, we’ll take a very close look at the properties of each protocol, and dig a bit into how the internet actually works. Once we have all this information, the correct choice is clear.

TCP/IP

TCP stands for “transmission control protocol”. IP stands for “internet protocol”. Together they form the backbone for almost everything you do online, from web browsing to IRC to email, it’s all built on top of TCP/IP.

If you have ever used a TCP socket, then you know it’s a reliable connection based protocol. This means you create a connection between two machines, then you exchange data much like you’re writing to a file on one side, and reading from a file on the other.

TCP connections are reliable and ordered. All data you send is guaranteed to arrive at the other side and in the order you wrote it. It’s also a stream protocol, so TCP automatically splits your data into packets and sends them over the network for you.

IP

The simplicity of TCP is in stark contrast to what actually goes on underneath TCP at the IP or “internet protocol” level.

Here there is no concept of connection, packets are simply passed from one computer to the next. You can visualize this process being somewhat like a hand-written note passed from one person to the next across a crowded room, eventually, reaching the person it’s addressed to, but only after passing through many hands.

There is also no guarantee that this note will actually reach the person it is intended for. The sender just passes the note along and hopes for the best, never knowing whether or not the note was received, unless the other person decides to write back!

Of course IP is in reality a little more complicated than this, since no one computer knows the exact sequence of computers to pass the packet along to so that it reaches its destination quickly. Sometimes IP passes along multiple copies of the same packet and these packets make their way to the destination via different paths, causing packets to arrive out of order and in duplicate.

This is because the internet is designed to be self-organizing and self-repairing, able to route around connectivity problems rather than relying on direct connections between computers. It’s actually quite cool if you think about what’s really going on at the low level. You can read all about this in the classic book TCP/IP Illustrated.

UDP

Instead of treating communications between computers like writing to files, what if we want to send and receive packets directly?

We can do this using UDP.

UDP stands for “user datagram protocol” and it’s another protocol built on top of IP, but unlike TCP, instead of adding lots of features and complexity, UDP is a very thin layer over IP.

With UDP we can send a packet to a destination IP address (eg. 112.140.20.10) and port (say 52423), and it gets passed from computer to computer until it arrives at the destination or is lost along the way.

On the receiver side, we just sit there listening on a specific port (eg. 52423) and when a packet arrives from _any_computer (remember there are no connections!), we get notified of the address and port of the computer that sent the packet, the size of the packet, and can read the packet data.

Like IP, UDP is an unreliable protocol. In practice however, most packets that are sent will get through, but you’ll usually have around 1-5% packet loss, and occasionally you’ll get periods where no packets get through at all (remember there are lots of computers between you and your destination where things can go wrong…)

There is also no guarantee of ordering of packets with UDP. You could send 5 packets in order 1,2,3,4,5 and they could arrive completely out of order like 3,1,2,5,4. In practice, packets tend to arrive in order most of the time, but you cannot rely on this!

UDP also provides a 16 bit checksum, which in theory is meant to protect you from receiving invalid or truncated data, but you can’t even trust this, since 16 bits is just not enough protection when you are sending UDP packets rapidly over a long period of time. Statistically, you can’t even rely on this checksum and must add your own.

So in short, when you use UDP you’re pretty much on your own!

阅读全文 »
1…45

Lumieru

46 日志
8 分类
17 标签
© 2022 Lumieru
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Pisces v7.1.1