ab https://alexandrebruffa.com/ Thu, 01 Feb 2024 02:41:53 +0000 en-US hourly 1 https://wordpress.org/?v=6.4.3 https://alexandrebruffa.com/wp-content/uploads/2022/04/cropped-cropped-elior-favicon-270x270-1-32x32.png ab https://alexandrebruffa.com/ 32 32 Debug Your GameLift Game Server Like a Pro https://alexandrebruffa.com/debug-your-gamelift-game-server-like-a-pro/ https://alexandrebruffa.com/debug-your-gamelift-game-server-like-a-pro/#respond Thu, 01 Feb 2024 02:39:56 +0000 https://alexandrebruffa.com/?p=1886 Based on your feedbacks and comments, I show you how to debug your GameLift game server!

The post Debug Your GameLift Game Server Like a Pro appeared first on ab.

]]>
This article was initially published on my Medium Page.

Lately, I have published a series of articles and videos about creating a real-time multiplayer game with Unity3D and Amazon GameLift. The feedback I received about them had been outstanding: a lot of developers downloaded my source code and made their own projects and games using Amazon services.

I received many messages and e-mails asking me for help as well. Let’s be honest: the architecture of a real-time multiplayer game that I always suggest is simple but contains a lot of distinct elements working together like the cogs in a well-oiled machine. A simple mistake and the whole architecture will fail. Furthermore, GameLift can sometimes be unfriendly; I personally had some hard times when trying to find the cause of an error or bug.

In this post, I will explore the common errors people have experienced and how to debug a GameLift game server.

Do you prefer watching a video instead of reading? Here you have:

5 Common Errors To Avoid

This is the architecture of a real-time multiplayer game I always suggest in my videos and articles:

And those are the 5 common mistakes related to the architecture I could identify:

1. AWS SDK for .NET

Numerous people asking me for help had trouble connecting to the Lambda function from Unity. Remember that Unity uses .NET Standard 2.1, and the Amazon documentation recommends downloading the AWS SDK for .NET here for Unity. If you download the wrong version or download it from elsewhere, some Amazon services won’t work correctly, including the Lambda calls.

Unity project settings

2. Multiple Unity Desktop Clients

In my code, I have included a mechanism to avoid consuming the game server resources if the users minimize the application using the Unity functions OnApplicationFocus and OnApplicationPause. Some of you were trying to launch multiple Unity desktop clients and experienced server disconnections in the out-of-focus clients. In this case, please comment both functions or add a conditional compilation for the Unity editor in the AppController class.

3. Client Proxy / Firewall / VPN

The connection between the Unity client and the game server is established thanks to the TCP and UDP networking. Ensure you don’t have any software or system that could block your TCP and UDP ports, like a proxy, firewall, or VPN.

4. Memory Provisioning for Lambda

I have been told that for the first connection after a long time to the Lambda function, an error is returned, and the player can not join the game. This is totally “normal”: this phenomenon is known as a cold start.

According to the cloud experts PluralSight, “A cold start occurs when an AWS Lambda function is invoked after not being used for an extended period of time, resulting in increased invocation latency.”. A Lambda function has a default timeout of 3 seconds; an error is returned if the execution time exceeds the function timeout.

To solve this slow invocation issue, Amazon recommends over-provisioning your Lambda function memory instead of the timeout to avoid unexpected costs.

Lambda function configuration

5. GameLift Launch Path

Before creating your GameLift fleet, you need first to upload to GameLift a compressed archive (zip file) containing your Realtime script and dependencies. During the fleet creation, you will be asked for the launch path, in other words, the path of your Javascript code file within the zip file. For example, if you have no dependencies and have compressed the Javascript file directly, the path will be file.js. If you have compressed a folder containing your Javascript file and dependencies, the path will be folder/file.js.

Launch path during fleet creation

if you want more insights about the Realtime script, please check my post about it:

Debugging a GameLift Game Server

Suppose that your Unity client runs great, and your Lambda function is called correctly, but a new game session can not be created, probably due to an error in GameLift. The first thing you must check is whether your game server is running correctly, thanks to the GameLift events and metrics.

Events & Metrics

In the GameLift console, click on your fleet and go to the Events section. This section collects all the log entries describing an event that involves GameLift resources. The GameLift documentation says the following: “In addition to tracking activity, event codes and messages can provide additional information for troubleshooting and debugging problems.”

Events section

If your fleet is running correctly, you should see the following main events showing up in this specific order: FLEET_CREATED, FLEET_STATE_VALIDATING, FLEET_STATE_ACTIVATING, FLEET_STATE_ACTIVE, FLEET_SCALING_EVENT.

Fleet creation events flow

If you see critical messages like SERVER_PROCESS_TERMINATED_UNHEALTHY during the fleet creation, something may be wrong with either the launch path (see previous section) or your Realtime script (wrong syntax or broken dependencies).

The last message of the successful fleet creation is a scaling message, meaning that your fleet has automatically scaled up, launching a new EC2 instance. If you go to the Metrics section, you can visualize it:

Your game server is running correctly!

Game Session Logs

Now, suppose that your game server is running correctly: your fleet has scaled up, and no critical messages have shown up during the fleet creation. You are able to execute multiple Unity clients at the same time, and the multiplayer feature works great. However, in some cases, you notice that for some actions you perform in the Unity client, your game server does not have the expected behavior and can even crash. Something is failing in your Realtime script, and you want to check the value of certain variables at a precise moment in time.

There is a simple workaround: you can write into the game session logs and then access them to see what happened.

Writing into the game session logs

Do you remember my previous article about talking with NPCs?

I will add a few lines of code in the Realtime script: when a player starts to talk with an NPC, I will write information into the game session logs. According to the GameLift documentation, there are 6 levels of server log messages; let’s try with 3 of them: info, warning, and error.

We have written into the game session logs; now, let’s access them!

Accessing the game session logs

This part is a little bit tricky. As described in the GameLift documentation, when a game session finishes, the related logs are stored in an S3 bucket. There is no simple way to access those logs; the only way to achieve it is by using the GetGameSessionLogUrl API call to get the location of the logs. I will implement the API call in a Lambda function. I’m a Python guy so I will do it with Python, but it’s up to you to use your favorite language!

Remember that Lambda includes boto3, the official AWS SDK for Python, perfect! Checking the documentation of the boto3 function get_game_session_log_url, we can figure out that the function requires a parameter called GameSessionId, described as “A unique identifier for the game session to get logs for.”. There is a slight confusion with the boto3 documentation and, more generally, with the whole Amazon documentation: we need the game session ARN, not the game session ID.

Game session ID and ARN

Building the Lambda function

Now we can write the function:

Before executing the function, we need to give the Lambda function the necessary permissions to access the game session logs. Go to the Lambda function role and add the following policy:

Reading the logs

Now, let’s execute the function! The answer will return a pre-signed URL of the location of the logs for the specific game session:

Note that a pre-signed URL is temporary: in this particular case, the URL is valid for 15 minutes after the request. Visit the URL with your favorite internet browser and download the logs. Our messages can be visualized!

game session log file

Final Thoughts

Thanks for reading this post until the end! I really hope it helped you troubleshoot your real-time multiplayer game and understand more deeply how the game session logs work.

If you have any feedback or questions, feel free to reach out to me on my social networks:

🎬 YouTube Ⓜ Medium 🌐 Website

See you in the next post!

The post Debug Your GameLift Game Server Like a Pro appeared first on ab.

]]>
https://alexandrebruffa.com/debug-your-gamelift-game-server-like-a-pro/feed/ 0
Enhance Your Real-time Multiplayer Game with Generative AI (Bedrock)! https://alexandrebruffa.com/enhance-your-real-time-multiplayer-game-with-generative-ai-bedrock/ https://alexandrebruffa.com/enhance-your-real-time-multiplayer-game-with-generative-ai-bedrock/#respond Fri, 12 Jan 2024 03:25:07 +0000 https://alexandrebruffa.com/?p=1864 Can an NPC be smart? In this post, I show how to enhance a real-time multiplayer game with AI.

The post Enhance Your Real-time Multiplayer Game with Generative AI (Bedrock)! appeared first on ab.

]]>
This article was initially published on my Medium Page.

Can an NPC be smart? What about having a real conversation with an NPC? You may have watched those incredible videos of gamers talking with AI NPCs. Can it be done with Unity3D and Amazon services? Let’s see!

Check my video to learn how to do it:

Preamble

Lately, I have published a series of articles and videos about building a real-time multiplayer game with Unity3D and Amazon GameLift.

I also entered the AI field and produced content about integrating Unity3D and AI services: ChatGPT, Dall-E, and Amazon Bedrock.

On my video about Amazon Bedrock, a clever follower left this comment:

What an outstanding idea! Technically, it would be a perfect mix between my work about Amazon GameLift and the one about Bedrock. Thanks for the idea, bro; let’s do it!

About NPCs

A non-player character (NPC), as its name indicates, is a character that is not controlled by a player but can eventually interact with the real players of a game. Therefore, every action or decision taken by the NPC is server-managed. The flow is the following:

  1. A player interacts with an NPC; the player notifies the game server.
  2. The game server processes the information and eventually connects to other services (Database, AI, etc. )
  3. The game server sends an answer to all the players, and Unity clients are updated.

General Architecture

The architecture of this project contains 3 main parts:

  1. A simple architecture of a real-time multiplayer game implicating the services Cognito, Lambda, and GameLift.
  2. A Lambda function that calls the generative AI service Amazon Bedrock.
  3. A connection between the GameLift’s game server and the Lambda function.

For the first two parts, please refer to the following articles and videos: Building a Real-Time Multiplayer Game With Unity3D and Amazon GameLift and Generative AI With Amazon Bedrock and Unity3D. This article will focus on how to invoke a Lambda function from a GameLift’s game server.

Accessing AWS Resources From GameLift

We want the game server to access another AWS resource here, Lambda. The classical way to do it would be to create a role with associated policies to allow GameLift to invoke a specific Lambda function. But this is an uncommon case and requires an extra step. The GameLift documentation says you can achieve doing the following:

  1. Set up an IAM service role for Amazon GameLift.
  2. Associate the service role with an Amazon GameLift fleet.
  3. Add code to your game server to assume the service role.

So, why this extra step? Remember that GameLift game servers are actually composed of one or various EC2 instances (fleet); therefore, we must associate a role to the fleet and also to the EC2 instance where the game session is running. After that, we can invoke our Lambda function from the game server.

It’s not so straightforward, so fasten your seatbelt, and let’s start!

The IAM role

The new role we are creating will allow GameLift to access other resources. To do so, we select GameLift as a trusted entity when creating the role.

By default, an AWS-managed policy called GameLiftGameServerGroupPolicy is attached to the role. We create a new policy to allow access to the Lambda function and attach it to the role.

Okay, so we have the role ready; we can attach it to a new GameLift fleet. But don’t create the fleet yet! We need to work on the Realtime script and dependencies first.

The Realtime Script

This is the spicy part. The role we have created is assumed by the GameLift fleet, but as mentioned before, we also need to assume the role from the Realtime script. Realtime servers use Node.js and JavaScript, so we will use the AWS SDK for JavaScript.

For some reason, I could not use the AWS SDK for Javascript version 3; it made my game server crash. I used the AWS SDK for Javascript version 2 instead, and everything worked like a charm. If you could achieve it with version 3, please reach out to me!

First, we need the game server to assume the role we have created. In the init function of the Realtime Script, we call the STS service and assume the role:

Notes:

  • We call the function assumeRole as specified in the STS documentation

As indicated in the STS documentation, the response has the following structure containing credentials:

Thanks to the credentials, we can now call our lambda function:

Notes:

  • We call the Lambda constructor thanks to the credentials returned by STS, as specified in the documentation.
  • We invoke the Lambda function (in my case npcFunction), as specified in the documentation.

To get more details about how the Realtime script works, please refer to this previous article:

The Dependencies

In the previous section, we worked with the AWS SDK for JavaScript in the Realtime script. Small but very important detail: the AWS SDK for JavaScript is not installed on the game server! Good news: we can upload the dependencies along with the Realtime script. Therefore, we will follow those steps:

Install Node.js in your local environment.

First, go to the Node.js from the official website. Select the operating system running on your local machine and install Node. Once installed, open a new terminal (or command prompt) and type “node”. You should be able to enter the Node console:

Install the AWS SDK for Javascript

In a new terminal, go to the folder containing your Realtime script and install the AWS SDK for Javascript version 2 thanks to Node’s package manager, NPM:npm install aws-sdk

Once installed, 3 new items have been created: the package.json and package-lock.json files and the node_modules folder.

Wrap the script and the dependencies

Zip the folder containing the Realtime script and the dependencies (4 files in total), and go to the GameLift console. In the script section, create a new script and select the zip file.

🚨 Houston, we have a problem: our zip file is too big! The reason is the following: AWS SDK for Javascript version 2 is not modular, so we had no choice: we have installed and zipped the whole SDK (12 MB). With the AWS SDK for Javascript version 3, we could have installed only the services we need (STS and Lambda), and this would have resulted in a lightweight zip file (2–3 MB).

Hopefully, another option is available: hosting our zip file in an Amazon S3 bucket. This is our updated architecture:

Create an S3 bucket and a related role

Create a new S3 private bucket and upload the zip file.

In the IAM console, create a new role with GameLift as a trusted entity and attach a policy that allows the private bucket and its content to be read:

Upload the script and the dependencies to GameLift

Come back to the GameLift console! In the script section, create a new script, but this time, select the zip file from S3 and the role we have just created:

GameLift can now access your Realtime script and dependencies during fleet creation through an S3 bucket.

Creating a new Fleet

When creating a new fleet, in the additional details section, indicate the role we have created at the beginning.

You will be asked for the Realtime script. Select the script you have created before, and in the Runtime configuration section, indicate the script’s path. Remember that we have zipped a folder containing the script; therefore, the path will be folder/script, in my case, GameLift/Multiplayer.js.

The Unity Client

The NPC

As I mentioned in other posts, I’m not a modeler or a 3D artist; therefore, I always look for free assets for my projects. The characters I’m using for this project, like the previous ones, are from the website Mixamo. This time, I looked for something different for the NPC and found this great Moai model on free3D.com. OBJ format is compatible with Unity, perfect!

Moai on free3D.com

The events

For this project, I added 4 new events related to the NPC:

  • PLAYER_MEETS_NPC: A player notifies the game server that he wants to interact with the NPC. If the game server allows it, the same event is sent back to all players.
  • PLAYER_TO_NPC: The player can now interact with the NPC; he can send this event along with a message.
  • NPC_TO_PLAYER: The game server sends a message back to the player.
  • PLAYER_LEAVES_NPC: The interaction ends, and all players are notified.

Final Result

This is the final result of one of the characters interacting with Moai; it looks pretty cool!

Closing Thoughts

Weeks ago, I had the opportunity to share my knowledge as a speaker at the AWS UG Peru Conference 2023. One of the attendees asked me: “What is the advantage of using GameLift over another similar service like Photon?”. My answer was the following: using GameLift, YOU build the cloud architecture of your game, and therefore, you can do absolutely what you want. You could, for example, connect your game to an AI service, a database, a notification system, etc.

And that is totally what I meant with this article: accessing AWS Resources from a GameLift game server opens the door to infinite possibilities! The implementation was a little bit complex, but hey, it is totally worth it!

Resources

Here are the resources mentioned in the article:

I also used free Mixamo characters and a model from free3D.com.

The post Enhance Your Real-time Multiplayer Game with Generative AI (Bedrock)! appeared first on ab.

]]>
https://alexandrebruffa.com/enhance-your-real-time-multiplayer-game-with-generative-ai-bedrock/feed/ 0
My First Experience as a Speaker in an AWS Conference https://alexandrebruffa.com/my-first-experience-as-a-speaker-in-an-aws-conference/ Thu, 19 Oct 2023 16:30:28 +0000 https://alexandrebruffa.com/?p=1859 I had the incredible opportunity to participate in the AWS UG Peru 2023 Conference as the speaker. I share my experience in this post!

The post My First Experience as a Speaker in an AWS Conference appeared first on ab.

]]>
This article was initially published on my Medium Page.

Last Saturday, I had the opportunity to share my knowledge as a speaker at the AWS UG Peru Conference 2023. It was a wonderful experience; I will share it in this post.

Promotional banner for my talk

An Event Huger Than Expected

When I postulated to be a speaker at this conference, I totally underestimated the event’s magnitude. 4500 registered persons, 2300 attendees, and more than 100 speakers in just one day making it one of the biggest AWS events in Latin America. It was impressive!

4 floors of the PUCP Cultural Center in Lima were full of AWS enthusiasts attending highly diverse talks and participating in activities, workshops, and contests; an El Dorado for any cloud lover!

Speakers from all over the Americas shared their knowledge in various languages. I chose to speak Spanish to feel more comfortable and answer the audience’s questions easily.

My name and picture on the banner of the Nazca conference room
My name and picture on the banner of the Nazca conference room

A Risky Talk

For my talk, I chose to make a live demo of a real-time multiplayer game created with Unity3D and Amazon GameLift. Undoubtedly a bold bet since this live demo required multiple fully operational Unity clients, some Amazon services running on the cloud, and an excellent internet connection. If one of those components did not respond as expected, it would have been a total failure!

Following my fellow AWS CB Diana Alfaro’s wise advice, I recorded the whole demo the day before the conference. In the worst case, I would have shown a video to the audience. Maybe not the ideal scenario, but it would have saved the day.

Hopefully, the internet of the PUCP Cultural Center could handle thousands of simultaneous connections with a high bandwidth; perfect! I could make my demo without experiment any inconvenience.

3 Unity clients running on 2 devices

A Great Audience

I will be honest; for this talk, I was expecting a cloud veterans audience, but the title of my talk attracted the curiosity of young people interested in video game creation, and the result was awesome! I’m aware that the content I’m producing through my posts and videos may be uncommon, and I was so thrilled that so many people came to see my talk!

The spectators paid a lot of attention and asked me questions about GameLift, Unity, and game development in general. A lucky guy in the first row could even participate in the demo: I let him play with one of the Unity clients running on a mobile device while everybody could see it on the projector screen.

Overview of the audience
My family also came to see me ❤

Final Thoughts

It was an incredible experience, and I hope to be part of the AWS UG Peru Conference next year as a speaker and as a member of the organization’s staff.

My talk was not recorded, but I created a video summarizing the Q&A section.

The post My First Experience as a Speaker in an AWS Conference appeared first on ab.

]]>
Generative AI With Amazon Bedrock and Unity3D https://alexandrebruffa.com/generative-ai-with-amazon-bedrock-and-unity3d/ Thu, 19 Oct 2023 16:08:19 +0000 https://alexandrebruffa.com/?p=1855 Have you heard about Bedrock, the new generative AI service from Amazon? Let's build a cool AI chat with Unity3D and Amazon Bedrock!

The post Generative AI With Amazon Bedrock and Unity3D appeared first on ab.

]]>
A few days ago, Amazon made a big announcement: the service Bedrock was finally released.

If you missed the news, here it is: Amazon decided to enter massively into the generative AI field and invested in the company Anthropic for $4 billion in order to compete with popular AI services like ChatGPT, Dall-E, MidJourney, etc. The first proposal of Amazon is Bedrock, a fully managed AI service that offers multiple foundational models such as Claude, Jurassic, and Stable Diffusion XL, among others.

In my previous articles, I created Unity3D applications communicating with ChatGPT and Dall-E. Let’s do the same with Bedrock!

Do you prefer something more interactive instead of reading? Check my video!

General Architecture

Here is the general architecture of our application:

We use 3 Amazon services:

  • API Gateway to create, expose, and consume endpoints.
  • Lambda to receive the client’s requests and communicate with Bedrock.
  • Bedrock to generate answers based on the client’s prompts.

If you want to get further adding a login mechanism with Cognito, please refer to my previous article:

Bedrock

First, we have to enable the foundational models we want to use. By default, all the models are disabled. Go to the Bedrock console and enable the models you will use in the model access section. If you have an updated payment method, activating the models only takes a few minutes.

Model access section in the Bedrock console

If you don’t enable the models in the Bedrock console, you will receive this error in Lambda:

An error occurred (AccessDeniedException) when calling the InvokeModel operation: Your account is not authorized to invoke this API operation.

Lambda, Boto3 and Bedrock

If you follow my work, you know I’m a Python guy, so I will use the Python SDK for AWS, Boto3. Good news: Bedrock is available on Boto3; bad news: Lambda runs an old version of Boto3 in which Bedrock does not exist yet.

💡 Here is a workaround: creating a new Lambda layer with an up-to-date version of Boto3. This is how to do it:

  1. In PyCharm, create a new project and install boto3 in a new virtual environment. Boto3 and all the dependencies will be installed.
PyCharm project

2. Go to the venv folder of your project and copy the lib folder into a new folder called python. Then, zip it.

venv folder

3. Go to the Layers section of the Lambda console and create a new layer. Upload the zip file we have created before and choose the same Python version as your local Python virtual environment for the runtime.

Creating a new Layer

The Lambda Functions

We create 2 Lambda functions, one for text generation and the other one for image generation, both with the same version as previously for the runtime (In my case, Python 3.9), and we add the layer we have created before.

Adding a new layer to the Lambda function

The text generation function

For the text generation, I use the Claude model and implement it as described in the Amazon documentation.

The image generation function

For the image generation, I use the Stable Diffusion XL model and implement it, as described in the Amazon documentation.

Note that the model IDs can be found in the Bedrock documentation.

The Lambda Policy

In order to allow Lambda to invoke a Bedrock model, we create a new managed policy and add it to the Lambda functions roles:

API Gateway

In the API Gateway console, we create a new REST API with 2 resources: image and text. Each resource has a post method integrating with the Lambda functions we have created before.

API resources

When deploying the API, you will be asked to create a new stage. After the creation of the stage, the final endpoint will be shown. You will have to use this URL in the Unity client to perform the request.

API stages

The Unity Client

the Unity client allows the user to send a message to generate a text or an image as an answer:

Handling the request

First, we need to create serializable classes to embed the sending and receiving data:

Sending a request in Unity is an asynchronous process. Therefore, we create a coroutine that sends the request to the server:

Dealing with the generated image

If we ask for an image generation, the result sent by Bedrock is a base64 image. To show it on the Unity UI, we must convert it into bytes and create a Texture2D. Then, we assign the texture to the RawImage component of the UI.

Result

Here is the result with text and image generations:

Costs

Let’s check with the AWS Calculator and the Bedrock pricing sheet what our system cost would be for a very pessimistic scenario: you love the app, and you perform 2,000 requests a month. 1,000 for text generation with the Claude model and 1,000 for image generation with Stable Diffusion XL.

  • API Gateway: With 2,000 requests to our REST API, the monthly cost is 0,01 USD
  • Lambda: With 2,000 requests with an average time of 5 seconds and 512 MB of memory allocation, the monthly cost is 0.08 USD.
  • Bedrock: 1,000 text generations by month with a maximum of 300 output tokens and 20 input tokens per request would result, in the worst case, in $0.2204 + $9.804. 1,000 image generations would give us a bill of $18.

Total: The total bill for our system would be approximately 28 USD monthly. It’s quite affordable!

Final Thoughts

Using Bedrock is very intuitive, and integrating it with other Amazon services is absolutely straightforward. The fact that Bedrock is an in-house product makes the integration easier: there is no need for API keys or external requests to make it work, resulting in greater performance and security.

Every code of this article has been tested using Unity 2021.3.3 and Visual Studio Community 2022 for Mac. The mobile device I used to run the Unity app is a Galaxy Tab A7 Lite with Android 11.

Thanks for reading until the end!

Resources

Here is the resource mentioned in the article:

The post Generative AI With Amazon Bedrock and Unity3D appeared first on ab.

]]>
AWS UG Perú Conf 2023 https://alexandrebruffa.com/aws-ug-peru-conf-2023/ Mon, 18 Sep 2023 18:44:00 +0000 https://alexandrebruffa.com/?p=1780 I'm very thrilled to announce that I will be speaking at AWS UG Perú Conf 2023; see you there!

The post AWS UG Perú Conf 2023 appeared first on ab.

]]>
I’m very thrilled to announce that I have been selected to speak at AWS UG Perú Conf 2023. I will make a demo of a real-time multiplayer game created with Amazon GameLift and Unity3D. See you there!

The post AWS UG Perú Conf 2023 appeared first on ab.

]]>
Unity3D + Amazon GameLift: Focus on the Realtime Script https://alexandrebruffa.com/unity3d-amazon-gamelift-focus-on-the-realtime-script/ Mon, 18 Sep 2023 18:28:38 +0000 https://alexandrebruffa.com/?p=1772 In this article, I explain in detail how the Realtime Script works providing an example of implementation.

The post Unity3D + Amazon GameLift: Focus on the Realtime Script appeared first on ab.

]]>
This article was initially published on my Medium Page.

In a previous article, I showed how to build an entire real-time multiplayer game with Amazon GameLift and Unity3D. The process implicates creating game sessions and player sessions with Lambda, guest access to the services with Cognito, and a game server with GameLift.

We could also find out that the game server’s behavior is defined by a script written in Javascript: the Realtime Script. This article will detail how this script works and how to create game server events.

You can also check out the video version of this blog post:

Overview of The Realtime Script

The Realtime Script is a collection of callback functions the game server calls during its lifetime. In other words, we can implement custom behavior for each of these functions. All the callback functions are described in the GameLift documentation; here are the main ones:

  • onStartGameSession(): Called when a new game session is started. In the callback function, we can store relevant information as the game server start time.
  • onPlayerAccepted(): Called when a player is accepted into the game. In the callback function, we can notify the other players that a new player has just joined the game.
  • onPlayerDisconnect(): Called when a player has left or been forcibly terminated. In the same way, we can notify the other players that the player disconnected in the callback function.
  • onMessage(): Called when a player sends a message to the server (i.e., action performed, position, etc.). In the callback function, we can send the new data to the other players.

Furthermore, the game session provides interesting functions such as:

  • getPlayers(): Retrieves a list of players currently connected to the game session.
  • newTextGameMessage(): Creates a new message containing text.
  • sendReliableMessage(): Sends a message to a player.
  • processEnding(): Terminates the game server.

All the game session functions are available in the GameLift documentation.

Creating a Game Server Event

In my previous article, I provided a very basic script making the game server act as a simple “dispatcher”. The game server notifies the players if someone joins or disconnects and resends a message sent by a player to the other players (i.e., action, life update, etc. ).

This time, we will create a non-related player event: a meteorite will fall on the map from time to time. No matter how many players are on the map or what they are doing, this event is 100% managed by the game server.

Our script contains a loop function used to check if the game session should be ended. We will integrate our new server event in the loop function:

We modify the script, adding the new feature in the loop function:

Notes:

You can find the entire code in the resources section of this article ⬇

The Unity Client

In the Unity client, we implement the new event sent by the game server with a countdown and cool VFXs:

It looks awesome! For the meteorite and the explosion, I used assets from the Voxel Arsenal assets. I managed the explosion force field with a Sphere Collider in trigger mode:

Explosion force field

I used the OnTriggerEnter and the CompareTag functions to detect this force on the player. Then, I normalized the differential vector and applied a ratio to it. I found that a ratio of 200 creates a cool visual effect. Finally, I applied the AddForce function to the player’s Rigidbody:

Final Thoughts

At first glance, the Realtime Script can be complex and challenging to understand, but once you master it, you have total control over the game server’s behavior and can do absolutely what you want! Meteorites, snow, rain, sunshine, real-time updating environment, non-player characters, etc. The only limit is your imagination!

In the resources section, I provide a Unity package of the game I showed in the demo. The meteorite and explosion assets are not included because of the license type.

You are free to use all the resources I provided in this article. Please ping me if you use them to build your game; I would be delighted to see the result!

Resources

Here are all the resources mentioned in the article:

For the demo, I’m using the Voxel Arsenal assets.

The post Unity3D + Amazon GameLift: Focus on the Realtime Script appeared first on ab.

]]>
Detecting Unsafe Content With Unity3D and Amazon Rekognition https://alexandrebruffa.com/detecting-unsafe-content-with-unity3d-and-amazon-rekognition/ Wed, 19 Jul 2023 17:31:08 +0000 https://alexandrebruffa.com/?p=1769 Is my profile picture suggestive? In this article, I show how to detect unsafe content thanks to AWS Rekognition and Unity3D.

The post Detecting Unsafe Content With Unity3D and Amazon Rekognition appeared first on ab.

]]>
This article was initially published on my Medium Page.

If you prefer watching a video instead of reading, here you have:

My Brief Journey on TikTok

Weeks ago, I finally decided to download TikTok. I download the app and create a new account. The first thing I always do just after registering on a social network is upload a profile picture. Strangely, TikTok did not let me do it. I tried two more times the same day, but I had no success. After that, I also tried to add friends and change my username, but still no success. I waited for a couple of days, I reopened the app, and I got this message:

Permanently banned message in Spanish.

I have been permanently banned from TikTok, and I don’t know why! Then I started to think. What did I do wrong? I did not post any publications or messages. I used a valid email to register, entered my real name, and tried to upload a real picture of me. I don’t believe my email and my name are a problem. What about my profile picture? Did TikTok detect it as inappropriate? Is it because I have no hair? 👨🏻‍🦲 How to find it out?

The System I built

Then I remembered that Amazon has a service for unsafe content detection: Rekognition; let’s try it! Additionally, you may remember this previous article of mine where I created a chat in Unity showing images from Dall-E. I will reuse the interface for this article.

This is how it works:

  • The Unity client login thanks to Cognito User Pool.
  • The client uploads then a picture to S3.
  • Finally, the client calls a Lambda function that works directly with Rekognition to define if the picture contains unsafe content.

Amazon Services

➡ About Cognito, I created an authenticated access using a User Pool coupled with an Identity Pool. A policy attached to the authenticated role of the Identity Pool allows users to access S3 (PutObject) and Lambda (InvokeFunction). If you want to know in detail how to do it, please check this previous article of mine:

➡ The S3 Bucket is private, so nobody but the authenticated users can access it. I called it censorimagesbucket.

➡ I wrote the Lambda function in Python:

Notes:

  • I used boto3, the AWS SDK for Python, to connect with Rekognition.
  • I used all the Rekognition’s top-level category moderation labels. My face may be offensive in many ways; we never know.
  • I used Rekognition’s DetectModeration API thanks to the detect_moderation_labels function and the S3Object parameter.
  • I used the very cool Pythonic any function.

Don’t forget to attach to the function’s role a policy allowing access to Rekognition and S3:

Unity

The connection between Unity3D and Amazon services is done through the AWS SDK for .NET, as described in my previous article. However, the function invocation is different this time because we have to send the filename to Lambda. We do it thanks to the Payload parameter.

Result

I performed three tests: one with a picture of Bibi, my daughter’s favorite teddy bear, a picture of a girl wearing a bikini, and a picture of myself.

It’s working great! The only unsafe content (the girl in a bikini) has been filtered successfully, and the following moderation labels have been detected:

The result is very accurate, with high confidence rates.

Conclusion

Apparently, my face is not unsafe content! I still don’t know why I have been permanently banned from TikTok, but thanks to this misadventure, I had the opportunity to discover Amazon Rekognition and realize an implementation with Unity3D.

All ids and tokens shown in this article are fake or expired; if you try to use them, you will not be able to establish any connections.

Every code of this article has been tested using Unity 2021.3.3 and Visual Studio Community 2022 for Mac. The mobile device I used to run the Unity app is a Galaxy Tab A7 Lite with Android 11.

Resources

Here are all the resources mentioned in the article:

The post Detecting Unsafe Content With Unity3D and Amazon Rekognition appeared first on ab.

]]>
Connecting Unity3D With AWS Services https://alexandrebruffa.com/connecting-unity3d-with-aws-services/ Tue, 18 Jul 2023 21:27:55 +0000 https://alexandrebruffa.com/?p=1760 In this article, I will show 3 ways of connecting Unity3D with Amazon Services: using an IAM user, a guest access, and an auth access.

The post Connecting Unity3D With AWS Services appeared first on ab.

]]>
This article was initially published in the AWS Community Builders’ dev.to.

In my last articles, I realized direct integrations between Unity3D and AWS using the AWS SDK for .NET. I generally don’t dive into details about how the connection between Unity3D and the AWS services is made in order to focus on the primary topic. Still, it deserves a whole article because it’s not that simple!

There are many ways to access AWS resources from Unity. In this article, I will summarize three of them: using an IAM user, using a Cognito guest user, and using a Cognito authenticated user.

General considerations: For this article, we will use the AWS SDK for .NET. Since Unity uses .NET Standard 2.1, you will need the .NET Standard 2.0 assemblies available here and unzip the file in your Unity project’s Plugins folder. Since we will perform asynchronous calls, you will also need the AsyncInterfaces package.

If you prefer to watch a video instead of reading this article, here you have!

1. Using an IAM User

Suppose you want to allow a specific user (i.e., a third-party app) to upload files to one of your S3 buckets. However, you only want to give programmatic access without implementing a signup or login flow. Using an IAM user is a perfect fit in this case.

Let’s simulate the process:

– In the S3 console, create a new S3 private bucket. I will call mine awsresourcesbucket.

– In the IAM console, create an IAM user with programmatic access and create a new Access Key; you will be given an Access Key and a Secret Access Key. Once created, don’t forget to copy the Secret Access Key. It is shown just one time!

– Attach a new policy to the IAM user. The policy gives the required permissions to write into the S3 bucket.

– In Unity, build an S3 Client thanks to the IAM user’s Access Key and Secret Access Key, and upload the file.

Comments about the above code:
– We use the NativeGallery package to pick an image from the device.
– We use the PutObjectAsync function as described in the AWS documentation.
– The function UploadFileAsync is asynchronous; you can call it with the await operator inside an async function.

2. Using a Cognito Guest User

You may remember my last article, where I built a real-time multiplayer game with Unity3D and Amazon GameLift. The Unity client calls a Lambda function to start playing, and we want that everybody who has downloaded the game can play without being logged in. You can achieve it using guest users of a Cognito Identity Pool.

Let’s simulate it:

– In the Lambda console, create a simple Lambda function returning a dummy value (I will call it `awsResourcesFunction`). I will do it in Python, but it’s up to you to choose your favorite programming language.

– In the Cognito console, create a Cognito Identity Pool with guest access. During the Pool creation, you will be asked to create a new guest role; I will call them respectively awsResourcesIdentityPool and awsResourcesCognitoRole.

– Once the Identity Pool is created, enter the guest role and attach a new policy. The policy gives the required permissions to invoke the Lambda function we have created before.

– In Unity, we first build the AWS Credentials thanks to the Identity Pool ID and then the Lambda Client with those credentials.

Comments about the above code:
– The AWS documentation indicates that the function InvokeAsync has been deprecated, but remember that we are using the .NET Standard 2.0 assemblies, so it’s valid for us!
– The InvokeAsync function is asynchronous; you can call it with the await operator inside an async function.

3. Using a Cognito Authenticated User

Now imagine that you want to allow the players of your game to upload a profile picture, but you require a login to do it. This case is a bit more complex because your game will handle guest and authenticated users. You can achieve it by creating a User Pool and adding authenticated access to our Identity Pool.

Let’s try:

– In the Cognito console, create a new User Pool. You also be asked to create an Application Client during the User Pool creation. Don’t forget to enable the ALLOW_USER_PASSWORD_AUTH as authentication flow.

– For this example, we assume we already have a user registered and confirmed. Please take a look at this article of mine to learn how to do it.

– Then, go back to the Identity Pool we created before, click on “Add identity provider” of the Authenticated access section, choose “Amazon Cognito User Pool”, and link the Cognito User Pool we have created previously.

– Go then to “Edit role”, create a new role, and attach a new policy to the role (or you can reuse the policy we created for the IAM User). The policy gives the required permissions to write into the S3 bucket.

– In Unity, we first login to the Cognito User Pool with the user Credentials; a Token ID is returned. Then we build the AWS Credentials thanks to the Identity Pool ID, and we add the login data to the AWS Credentials: the `Token ID` and the User Pool Provider Name. We can finally build the S3 Client with the AWS Credentials and upload a file.

Comments about the above code:

– We log in to the Cognito User Pool thanks to the InitiateAuthAsync function.
– We add the login data to the AWS Credentials thanks to the AddLogin function.
– The Provider Name is the concatenation of the following: cognito-idp + region + .amazonaws.com/ + Cognito User Pool ID.

Final Thoughts

Connecting Unity3D with AWS services is challenging work; I hope that this article could help you!

All ids and tokens shown in this article are fake or expired; if you try to use them, you will not be able to establish any connections.

Every code of this article has been tested using Unity 2021.3.3 and Visual Studio Community 2022 for Mac. The mobile device I used to run the Unity app is a Galaxy Tab A7 Lite with Android 11.

A special thanks to Gianca Chavest for designing the fantastic illustration.

The post Connecting Unity3D With AWS Services appeared first on ab.

]]>
Building a Real-Time Multiplayer Game With Unity3D and GameLift https://alexandrebruffa.com/building-a-real-time-multiplayer-game-with-unity3d-and-gamelift/ Tue, 18 Jul 2023 19:28:27 +0000 https://alexandrebruffa.com/?p=1757 In this article, I explain step by step how to build a real-time multiplayer game with Unity3D and Amazon GameLift.

The post Building a Real-Time Multiplayer Game With Unity3D and GameLift appeared first on ab.

]]>
This article was initially published on my Medium Page.

You are talented with Unity and game creation in general, and it’s time for you to move up a gear by creating a real-time multiplayer game, but you have no idea how to do it, and you know very little about cloud computing. Don’t worry, we will see how to do it step by step.

This article is based on the excellent tutorial by Chris Blackwell. Please take a look at it!

Disclaimer: This is not an article about game design. I will focus on the technical aspect of creating a real-time multiplayer game.

Here is the final result:

Preamble

When one starts to work on a real-time multiplayer game, a lot of questions come to mind:

How can I match the players in one or multiple rooms (game sessions)? How can my players communicate together? How can I achieve to have a very low latency for my game?

Representation of a game server

Short answer: Amazon GameLift.

Amazon GameLift is a managed service for multiplayer games with the following characteristics:

  • It deploys a set of EC2 instances (fleet) for you, so you won’t have to worry about mounting EC2 instances, securing them, etc.
  • It operates the EC2 instances for you: you will never connect to the instances nor install anything. A game server is automatically set up when you run a new GameLift fleet.
  • It scales the service for you. No matter how many users your game is played by, GameLift automatically scales up or down according to the demand.
  • It connects the players through the game server, creating game and player sessions.

The Architecture

We can achieve building a real-time multiplayer game with few components. Here is our architecture:

This is how it works:

  • The client (Unity application on a mobile device) joins the game by calling a Lambda function.
  • The Lambda function indicates GameLift to create a new game session if no game session is available and to create a new player session. The function returns the necessary information to connect to the game server (IP, port, credentials, etc.).
  • The client establishes a new connection with the game server, and the user is ready to play.

Lambda

The Lambda function (Python 3.10) will work directly with GameLift and will have the following behavior:

The origin tutorial exposed a Node.js function, but since I’m a Python guy, I rewrote the function in Python. You can find the whole function in the last section of this article.

Also, the Lambda function needs the following permissions to access the GameLift service: CreateGameSessionDescribeGameSessionDetailsCreatePlayerSession, and SearchGameSessions. You can create a new manage IAM policy with those permissions and add it to the Lambda function role.

You can find the policy at the end of this article.

Cognito

In previous articles of mine, I performed user authentication through IAM users or Cognito User Pools. We don’t need user authentication this time: we will use guest access to avoid any restrictions; everyone who downloads our game can play immediately.

In this opportunity, the Unity client invokes a Lambda function, and the best way to give access to AWS resources without credentials (guest access) is through a Cognito Identity Pool. A Cognito Identity Pool allows both authenticated and guest users, so if you want to enable some authentication feature in the future (for example, linking users’ Facebook or Twitter accounts to save game progress), you could do it easily.

Creating a Cognito Identity Pool with guest access

We must attach the necessary permissions (Lambda Invoke) to the Identity Pool we created. You can edit the guest role associated with the Identity Pool and create a new policy to achieve it. You can find the policy at the end of this article.

GameLift

Before running a new GameLift fleet, we need to elaborate a script that will be attached to the fleet. The first step is defining the behavior of the game server. This is how a game session will be managed:

Based on the above flow, we can write and upload a JavaScript script to GameLift. Then, we can create a new fleet and include our script during the fleet creation. Check the end of this article for the script.

GameLift Script
GameLift Fleet using the script

Before configuring the auto-scaling of your fleet, you need first set limits for it. Imagine that your game has an unexpected success; you don’t want to run out of budget in a few days! In the scaling capacity section, you can set a minimum and a maximum of instances for your fleet:

Scaling options in Amazon GameLift

Now, let’s create an auto-scaling policy. An EC2 instance usually takes one or two minutes to start and can inconvenience the players joining the game. Furthermore, it’s better to start an instance preventively before reaching the player limit:

Auto-scaling policy in Amazon GameLift

You can see how many available instances you have for your fleet here and request a limit increase here if necessary. In my case, I had only one available instance for my fleet (c4.large); the support team gently increased the limit to 15.

Unity

The plugins

We will integrate the Unity client directly with a Lambda function, so we need some AWS classes and functions. In the original tutorial, Chris Blackwell recommends using the AWS Mobile SDK for Unity to achieve it. Unfortunately, the AWS Mobile SDK for Unity has been deprecated, and Amazon recommends now using the AWS SDK for .NET. Let’s see.

In previous articles, I recommended downloading the AWS packages on NuGet.org, the official package manager for .NET. Although it could work, the Amazon documentation recommends doing it here for Unity. Since Unity uses .NET Standard 2.1, download and unzips the .NET Standard 2.0 zip file (it also supports 2.1).

Then, copy the following DLL files to the Plugins folder of your Unity project: AWSSDK.Core, AWSSDK.Lambda, AWSSDK.CognitoIdentity, and AWSSDK.SecurityToken. The Lambda function call is asynchronous, so you also need the Microsoft AsyncInterfaces package.

Unity project settings

Then, we will need an extra plugin to connect to the game server: the GameLift Realtime Client SDK. Go to the GameLift page and download it. Once unzipped, you can figure out this is a whole .NET project. Open the project with Visual Studio and compile it. Five DLL files will be generated: GameLiftRealtimeClientSdkNet45.dllGoogle.Protobuf.dlllog4net.dllSuperSocket.ClientEngine.dll, and WebSocket4Net.dll. Move those DLL files to the Plugins folder of your Unity project.

Plugins folder

Characters and animations

Since I’m not a designer or a 3D modeler, I had to look for a third party who could provide the animations I needed for my Unity project. I found out that Mixamo has a lot of fantastic free characters and animations.

I tried it by downloading the character Remy as an FBX file for Unity and moved it to my Unity project.

Character downloading

It looks good! After that, I downloaded multiple animations to give life to Remy. The animations should be downloaded without skin. We indicate the animation in the editor to use the character’s skin we previously downloaded.

Animation downloading

Then I defined the animations flow inside a new Animator. It looks great!

Animations flow

Building the App

In this section, I will give you some hints about how I built the Unity app. Don’t worry about the code and the project hierarchy! The entire Unity project is available for download at the end of this article.

Character movements

Our character can run, walk back, and rotate. We use the function OnAnimatorMove to have total control over it.

Sending data to the game server

When one starts to build the client, the following question comes to mind:

When should I send data to the game server?

The game server needs to be aware of all actions a player performs to inform the other players, but sending too much information would saturate the game server and burn resources. Remember: don’t send data every frame; otherwise, your game server will die!

I found that data can be sent in those cases: when the player starts and ends any movement (running and walking back), any rotation (turning left and right), and any action (punching, etc.).

If you have played online, you may have experienced the famous “lag,” meaning that what you see is delayed over reality. That can be caused by a slow internet connection or a high-latency game server, but it can also mean the server data must be updated. That is why this is important to “fix” the data occasionally, sending the server updated data. I decided to do it every second in the movement functions.

In red, the player sends updated data to the server.

Player data

For the basic game I made, I used the following data:

Note that the PlayerCoord class has four components: I used this for position or rotation (quaternions).

Costs

Let’s consider the following case: you published a successful FPS game with the following characteristics:

  • Every game session has a limit of 30 players.
  • In the peak hour, your game receives approximately 40 concurrent connections from players located in the United States.
  • Your GameLift fleet uses c4.large Linux Spot instances, and each instance handles a single game server.

Based on the Steam statistics, we can speculate that roughly 35% of the day, a single game server is used versus two games servers in the peak hour:

In red, the number of game servers used

The pricing sheet of Amazon GameLift indicates that a c4.large Linux Spot instance costs $0.07848 per hour, $56.51 per month. We can deduce the following calculation:

Total cost per month = $56.51 x 1.35 ≈ $76.28

GameLift is expensive, but hey, it is worth it! You save time and money instead of implementing your solution and possibly needing help with scaling issues. If you are using GameLift for your game, you should find a way to monetize it (ads, in-app purchases, etc.).

Here are the other costs:

  • Unity: As always, Unity is free. The personal plan is a good fit unless you need specific advanced features for your game.
  • Cognito: There is no charge for Cognito Identity Pools. Awesome!
  • Lambda: The Lambda function is called only once when a new player joins the game. Estimating an exact number of monthly connections is complex, but let’s say 100,000. With 128 MB allocated memory, and each request duration of 500 ms, the cost would be $0.12.

Total: Our real-time multiplayer game bill would be approximately $77 per month.

Final Thoughts

Building a real-time multiplayer game is relatively easy! Amazon GameLift provides all the infrastructure required for this type of application and allows game developers to focus on the visual part.

You are free to use all the resources I provided in this article. Please ping me if you use them to build your game; I would be delighted to see the result!

Resources

Here are all the resources mentioned in the article:

I also used free Mixamo characters and PolyHeaven-free textures.

The post Building a Real-Time Multiplayer Game With Unity3D and GameLift appeared first on ab.

]]>
How SQL Skills Can Boost Your Resume https://alexandrebruffa.com/how-sql-skills-can-boost-your-resume/ Tue, 18 Jul 2023 18:30:00 +0000 https://alexandrebruffa.com/?p=1754 In this article I wrote for LearnSQL.com, I will explain how having SQL skills can boost your resume and your professional career.

The post How SQL Skills Can Boost Your Resume appeared first on ab.

]]>
You may wonder: does having SQL skills matter? In what areas could I use my SQL skills? In this article, I will explain how having SQL skills can boost your resume and add momentum to your professional career.

We are living in the Big Data era. Every time we go online, we provide the websites we visit with a lot of information. If we voluntarily give our data by creating an account, filling out a form, or making a purchase, we give them even more information. All this data is recompiled and centralized in companies’ huge databases. And then what happens to it?

Every department in the company needs this data! If the e-commerce manager wants to monitor the website’s daily conversion, she needs the data. If the company’s country manager needs to create a detailed report of the quarter’s activity, he needs the data. If the marketing team wants to build a remarketing campaign to reengage old clients, they need the data. If the executive board wants to establish strategies for the next years, their decisions will be based on data.

The post How SQL Skills Can Boost Your Resume appeared first on ab.

]]>