Right now I'm trying to make a mmorpg for the iPhone. I have it set up so that the iPhone requests for the player positions several times a second. How it does this is that the client sends a request using asynchronous NSURLConnection to a php page that loads the positions from a mysql database and returns it in json. However, it takes about .5 seconds from when the positions are requested to when they actually get loaded. This seems really high, are there any obvious things that could cause this?
Also, this causes the player movement on the client to be really choppy too. Are there any algorithms or ways to reduce the choppiness of the player movement?
Start measuring how long the database query takes when you run it outside your iPhone.
Then measure how long it takes when you send the same http request from something other than your iPhone(It's e.g. a 10-15 line c# program to figure this out).
If none of the above show any sort of significant latency, the improvements need to be done on the iPhone side. Some things to look out for:
GPRS/3G has rather high latency
GPRS/3G has rather high bit error rates - meaning there's going to be quite a few dropped packets now and then which will cause tcp to retransmit and you'll experience even higher latency
HTTP has a lot of overhead.
JSON adds a lot of overhead.
Maybe you'll need to come up with a compact binary format for your messages, and drop HTTP in favor of a custom protocol - maybe even revert to UDP
The above points generally don't apply, but they do if you need to provide a smooth experience over high latency,low bandwidt, flaky connections.
At the very least, make sure you're not setting up a new TCP connection for every request. You need to use http keep-alive.
I don't have any specific info on player movement algorithms, but what is often used is some sort of movement prediction.
You know the direction the player is moving, you can derive the speed if it's not always constant - this means you can interpolate over time and guess his new position, adjust the on screen position while you're querying for the actual position, and adjust back to the actual position when you get the query response.
The trick is to always interpolate over time within certain boundaries. If your prediction was a bit off compared to what the query returned, don't immediatly snap the positon back to the real position. Do interpolation between the current position and the desired postion over a handful of frames.
On the server side you should be using some system that keep running and that keeps the database connection open all the time. Preferably it would also cache things instead of requesting them from database all the time.
Also, do not make a new HTTP request for every update. It would be best if you hadn't need to use HTTP at all, as it really isn't suitable for realtime comminunication.
GPRS typically has 600 ms ping time, 3G has 300 ms and HSPA has 100 ms. See which mode is being used. Notice that some devices (I don't know of iPhone) drop from HSPA to regular 3G for power-saving reasons whenever there is not enough traffic to justify the faster mode.
As for position, a rather common practice is to apply a linear prediction, i.e. make the character continue movement in current direction, at the current speed, even when no data from server is available yet.
Most importantly: benchmark/profile to see where the latencies are. Is it your server, the network connection or the application.
Loading the player positions that fast has downsides.
It hammers your server.
3G isn't really meant to support low-latency applications
So I don't see a mmorpg working without some necessary shortcuts at this time, e.g. extrapolating paths based on their velocity and position. Loading positions will not work as fast as you want, especially with a server based on PHP of all things.
Either way, when developing for a mobile platform you're going to have to make sacrifices in terms of features versus a fully-featured desktop implementation.
I might also reimplement some of the more critical stuff if not the whole server in a faster language, e.g. C++.
Related
I have managed to sync my ridigbodies real good but I just noticed that when a client (that's not the master) collides with one it doesn't move, it's locked, while reading on the net I had an idea when the object collides with a rigidbody I just transfer the ownership of that object to that client for the moment for this client to process the collision (I have tested this and it works really good, both clients sync perfectly)
is this recommended? performance-wise and security/cheating wise?
Thanks!
Short answer:
Transferring ownership of a GameObject to a client, when that client needs to control and update the object data, is fine. In cases of detecting cheating possibilities, always have one client (typically the master client or a dedicated server) validate, correct and sync the data to all clients.
I will not make any assumptions. Based on your explanation of the issue, it seems your GameObject Rigidbody IsKinematic was not being synced, causing the collisions having different effects at each client end. But in case that might not be the issue, I have a longer answer hoping it might help for this or other scenarios.
Longer version:
Sync Rigidibody data over the network where it is fundamentally required to be present on the client GameObject. The rest of the Rigidbody data can be created / calculated / simulated on each client individually:
This way, you will make sure all parameters of that Rigidbody are correct (e.g. isKinematic is correctly enabled/disabled on all clients)
Your games will always have the minimum required data to create/simulate the rest of the events and effects properly, reducing network lags and improving performance.
Where data validation is required, the master client will always validate the non-master client data, makes the crucial adjustments and decisions and updates the room data for all clients where necessary. This reduces the chances of players cheating.
Developers will find bugs easier when the events that are supposed to take place on each client, do not align with what is expected. This shows itself more often in scenarios where several events should take place at the same time and on each client.
Much longer version:
When I use PUN2 on GameObjects in my games, I only sync Rigidbody where those GameObjects require Rigidbody values to be present on the clients during collisions to perform specific tasks (e.g. using the velocity or direction for dynamic sound/visual effects), or when the master is validating and correcting the data needed for the non-master clients (as a result of network delay or cheat/hack tampering the data on client side).
When using PUN2 (up to this date), I update its class internal code to my needs. For example, PhotonRigidbodyView does not sync the kinematic state of a Rigidbody yet. When I need this in my games, I could override the class with my CustomPhotonRigidbodyView class (and/or updating the PhotonRigidbodyView a bit).
Does it effect the performance when using PhotonRigidbodyView? Yes, when not used with care, it does decrease it when there are too many objects syncing over the network at the same time. The clients will see jagged movements.
Does it allow cheaters to take advantage of this data, manipulate it and send it over to the clients? Yes, if the game is vulnerable to basic cheats. Then again, the topic of security/cheat detection is quite vast, so for each game definition of "basic" cheats are different.
Is it a good idea to transfer ownership momentarily to be processed on client side? Yes in some cases, other cases no:
If doing this momentary transfer is the only place you do this and it solves all your problems (except cheating), then use it so you won't spend too much time fixing this one part in a different way.
If the Rigidbody or Transform data is being validated and/or synced, either constantly or in periodic intervals by one client (to prevent cheating or to sync client data properly at crucial times), then it is fine to transfer momentarily too.
I typically transfer ownership, when the object data must be changed by the client (e.g. grabbing / dragging around / shooting / throwing) and once the action is performed, ownership will be back to the master to be validated and synced for all clients (including the one that just transferred the ownership). This results in more time spent on testing, catching unwanted (possibly unseen) bugs, and reduced cheating possibilities.
In case a developer working on your game has not properly optimized the Collider and/or Rigidbody components for each GameObject yet, please make sure you have done so before syncing their data over the network. This page in Unity doc may be a good reference to check whether your GameObjects need to be static colliders or dynamic colliders:
https://docs.unity3d.com/Manual/class-Rigidbody.html
https://docs.unity3d.com/Manual/CollidersOverview.html
Once the GameObjects that need a Rigidbody component are identified, then you can decide which ones need to be fully synced over the network or partially synced and/or their ownership transferred when required.
I hope my answer does not confuse any of the readers. If there is anything not clear, please mention in the comment and I will improve my answer for you.
Update: 2019-05-10 (reply to the 2nd comment):
For a pool game involving so many GameObjects, I would not transfer the ownership of all objects to a client. I would:
Create a struct holding the necessary information such as:
ball_id: indicating which ball is being hit by the pool stick
hit_info: a Vector3 representing the position (on the ball surface) and direction of the hit applied to the ball, by the hit stick.
hit_force: the required force to apply to the Rigidbody of the ball that is being hit by the hit stick.
and any other information that I might need, when the player hits the ball with stick.
I can then combine this information and pass them to the AddForceAtPosition method of the Rigidbody of the ball.
Dispatch this struct in the room, for all the clients to receive.
Once each client receives this message, including the sender, (in OnEvent as EventData containing the Phton Event Data), it will apply this info to the correct ball and will create its own version of physics (small differences will be noticed between each client).
This way:
I have the minimum amount of information passed over the network to make the simulations happen on all clients
Improved performance of the game by avoiding parsing and applying unnecessary Rigidbody data
Reduced the cheating possibilities of a client moving any of the other balls that they are not supposed to, around the table or into the pots.
To increase security as well as making sure the balls on all clients are exactly where they are supposed to be, another struct will be dispatched for example by the master client, indicating the exact position (and rotation) of each ball on the pool table (or in the pot).
I would sync the ball positions periodically (either at pre-defined intervals or at specific moments of my choosing depending on the game state) to all clients to overcome any incorrect positions at any moment in the game. This periodic sync can be done by the master client or a dedicated server.
What I'm trying to make
Hi, game development newbie here. The game I am trying to make is fairly simple. It's almost exactly like the old FC game "Ballon Fight" except that I'm trying to make it online where players can go through a match making to find opponents.
BalloonFight:
What I Read
I have read some articles, and found most of them lead to two approaches:
Put all game logic on the client, and the client sends player inputs to server on every frame update. The server acts like a dispatcher which only makes sure player A's input is received by both client A and B. My understanding is that if we see the client in this case as a pure function, and if the two players' inputs are received by each other, the game should produce same results on both clients. Thus synchronization is achieved.
Put all game logic on the server, and let the server do the calculations and send back results to both clients. In this case, clients only worry about displaying.
My Fears
Solution 1 sounded like a simpler one to me, but immediately I realized when network problem is put into account, it becomes incredibly complicated. Losing player A's connection for a few seconds means all the input is lost in that period. What I can guess is, to counter that, the server has to detect whether player A is lagged out and accumulate input from player B until player A is back then feed all the accumulated input to player A's client. Player A's client then need to do a fast forward to catch up. This sounds like there's huge amount of infra work on both client side and server side.
Solution 2 on the other hand looks very daunting to me, since for now I have only written some games on the client side.
My questions
in order to make a simple online game like this, what is the most beginner friendly way to synchronize game state?
if I were to use solution 1 stated above, is there any framework that provides such infra so that I don't have to handle network issues all by myself?
In advance, thank you game dev gurus.
we're attempting to track a streaming video with SiteCatalyst.The issue comes in as this video has obsviously no end and the s.media Module can't know how to set the seconds or milestones segment views.This is resulting in no tracking calls except for the starting one.Could a possible solution be the usage of s.media.monitor custom functions?Here's explained how to use them together with the basic Media module settings.Maybe a timing deployment of "sendRequest()" method could help...?I use this occasion to ask a brief how-to example of media.monitor methods, because I've been just using the basic settings till now, as below:
s.loadModule("Media");
s.Media.autoTrack = false;
s.Media.trackMilestones = "25,50";
s.Media.segmentByMilestones = true;... ...Thanks a lot
Yeah.. i really, really dislike the Media module. Video tracking is getting more and more popular with the clients, so it has become the biggest thorn in my side, because the nature of videos over the internet is a big mess with all kinds of moving parts internally, that make it extremely difficult to get truly accurate tracking beyond basic "start" and "stop". (actually I take that back.. I think mobile/sdk tracking is quickly becoming the thing i shake my angry fist at the most, but that's a different post!)
I think Adobe has made some heroic efforts to automate video tracking and it more or less works okay if you just have a regular (not flash) object or html5 tag embedded on the page but in practice, MOST of the time, sites implement their videos through 3rd party scripts (e.g. jwplayer, vimeo, youtube api) and the Media module automation basically goes down the drain on that count.
I understand that it needs to know how long a video is to know when to autopop the events, but I swear, 99% of the time in practice, the way Media module expects things to pop in certain orders etc.. it just doesn't align with how videos work in the real world. Even if you attempt to do it the "manual" way, more often than not it's still buggy,e.g. autoplay and buffering ALWAYS seem to screw up the open+play sequence that MUST happen in that order.
Basically, the Media module desperately needs to be rewritten to better handle streaming videos, and also just "manually" using it in general. Anyways..
Two things I have done in your situation. Overall, neither one of these options are a perfect 1:1 to normal videos with a duration, but then, streaming videos aren't really the same, so it doesn't really make sense to treat them the same.
Option #1: Use an estimated duration for your streaming video. So you said it yourself: your streaming videos have no end. Well as I mentioned, you can't calculate percent viewed unless you have a duration, pretty basic math. So, estimate a duration.
I have clients that have streaming webinars or whatever and it's true that there's technically no duration according to the player, but in reality they don't really conduct that webinar 24/7 forever. In reality it's for a set amount of time like 30 minutes or an hour or something. So, just specify the duration as that.
Yes, this will require extra custom work on your end to store/associate an estimated duration. And yes, this does have the potential for being misleading (e.g. if a webinar ends early or runs late). This option is generally good for sites that have set windows for the stream to actually be active.
Option #2: Ditch the notion of % viewed, record it as n time consumed. So the overall point of the milestones is to know how much of a video was actually watched, yes? Well, who said it has to be measured by % viewed?
How about instead, you just record n seconds consumed every n seconds. You can do this with an incrementor eVar, and/or counter event. (Part of the normal video tracking actually does include a counter event "Video Time", or a.media.timePlayed).
So basically, you'd basically just pop the events/props/eVars yourself, and ignore milestone/segment reports.
Note: This option only really works if you are using the older style video tracking that has events/props/eVars assigned for it. If you are using the newer style video tracking that does not use events/props/eVars.. well, AA does not currently offer an official way to manually pop that stuff directly. It is surely possible to unofficially do so, but I have not yet reverse engineered the latest Media module to figure out how to do that. So, in this case your only option is #1.
I have looked at several variations on the Reachability example such as the Donoho change and erica saduns UIApplication extension, but none of these allow you to determine the quality of your 3g connection.
Is there a programatic way to see signal strength and link quality?
I think you need to decide exactly what you mean by quality and also understand that it constantly changes.
The only really accurate measure is unfortunately historical - i.e. you can do a download or upload test and measure the time it took and any packet loss, jitter, delay etc and this will let you know what the quality was when your test was run.
The reason I say it is historical is that this does not guarantee that it will stay like this for any given time - for example you may move between cells (or rooms in the case of WiFi), or several other users in your area may start utilizing the bandwidth heavily.
It may be that a simple download or upload test is sufficient for your purposes to (I am guessing...) decide if your want to run your application in a certain way, and then you can build in further checks into the application itself to see if you need to adapt to a change in the network (e.g. you could trigger on the time for a particular application message transaction to complete)
This is more a system design question/challenge, than a coding question.
Basically, I'm thinking of throwing together a Bejeweled-esque game on Facebook using just HTML, CSS, and javascript. This is mostly out of a desire to learn all the little caveats of FBJS via a non-trivial project.
So here's the deal. When developing for Facebook, actual API calls are very expensive; not only is there an additional POST to the Facebook servers, there's also the api call limit and throttling to worry about. In a nutshell, the fewer calls to Facebook the better. Combine this with the timing concerns of even this simple puzzle game, and there's good reason to aggressively minimize the number of callbacks in general.
Not being a security expert, here's the design I've come up with:
Embed a random seed in the game page.
Use that seed to create the game board (As well as additional pieces as needed).
Tweak the seed (xor, concatenate and hash, something like that) after each player move, based on time since last move. Edit: I should probably also include the actual move taken in mutating the seed.
Upon game completion post back the following: game start time, each move taken and when, and the client side results.
On the server, re-run the game with the given data, sanity checking the start time and move times, and then confirm that the results match.
To mitigate denial of service, the game itself will be tweaked to have a win by turn X condition.
To discourage the server being used as a "oracle" of sorts, a user posting back an invalid game will be banned for some constant time X (X being on the order of minutes).
This design requires three Facebook call per game played: one to store the random seed before the game is played, one to fetch it after the game is finished, and one to update the player's score if the game is valid.
What I'm trying to proof the system against is straight up score spoofing (http://...?myscore=999999999, or similar). I'd also like to mitigate "look ahead" attacks, wherein the user can tell what pieces are coming to the board next. Denial of service attacks on the hosting server (intentional or otherwise) should also be prevented.
The actual question, can anyone see a flaw in this design? Equivalently, is there a simpler design that meets my criteria?
Note: I am aware how unnecessary this probably is, but its an interesting question none the less.
I'm going to try and throw some numbers up here to futher illustrate my reasoning, these are pretty rough but I hope helpful.
Assuming a 10x10 game board, there are ~200 potential moves (swapping two adjacent pieces) most of which are invalid. Let's say there are on average 5 valid moves per "turn". If we constrain player actions to the frame of 50 to 30,000 milliseconds, there are 149,750 potential new hashes provided the "tweaking" algorithm doesn't discard bits; I feel confident in say there are at least 10,000 potential new hashes which must be calculated by an attacker assuming a cryptographically secure hash is used. If you throw a min-max algorithm at this, your decision tree explodes very quickly. Throw a game session expiration at this, say 30 minutes, and I believe the attack because equivalent in complexity to writing a little bot program to play for you which cannot reasonably be defended against.
If the client code calculates the next piece and you can't hide this algorithm very well, then some bored college student will figure this out. As a result, they will be able to generate a massive score and defeat your intentions.
I tend to say that it is impossible to do. Why? You cannot trust the client - I could just analyse and completly rewrite the client side code and return whatever values I like. The only way to protect you from cheating and all kinds of attacks is to perform the logic at the server - the client will just collect user input and display the server output. But this is completly against your design goal to minimize the number of server calls.