Jump to content

  • Log In with Google      Sign In   
  • Create Account

Angus Hollands

Member Since 06 Apr 2012
Offline Last Active Aug 26 2016 06:37 PM

#5306952 Friends living abroad have really laggy connection to me, why?(using raknet,...

Posted by on 20 August 2016 - 08:49 PM

There are several issues at play here.


Firstly, you shouldn't really be running at 500FPS simulation framerate. That's absurd! Most games with any physics will ask for at most 60FPS. You should lock your simulation frequency to something like 60Hz, and render separately to that timestep.


Secondly, you can't hope to send data every tick. You'll flood the connection. Running at a reduced transmission rate, and keeping packets small reduces the liklihood of this happening.


Thirdly, the speed at which information can travel between two end points is finite and non-zero. At best, it's the speed of light distance, realistically though the path between two nodes is not a geometric minimum, and isn't entirely vacuum (instead copper + fibre). In short, there will be latency, and it's calculable for a ballpark figure.


The clients do not need "new" state for each sim tick. You can interpolate between recent states, or extrapolate the latest state to smooth the timestep between two simulation states from the server.

#5284143 "Weapon Fired" Event -- Reliable, Unreliable, or In-Between?

Posted by on 29 March 2016 - 05:55 PM

Whatever solution you use will depend on a few things, including whether your client simulation runs in the past or not. If you're already interpolating entities, that will give you some additional time to receive information about projectiles.


When it comes to entity replication, I will send a reliable un-ordered packet that contains the information required to instantiate the entity client-side. From there, I would send state updates as unreliable, discarding out-of-date packets. You could even reduce bandwidth for predictable projectiles and just send the initial state, with the network tick and velocity, and allow the client to simulate it.


I'm generally uncomfortable with the notion of reliable ordered. The reason most use UDP for fast-paced games is to avoid the latency that is fundamental to the operation of a reliable stream over unreliable network conditions. At least with reliable unordered you can proceed other state whilst the packet is redelivered when dropped.

#5236469 Glitches in Navigating my NavMesh

Posted by on 23 June 2015 - 06:17 PM

The way that Recast & Detour handles this is to include the agent's radius in the navmesh (to avoid having to post-process paths). In my game, I just apply velocity in the bearing of the waypoint until within a specific margin (0.01 m or so (> than 1 frame velocity error)) and then switch to the next waypoint. You could also check if the dot of the vector from the current waypoint to the npc position is greater than the distance between the current and next waypoint.

I avoid recalculating paths by only doing so if the target moves. You could extend this further by keeping track of entites within the same node and checking if they're in the path or not. To handle the case where the player leaves the navmesh, I keep track of the last node the player was within, then find the nearest neighbour according to the edge distance (assuming that I'm not currently in a node).

#5213092 Component-based architecture - entity and component storage

Posted by on 26 February 2015 - 09:08 AM

As you may be aware, there are a large number of different implementations of component based systems.

Especially in languages such as C++, the benefits of ECS designs can be the ability to employ contiguous memory. If you have each system allocate a pool of components, then you can reduce the frequency of cache misses, and hence improve performance of system updates.


Hence, when you register a component with an entity, it makes sense to request it from a system, which will maintain an internal pool (and therefore update internally) of components.

IComponent* physics_component = physics_system->create_component();

// Some time later
double delta_time = 1.0/60;

This has its difficulties when you have systems which share components with other systems. Generally speaking, avoiding this dependency helps a great deal.

#5208642 Why is scaling an mmo so difficult?

Posted by on 04 February 2015 - 10:09 AM

I think the best option is to run the safe code on the server, use databases to store players game state and balance out the load between servers. Any tips here?

That's exactly it! Now, good luck developing!

The tricky part is in the how - how do we "share load" between servers, in a seamless fashion to the end user? How to we divide the calculations required across multiple servers? Do we split them geographically in the real world (for faster latency response) or in world (for faster lookup of local entity data)? How should we handle interactions across servers?


I'm not an MMO specialist, but there are a number of topics recently posted in this forum which should be of use :)

#5201776 Average user packets per second

Posted by on 04 January 2015 - 12:21 PM

If you're trying to ensure that you don't flood clients with data, then it would be sensible to perform some dynamic throttling. Start with an estimate of what you might consider appropriate. When you start dropping packets, halve the estimated bandwidth, otherwise increase slowly by some constant value.

(Thanks to hplus0603 for this recommendation in a previous discussion)


I would also recommend only modifying this value (reduction or growth) after it can be confirmed that data has been received from the client since the last change was made (as there might be n packets dropped before the client receives data at a reduced rate from the server due to the packet loss, so you would actually reduce the bandwidth by 2^n if you did not take this into account).

#5159483 game's protocol between client/server

Posted by on 10 June 2014 - 06:22 AM

Typically, it won't matter what the contents of the message are when you need to handle where it goes. Usually, you might prefix the message with an identifier (type) that can be used to select the appropriate recipient. The contents are then managed by the requesting handler.


If you're using JSON, everything is serialised/deserialised in one go, so this is less explicit in practice, but you can still simply define the message to include a type field, and the rest is up to the sender.


That way, you check the type field and dispatch to the recipient as needed. Creating a generic message that does everything every message might need is both a waste of bandwidth and development time.

#5155768 Variance Shadow Mapping Shadow Brightness Issue

Posted by on 24 May 2014 - 07:49 PM

Whilst I have little immediate experience on the subject, we had VSM shadows implemented recently, and a similar effect was observed.
The developer who implemented speculated (in passing) that the intensity of the light source was influencing the shadow


#5155757 Timestamping & processing inputs

Posted by on 24 May 2014 - 06:15 PM

As long as the buffer has reasonable bounds, dropping any extra inputs which exceed the maximum buffer length will prevent the client from feeling lagged, instead they will notice server correction. This case will only occur if you send an excessive number of inputs, so you have to tune your upper bound for your buffer to consider the tradeoff between command latency and connection quality. 


Best ensure that you start sending inputs at a consistent rate though, don't try and account for the time spend loading for the map - that time is "dead time", meaning that user-input wasn't useful or valid during this time.

#5155707 Packet combining

Posted by on 24 May 2014 - 01:08 PM

There are many different ways of handling your packets. I tend to define a header as the size of the packet contents, then its protocol. That is it. This helps avoid errors within a single packet from causing off-by-n errors elsewhere. So an entity update packet might involve sending the number of repeated entities, then packing their data, and appending the header to that packet. 

#5153321 Perfectionism and Programmer's Block

Posted by on 13 May 2014 - 09:12 AM

I think that there is merit in thinking very carefully about what you do before you do it, just to stress this point. However, it is true that you cannot foresee what you will eventually ask of your code, so the most important thing is to keep to good design principles. It becomes structurally much easier to later modify the flow of execution if everything is nicely encapsulated, and even change implementation details.


But best choose one or the other. Either spend an inordinate amount of time planning and thinking before writing anything, or do the basic ground work, and get started - and quickly identify what might need to be changed. That way you make the best use of your time :)

#5148946 Your most valuable debugging techniques for Networked games?

Posted by on 23 April 2014 - 06:58 AM

Unit tests are a god send!


I've never been exposed to their necessity in a production environment, but now I don't think that I will need that experience to encourage me to use them. If you can't write a unit test for it, it probably needs refactoring!


Most network errors are caused by misreading data from the byte stream (off by-n errors).I always check the data coming in. However, recently I had an error in some reading code which caused an off by one error. The best thing to do in those circumstances (my error only arose after data was already sent) is to break the simulation into three different states and compare the transition between them (whenever my variable was set to None, it remained considered as a None value (Which isn't included in the byte stream) hence we forgot to read an extra byte from later packets! I had to break it down to fix it.


Having an inspector in game is really useful, (assuming you're a runtime interpreted language) even a GUI with a command input dialogue is all you'd need (as long as you can prevent the game state from progressing)

#5148423 Can a non-programmer make games?

Posted by on 20 April 2014 - 05:18 PM

Simple answer, no. More complex answer, yes:


A game is really an abstract concept, many things can be considered "a game". A game involves creating an experience, and that is a broad field. Anyone can create a game by this logic. What you're really asking is, can someone without programming knowledge create a playable game with existing tools, and the answer to that is yes. Programming itself is often a case of learning about logical thinking - maintaining an understanding of how your code translates into the user's experience, and how your systems work with one another, and any potential APIs. As a programmer, one doesn't possess any ability a "non" programmer does not, they have merely developed the line of logical analysis further, to enable them to express their thoughts in another language, on another architecture.


For example, I specialise in Python, but I have a good grasp of many other languages. After learning how programming necessitates a certain mindset and adopting it, it was far easier to learn new languages, and even the difference between typing, interpreting and additional language capabilities did not prove to be too challenging to grasp, given the initial toolset that I had learned.


You will need to program in order to develop a game. A game requires some form of interactive experience, and interactive experiences need to be designed. However, programming is a diverse and loosely defined concept, and there are many restricted and abstracted programming environments which enable you to write "code" through a more visual approach.


Such examples include Blender Game Engine's logic bricks and Hive nodes (which are currently quite young in implementation), Unity PlayMaker and UScript, UDK's Blueprints / Kismet, the list goes on.


Ultimately these translate, like programming languages, into machine code,the difference is the semantics. With all of these systems, there comes a price. Typically, more complicated programs either do not translate into visual languages, or they do so poorly. It may be  that on occasion, you require someone else to implement logic into a visual logic editor for you (e.g writing a new node), which limits you as the developer. 


My advice would be to understand to adopt the programmer's mindset, even if you don't intend to write complex programs any time soon.


I wish you the best!


#5148211 Entity Interpolation

Posted by on 19 April 2014 - 01:31 PM

You might want to split it into more functions, so it can be easier maintained and checked for errors:

function interpolateClientState(stateA, stateB, interpolationFactor)
	// Interpolate between the two states
	var interpolatedPosition = previousSnapshot.position.lerp(nextSnapshot.position, interpolationFactor);

	// Create interpolated state
	State interpolatedState;

	// Set the position from the state
	interpolatedState.position = interpolatedPosition;
	return interpolatedState;

function applyState(state, actor)
	// ...

function updateRemoteClients() {
	var currentTime = new Date().getTime();
	var renderLatency = 400;
	var delayedTime = currentTime - renderLatency;

	// loop over all our remote clients and find the interpolated position to draw them at
	for (var c in remoteClients) {
		var actor = remoteClients[c];
		for (var i = 0; i < actor.snapshots.length; i++) {
			// make sure we don't go out of bounds with our checks
			if (!(i + 1 < actor.snapshots.length))
			// Get snapshots
			previousSnapshot = actor.snapshots[i];
			nextSnapshot = actor.snapshots[i + 1];
			// Get timestamps
			var previousTimestamp = previousSnapshot.timestamp;
			var nextTimestamp = nextSnapshot.timestamp;

			//  Determine if we straddle the delayed timestamp
			if (!(previousTimestamp < delayedTime) or !(nextTimestamp > delayedTime))
			// Calculate the factor (0.0 <= factor <= 1.0) to interpolate by
			var interpolationFactor = (delayedTime - previousTimestamp) / (nextTimestamp - previousTimestamp);
			// Get new state
			var interpolatedState = interpolateClientState(previousSnapshot, nextSnapshot, interpolationFactor);
			// Apply new state
			applyState(interpolatedState, actor);

Be aware this is psuedocode (I can't remember all the Javascript object creation information).

#5136654 Switch or Not?

Posted by on 05 March 2014 - 06:39 PM

All programming languages become boring eventually, because the user confuses their own lack of direction with a fault in the language (not that I'm accusing you of that in these circumstances). Except Brainfuck. I can't see how you'd ever get bored, because you'll never understand what is going on :)


If you're trying to produce a game, using an existing framework / engine will help you get there quicker. But if you're truly passionate then it's inevitable you'll one day take a step back and implement the same things for yourself, so it's where you start.