Nuno Afonso
  • Home
  • Flux
  • About

Unity & Object-Oriented Programming

4/7/2018

5 Comments

 
There was a session in GDC called “A Data-Oriented Approach to Parallelizing Hierarchical Transforms (Presented by Unity Technologies)” and given that I had seen the past Unite the session by Joachim Ante on their new Entity Component System I wasn’t planning to go to it. I had never heard about Mike Acton, so when somebody mentioned to me "it should be really good" I decided to give it a shot.

The session starts very well; Mike makes an analogy on how Unity is like a car full of clowns, and before moving forward we have to make sure all those clowns are out of the car. At this point I’m pumped, I’m thinking that finally somebody is going to break out of this idyllic view that the Unity developers often portray (can’t remember how many discussions I was involved with Unity about weird decisions, like their IMGUI or how “C# is fast enough”) and put all its skeletons out in the open. And then he drops the bomb: “and the first clown we have to get out of there is Object-Oriented Programming”.

​Object-Oriented Programming is Communism and Data-Oriented Programming is Democracy

I’m always very weary when people take extreme positions. By default, Communism has a very good concept; to make society more equalitarian. As a goal this sounds pretty good to me, but even Marx predicted that for it to be achieved, the sacrifice would have to be huge.

At its core, Object-Oriented Programming (OOP) has the following principles:
  • Encapsulation
  • Abstraction
  • Inheritance
  • Polymorphism

These are very simple concepts. Nothing inherently wrong with them, and at its heart it is what OOP is. The problem, like with Communism, is not about the goal but what we do to try to achieve it.

In my opinion, there is a massive problem with how programmers are being taught today. In my line of work, I very often come across two major issues: over engineering, and suboptimal code.
​
Over engineering is the worst from architectural point of view, because it goes against the whole purpose of OOP; it makes things more convoluted, complicated, unmaintainable, inflexible.

Suboptimal (some might call it simply bad) code has to do more with how programmers code without realizing the implications that the code they are writing has, e.g. allocating memory like crazy, algorithms that iterate over data far more than needed.

I mostly blame schools because they teach students to do things “the right way”, but the students have their share of blame too. It is specially frustrating for me when young programmers are very stubborn in their “right ways” of doing things, and they should be more open to understand that “right” is a very subjective term (history teaches us that over and over), specially when sometimes these mentors that taught them never actually had real world experience on the subjects.

Not saying school or teachers are bad, but I do think it could be better. It’s weird to me that at the point people should be most open to learn (given that’s what they were doing for most of their life), they are the most closed to it.

And now here comes Data-Oriented Programming (DOP), the Democracy, allowing all developers to take hold of the full potential (of not only their games but themselves). Democracy is one of those interesting concepts, in theory everybody has an equal say in it and the majority drives the direction but, as we’re seeing these days, what happens when the majority is being fooled by huge propaganda machines?

This is how I feel about DOP; at the moment there’s this idea starting to push it forward as “the right way” of programming. If bad OOP code can be tricky as hell to get around with, one can only imagine with DOP code.

DOP was the old way of doing things (more out of necessity), that’s basically the core of C programming language, but at a certain point everybody (i.e. in general programming, not talking about low level kernel) kind of flocked at the idea of having a better way to organize things without sacrificing much performance.
​
Don’t get me wrong, I don’t think that DOP shouldn’t be used; like every tool it has its purpose but as a default I believe that OOP is a far better option when creating complex code like an App or Game, specially when you have a lot of people involved (exacerbated by lack of experience).

​The Biggest Clown

Unfortunately, it seems to me that the biggest clown in Unity will continue there. He’s the one with the driving license, and as such will not leave the car. I’m not talking about nested prefabs, input systems, core loop methods based on broadcasts, or any other piece of code; I believe that for Unity to become a real AAA engine, Unity Technologies needs to start making games.

Only when you have to do big games with a lot of people you realise all the problems that actually exist, and all of a sudden these cannot be skimmed over or ignored. They are show stoppers (or at the very least delayers) and require full on attention to tackle and solve them.

For long I’ve had a love/hate relationship with Unity. I’ve been there from the start in the Mac OS days, and I’ve been actually very close to dropping it, but fate brought me right in for professional reasons. It’s funny because Unity is in the best shape it has ever been, but like a victim of domestic abuse that endured for years eventually there’s that little thing that will tip the scales.
​
I honestly hope that Unity becomes better, but I advise extreme caution specially to inexperienced teams following extremist points of view.
5 Comments

Unreal Framework & Network

4/27/2015

13 Comments

 
One of the biggest problems when getting into UE is that the documentation is very lacking in some areas. One example, is that they talk about their framework, but I didn't find anywhere is how this framework is organised between Server and Clients.

This post is meant to shed some light on how things are structured, so that you can get a better understanding on how things work and what exists where.

Network in Unreal

Unreal's network is the standard server-client architecture. Basically, the server is authoritative, and the clients send information to the server, which the server then validates and executes upon.

So when you're moving your character, the one that actually moves it is the server. You can specifically see this if you have a bad connection with the server, where you'll feel the character unresponsive  and your character position will be corrected, warping it to where it actually is in the server.

This also means that clients never talk to each other directly. If you want to send a chat message to the players on your team, what you're actually be doing is sending a message to the server saying that you want to send a message to your team, and the server will be the one relaying it.

When developing a game that you want to work in multi-player, I advise you to always keep this in the back of your head, never just "do something", tell the server to do it (exception being client only things, that should just be "visual stuff", nothing that actually influences the game).

Framework & Network

So given this, it means that the framework is laid out between:
  • Server Only - an object only exists on the server
  • Server & Clients - an object is known to everybody, so if the server changes it all the clients will get the update
  • Server & Owning Client - an object only exists in the server and the client that owns it
  • Owning Client Only - an object only exists in the client that owns it
Framework Layout
How the "most important" framework classes are laid out in network terms
The next picture shows how the objects would be distributed through the network:
Framework Example
Framework example of a dedicated server with 2 Clients
Notice the intersection between client 1 and 2 doesn't have any objects, just like I mentioned above, everything goes through the server.

GAme Mode

Picture
The Game Mode (class AGameMode) is only meant to define rules of the game, for example how many lives each player starts with, check for winning conditions, etc. It is only present in the server, so you want to only handle there things that only the server would care about.

GAme State

Picture
The Game State (AGameState) is probably the most important globally shared class. It holds a list of the players in the game (Player States), so when you want to get a player you go through it, NOT through UGameplayStatics::GetPlayerController (which is a very common beginner's mistake).

So if Game Mode held how much time a round of the game took, the Game State can be seen as the class that would keep track of the time remaining.

Player State

Picture
The Player State (APlayerState) is the most important player related class, because it represents the player, and as such is where the important information about the player will be kept (e.g. how many lives he still has, team he belongs to, username, etc).

Pawn

Picture
The Pawn (APawn) is a thing that the player can control (through the Player Controller).
There can be multiple Pawns in the game, however the Player Controller can only possess one at a time.

For convenience, UE has a Character (ACharacter), which comes from Pawn, and adds a "network movement component", which handles the movement of the Character. Like I mentioned above, the server is the one that moves things, not the client, so it is because of that "special" character movement component that we're able to just say locally to move the character, but in fact that abstracts for us the fact that the data is being sent to the server to act upon it.

Player Controller

Picture
The Player Controller (APlayerController) is in my opinion the biggest trap for newcomers to UE.

Most people associate the Player Controller with the representation of the player, which is wrong. The Player Controller can be seen as the "player high level input".

Basically when the player possesses a Pawn, this is the class that will control it. The reason that I call it high level input and not just input, is because you CAN have the input in the Pawn; in fact, I recommend you do your input in the Pawn, because in a lot of cases you possess pawns with completely different input and behaviour (e.g. a human and a car), so it is much easier to handle the input in the Pawn it refers to, than globally handle all input in the Player Controller.

By the way, the way input works, it will first be passed to the Player Controller, and if it doesn't get used up by it, it falls through to the Pawn. So you can have different levels of input, for example handling menus in the Player Controller, and then the movement of the Character itself on it.

Something that a lot of people stumble upon is how to get their Player Controller. Although it isn't easier to find, there's a rule that states that when you call UGameplayStatics::GetPlayerController( 0 ) it always returns your Player Controller.

So if you're running a server, GetPlayerController( 0 ) returns the Player Controller of the server. If you're running a client, GetPlayerController( 0 ) returns the Player Controller of that client (remember that clients only know their Player Controller, so they can't access any other).

If you're running a dedicated server (i.e. pure server without a local client), then GetPlayerController( 0 ) will return the first client.

HUD

Picture
The HUD (AHUD) is an object that is automatically spawned per player, and added to their Player Controller. Although you can use it for low level things (e.g. drawing text on screen), it is mostly used for debugging purposes. You can think of it as Unity's immediate mode UI.

UMG Widgets

Picture
If HUD is the immediate mode UI, the UMG is the new default UI system in UE, which has more complex elements (e.g. labels, text fields). Thankfully, the engines are getting away from scaleform (which I'm not a fan), and UMG is very similar to Unity's new UI system (specially the anchor system which I'm a fan).

As of 4.7.6, UE still has some issues when spawning the HUD at the start, so what I advise for now is that before you spawn any UMG widgets, add a delay (e.g. 0.2s) to let UE properly initialise stuff before the widgets are created.
13 Comments

Getting into Unreal Engine 4

4/7/2015

6 Comments

 
I've been working with Unity since 2005, and recently started doing a prototype in UE4. So this post is meant to help people like me that either have experience in Unity or are simply new to UE4.

It doesn't make sense for me to go into the differences/similarities between Unity and UE, since this article already does a good job explaining them.

Scene Component

The one thing that it took me a long time to find out it existed (didn't see it in any docs at the time) was the Scene Component. This component is very useful, and it's name is very misleading (IMO it should be called Anchor or Transform Component. It basically allows you to offset components internally when you're building your Blueprints (BPs), which is something that you just do naturally in Unity by chaining GameObjects.
Picture
Keep in mind that in the World Outliner it will still show up as a flat object since they are Components, unlike in Unity. To actually chain them like that your option is Child Actor Component, since that's the one that uses Actors (which are the only things that can be placed in the world).

Use Blueprints

Speaking of which, I highly advise you to start doing things in BPs. As a programmer I've always been skeptical about these kinds of tools, but I have to say that BPs have far exceeded my expectations.
The main reason why I suggest starting with BPs is because IMO the worst part from UE so far is that its API shows it's age.

Finding things in UE most of the times (specially when you're starting to use it) is very cumbersome. I'm used to Unity's API, which is pretty intuitive. For example, if I want to open a new level I just think about "who should open the level" and it leads me to think about the Application class. In UE, for example, it is in UGameplayStatics class, which kind of looks (from it's class hierarchy) like a class that was created to expose common useful things to BP.

Another example is raycast, which in Unity you just think about "I want to cast a ray, let me search the Physics class", and in UE it is in the UWorld. And a lot of times figuring this thing out just takes too long, because usually the oficial documentation shows you how to do it in BP.

Try to Use Windows

This one pains me to say, but unfortunately I'd recommend you use Windows. ATM (4.7.4) UE still has some sluggishness in the editor - and some crashes - that seems related to input on OS X (which I've been told should improve with 4.8). The experience in Windows is far smoother.

The other big problem is that OS X only allows you to build for OS X and iOS, which is a big let down for me. One of the big pros of Unity is that I can just build it to whatever platform I want from any OS (the only exception was iOS which forced you to build from OS X).

Besides that, I have to say that they are pretty much always behave the same on both platforms. Initially I was seeing some weird behaviours which I naturally assumed it was from the OS X version only, but turned out that they were bugs present in Windows too.

However, that being said, I've been using OS X for most of it because so far I've been focusing in BP, which only require you to use the Editor. The problem comes when you try to go into C++ land, which has a horrible support in Xcode (e.g. you can't do simple things like refactor a function name).

So if / when you're going to use C++, I'd advise you to go with Windows.

Extending The Editor

I have to say that I haven't delved into this one yet, but from what I looked at it, it is far more complex to start using than in Unity, which tbh is a shame (specially given how Unity is so easy and I've used extensively).

Eventually I'm going to step into it, and I'll post some thoughts.

Network Ready

I'd have to say that probably this is the biggest thing for me (from my programmer view), network is very built into UE. It is very easy to get networking stuff working, specially if you want to have characters moving around.

However, not everything is roses. You're going to get into a lot of issues which IMO comes from 2 things: UE gameplay framework (which you'll have to learn and get used to), and dated APIs.

It's clear that UE is still not fully revamped, and in some areas this is quite apparent. In the next post I'll try to put out some hints about what issues and solutions you may come across when developing a networked game.
6 Comments

    Author

    Nuno Afonso
    Game & Tools Developer

    Archives

    April 2015

    Categories

    All

    RSS Feed