Le Blog Amazon Web Services

Comment créer un message du jour dynamique avec AWS Lambda

Un dialogue continu avec vos joueurs est un excellent moyen de les impliquer et de les faire revenir à votre jeu, longtemps après le lancement. En envoyant chaque jour un message à vos joueurs sur les différents supports qu’ils utilisent, vous pouvez les encourager à explorer une nouvelle carte, à équiper une nouvelle arme ou même à effectuer un achat dans le jeu.

Aujourd’hui, nous allons vous montrer à quel point il est simple de créer un système de message du jour dynamique en utilisant AWS. Nous vous guiderons à travers les étapes pour envoyer des messages personnalisés à vos joueurs et qu’ils pourront consulter à la première ouverture de votre jeu.

Pour vous aider à démarrer, nous avons créé un exemple que vous pouvez télécharger et utiliser dans votre jeu aujourd’hui.

A propos du tutorial

Ce système de messagerie est dynamique et varie en fonction du niveau de votre joueur et de la quantité d’or qu’il possède.

Si le joueur est nouveau et qu’il n’a pas amassé beaucoup d’or, le message le dirigera vers le magasin pour qu’il achète la monnaie du jeu afin de prendre un bon départ.

Si le nouveau joueur possède déjà une grande quantité d’or, il lui sera demandé d’acheter une arme à impact supérieur qui pourra l’aider à passer au niveau supérieur plus rapidement.

Si le joueur est déjà à un niveau supérieur, le message lui demandera de rejoindre un duel multijoueur.

Le but de ce système est d’encourager les joueurs à explorer davantage votre jeu en les aidant à découvrir de nouveaux contenus.

Votre jeu doit donc extraire le contenu des messages d’un service central. Ce service doit vous permettre de mettre à jour le contenu et de mettre à jour un algorithme pour choisir le contenu à récupérer.

Une solution basée sur AWS

Ce guide est une introduction aux services AWS. Nous allons construire un système assez simple, mais il fait le lien entre beaucoup de concepts utiles d’AWS.

La conception du système de base utilise Amazon Simple Storage Service (Amazon S3), qui contiendra les différents fichiers texte pouvant être envoyés au lecteur. AWS Lambda, le service de calcul serverless d’Amazon, examinera les données envoyées par votre jeu, décidera quel message le joueur devrait voir, récupérera le fichier texte approprié de S3, personnalisera le message, puis le transmettra au joueur.

 

Phase 1: Configuration d’AWS

Ici, nous nous concentrons sur la configuration AWS pour les services présentés dans la figure ci-dessus. Nous allons passer en revue le code et la configuration effectués dans la console AWS pour configurer un compartiment (bucket) S3, une fonction Lambda et les autorisations appropriées pour permettre aux services de communiquer entre eux.

Tout d’abord, téléchargez l’exemple de projet à partir de GitHub.

Dans le dossier «s3_files» du projet, nous avons inclus des messages prédéfinis qui fonctionnent avec la démo. Dans les étapes suivantes, vous allez créer un compartiment S3, qui est un emplacement nommé pour contenir les fichiers, un peu comme un dossier.

  1. Ouvrez la console AWS et recherchez le service S3.
  2. Cliquez sur « Créer un compartiment » et attribuez-lui un nom unique. Cela doit être unique pour l’ensemble de Amazon S3, pas uniquement pour votre compte. Vous ne pouvez pas changer ce nom alors choisissez judicieusement ! Nous vous suggérons d’utiliser le nom de votre organisation avec la fonction de votre compartiment. Par exemple, nous avons utilisé «motd.amazongametech.com».
  3. Nous vous suggérons de créer toutes les ressources pour cette démonstration dans la même région. C’est généralement ce que vous ferez pour les petits jeux et les services moins critiques.
  4. Il y a beaucoup d’options proposées après avoir choisi le nom. Nous avons laissé tous les paramètres par défaut, mais pour les systèmes de production, vous devrez penser à la journalisation des demandes d’accès et éventuellement à la gestion des versions.
  5. Laissez les autorisations définies par défaut, n’autorisant aucun accès public. Nous donnerons l’accès à une fonction Lambda plus tard.
  6. Cliquez sur le nouveau nom du compartiment dans la liste.
  7. Cliquez sur le bouton ” démarrer “.
  8. Faites glisser tous les fichiers du dossier s3_files dans la boîte de dialogue.
  9. Ne vous inquiétez pas des autorisations pour l’instant, laissez-les simplement avec les valeurs par défaut.

Ensuite, nous devons créer la fonction Lambda qui sélectionnera le bon message.

  1. Accédez à AWS Lambda à partir de la page d’accueil de la console AWS.
  2. Cliquez sur “Créer une fonction ” puis “ Créer à partir de zéro “.
  3. Donnez un nom à la fonction (pour cette démo, il faut que ce soit GetMOTD).
  4. Pour le runtime, nous avons choisi Node.js 8.10, qui est la valeur par défaut, mais il y a beaucoup de choix!
  5. Créez un nouveau rôle à partir des modèles.
  6. Nommez le rôle AccessMOTDBucketFromLambda

Les noms simples et précis sont aussi importants lors de la création de ressources AWS que pour les variables de votre code. Rendez-les faciles à identifier avec des noms très descriptifs. (Vos collaborateurs vous remercieront plus tard.)

  1. Ajoutez le modèle de stratégie «Autorisations en lecture seule des objets Amazon S3», qui autorisera l’accès au compartiment que vous avez créé.
  2. Créez le rôle.
  3. Vous êtes maintenant prêt à créer la fonction Lambda! Dans l’éditeur Lambda, vous pouvez effacer ce qu’il y a dans le fichier et le coller ci-dessous (vous le trouverez également dans le dossier AWS du projet exemple):
var AWS = require('aws-sdk');
var S3 = new AWS.S3();

var motdKeys = {
    newbNeedsGold: "newb_needs_fakegold.txt",
    newbNeedsSword: "newb_needs_better_weapon.txt",
    prodMultiplayer: "multi_player_prod.txt",
    default: "default.txt"
}
var motdBucket = "motd.yourorg.com"; // replace with your bucket name
exports.handler = async (event, context, callback) => {
    var motdKey = motdKeys.default;
    if(event.playerlevel > 10){
        motdKey = motdKeys.prodMultiplayer;
    }
    else {
        if(event.playergold < 100){
            motdKey = motdKeys.newbNeedsGold;
        }
        else {
            motdKey = motdKeys.newbNeedsSword;
        }
    }
    var response;
    await S3.getObject({
        Bucket: motdBucket,
        Key: motdKey
    }).promise().then(data => {
        var motdText = data.Body.toString('ascii');
        motdText = motdText.replace("@playername@", event.playername);
        response = {
            statusCode: 200,
            body: motdText
        };
    }).catch(err => {
        response = err;
    });
    return response;
};

ATTENTION: Lorsque vous codez votre Lambda dans la console, utilisez fréquemment la fonction de sauvegarde ! Si vous êtes déconnecté de la console, il est possible de perdre votre travail.

Notez qu’il existe un nom de ressource unique dans le coin supérieur de la page appelé un ARN (Amazon Resource Name). Vous en aurez besoin dans les étapes ci-dessous, alors prenez note. Cela ressemblera à ceci: “ARN – arn:aws:lambda:us-east-1:0123456789123:fonction:jenny”

Maintenant que la fonction Lambda est prête, nous devons la rendre accessible aux joueurs. Par défaut, elle ne sera disponible que pour le compte administrateur AWS. Pour y parvenir il faudra non seulement créer un rôle IAM avec un accès approprié, mais également associer le rôle à une identité anonyme Amazon Cognito.

IAM (Identity & Access Management) est un système qui dit qui, ou quoi, peut accéder à tout ce que vous créez dans AWS. Un rôle IAM est une description de cet accès.

Vous pouvez donner accès à vos ressources AWS à vos joueurs de deux manières. L’une consiste à créer un nouveau type d’utilisateur dans IAM, y attacher le rôle, puis à générer un fichier d’informations d’identification pour le type d’utilisateur, qui est ensuite distribué à vos lecteurs. Cependant, ce n’est vraiment pas la meilleure pratique. Il est assez fragile et facile d’invalider par inadvertance des informations d’identification ou d’expédier les mauvaises.

La deuxième méthode recommandée consiste à utiliser un pool d’identités Amazon Cognito permettant des identités non authentifiées. Cette solution utilise le système d’authentification Amazon Cognito pour permettre aux utilisateurs qui ne se sont pas connectés d’accéder aux ressources spécifiées via les rôles IAM. Cela peut sembler compliqué, mais c’est en fait assez facile à coder et beaucoup plus sûr que d’envoyer des identifiants. Pour faire cela :

  1. Accédez à la console Amazon Cognito.
  2. Cliquez sur « Gérer les groupes d’identité». ».
  3. Si vous n’avez jamais créé de groupes d’identités auparavant, vous en créerez automatiquement un, sinon cliquez sur « Créer un groupe d’identités». ».
  4. Donnez un nom au groupe (nous avons utilisé des utilisateurs MOTD pour cette démo).
  5. Cochez la case ” Activer l’accès aux identités non authentifiées “.
  6. Aucun fournisseur d’authentification n’est nécessaire, nous devons uniquement traiter avec des utilisateurs non authentifiés.
  7. Si vous souhaitez utiliser une connexion de lecteur, consultez notre article sur l’ authentification de lecteur à l’aide d’Amazon Cognito.
  8. Créer le groupe
  9. Dans la boîte de dialogue ” Vos identités Cognito nécessitent un accès à vos ressources “, cliquez sur ” Afficher les détails “, puis sur ” Pour utilisation non authentifiée “, cliquez sur “Afficher le document de stratégie” puis sur ” Modifier “.
  10. Remplacez le contenu de la zone d’édition par ce qui suit. Cela préserve les autorisations par défaut et ajoute la possibilité d’appeler la fonction Lambda créée précédemment:
{
    "Version": "2012-10-17",
    "Statement": [
    {
       "Sid": "Invoke",
       "Effect": 
       "Allow",
       "Action": ["lambda:InvokeFunction"],
       "Resource": "arn:aws:lambda:us-east-1:0000000000000:function:GetMOTD"
    }, 
    {
       "Effect": "Allow",
       "Action": ["mobileanalytics:PutEvents","cognito-sync:*"],
       "Resource": ["*"]
    }
  ]
}

Vous voyez où il est écrit “Ressource” suivi d’une chaîne commençant par “arn”? Ici, vous devrez remplacer cette chaîne par le «ARN» de la fonction Lambda que vous avez créée précédemment qui ressemblait à “ARN – arn:aws:lambda:us-east-1:0123456789123:fonction:jenny”

Si vous n’en avez pas pris note, vous pouvez toujours ouvrir à nouveau cette fonction dans la console Lambda. L’ARN sera en haut à droite avec un bouton vous permettant de la copier dans le presse-papier.

Une fois que vous avez remplacé la chaîne par l’ARN, vous serez dirigé vers une page contenant un exemple de code à utiliser dans votre jeu pour obtenir un accès pour vos utilisateurs non authentifiés. Pour cette démonstration, tout ce dont vous avez besoin est l’ID du pool d’identités. Copiez-le dans le fichier de paramètres du code de démonstration du client (pour C ++, vous avez besoin d’un autre élément d’information, voir ci-dessous.)

Phase 2: le client

Vous êtes maintenant prêt à intégrer le kit SDK AWS à votre client de jeu et à le faire dialoguer avec AWS. Les étapes diffèrent selon que vous construisez un jeu C ++ ou .NET (C #). Nous avons créé un guide pour chacun ci-dessous:

Comme nous l’avons déjà mentionné, nous allons utiliser des informations d’identification anonymes pour permettre à toute personne exécutant le client de voir le message du jour sans avoir besoin de se connecter, sans ouvrir notre compartiment S3 au monde entier. C’est le moyen privilégié pour donner aux utilisateurs l’accès à vos ressources AWS sans qu’ils aient besoin de se connecter ou de créer de nouveaux rôles IAM et de fournir les clés. La configuration des informations d’identification anonymes est décrite dans les publications ci-dessus.

.NET & C #

Ce code est utilisé pour récupérer les informations d’identification Amazon Cognito et créer le client Lambda:

CognitoAWSCredentials credentials = new CognitoAWSCredentials(
    "us-east-1:xx0000x0-0x00-0000-0000-0x0000000xxx", // Identity pool ID
    RegionEndpoint.USEast1 // Region
);

lambdaClient = new AmazonLambdaClient(credentials, RegionEndpoint.USEast1);

Et voici comment vous appelez la fonction Lambda une fois que vous avez créé le client Lambda:

private static void InvokeLambda(string playername, int playerlevel, int playergold)
{
    JObject jsonPayload = new JObject {
        { "playername", playername },
        { "playerlevel", playerlevel },
        { "playergold", playergold } };

    InvokeRequest request = new InvokeRequest
    {
        FunctionName = "GetMOTD",
        InvocationType = InvocationType.RequestResponse,
        Payload = jsonPayload.ToString()
    };
    InvokeResponse response = lambdaClient.Invoke(request);
    if(response.StatusCode == 200)
    {
        var payloadStreamReader = new StreamReader(response.Payload);
        var jsonReader = new JsonTextReader(payloadStreamReader);
        var jsonObj = (JObject)(new JsonSerializer().Deserialize(jsonReader));
        Console.WriteLine($"Todays Message: {jsonObj["body"].Value<string>()}");
    }
    else
    {
        Console.WriteLine($"Lambda error: {response.FunctionError}");
    }
}

Vous pouvez voir comment initialiser l’API AWS C ++ dans notre article « Guide du développeur pour commencer à utiliser le kit SDK AWS », ainsi que sur la manière de récupérer les informations d’identification anonymes d’Amazon Cognito et de créer le client Lambda.

Une fois que tout est configuré, l’invocation de la fonction Lambda que nous avons créé ressemble à ceci:

    Aws::Lambda::Model::InvokeRequest invokeRequest;
    invokeRequest.SetFunctionName("GetMOTD");
    invokeRequest.SetInvocationType(Aws::Lambda::Model::InvocationType::RequestResponse);
    std::shared_ptr<Aws::IOStream> payload = Aws::MakeShared<Aws::StringStream>("LambdaFunctionRequest");
    Aws::Utils::Json::JsonValue jsonPayload;
    jsonPayload.WithString("playername", playername);
    jsonPayload.WithInteger("playerlevel", playerlevel);
    jsonPayload.WithInteger("playergold", playergold);
    *payload << jsonPayload.View().WriteReadable();
    invokeRequest.SetBody(payload);
    invokeRequest.SetContentType("application/javascript");

    auto outcome = s_LambdaClient->Invoke(invokeRequest);

    if (outcome.IsSuccess())
    {
        auto& result = outcome.GetResult();
        Aws::Utils::Json::JsonValue resultPayload{ result.GetPayload() };
        auto jsonView = resultPayload.View();

        if (jsonView.ValueExists("body"))
        {
            cout << "Today’s Message: " << jsonView.GetString("body") << endl << endl;
        }
        else
        {
            cout << "Unable to parse today message!" << endl << endl;
        }

    }
    else
    {
        auto error = outcome.GetError();
        cout << "Error invoking lambda: " << error.GetMessage() << endl << endl;

    }

Vous pouvez voir comment nous analysons le fichier JSON envoyé au client. Ceci sélectionne notre message du jour afin que nous puissions l’afficher à notre joueur. Et le tour est joué!

Contenu connexe

Comme d’habitude, nous voulons avoir de vos nouvelles! Si vous avez des questions ou des commentaires sur l’un de nos supports d’apprentissage, rendez-vous sur les forums Amazon GameDev.

Traduit en Français par Frédéric Nowak, Architecte Solutions, passionné de jeux vidéo et aidant les clients de toute taille à migrer vers le cloud. Disponible pour toute question via LinkedIn.