How To Connect to S3 in Unity

Let’s say you want to upload a file to AWS S3 from your Unity game. Well, if you follow the AWS instructions, you’ll probably run into errors. This guide helps you through the errors I encountered.

Step 1 – Follow the Setup the AWS SDK Tutorial

Notes:

While importing the AWS SDK into Unity, since I only needed to use S3 for now, I imported the S3 and IdentityManagement package.

Fixing awsconfig.xml

The awsconfig.xml file in the documentation as of Sept 2018 doesn’t work. Use this for your Assets/Resources/awsconfig.xml file (Download here) (Note the region I work in is us-west-2, yours may be different):

<?xml version="1.0" encoding="utf-8"?>
<aws region="us-west-2" correctForClockSkew="true">
    <logging logTo="UnityLogger"
             logResponses="Always"
             logMetrics="true"
             logMetricsFormat="JSON" />
</aws>

Errors the above file fixed for me:

  • correctForClockSkew fixes: NullReferenceException: Object reference not set to an instance of an object Amazon.AWSConfigs.GetSection[AWSSection] (System.String sectionName)
  • XmlException: expected ‘>’ (3E) but found ‘<‘ (3C)
  • XmlException: a name did not start with a legal character 60 (<)
  • XmlException: XML declaration cannot appear in this state.

Step 2 – Get the Examples/S3Example.scene working

Follow the Examples/readme.txt. This gives you instructions on setting up an AWS Cognito Pool and setting the region, bucket name, and pool Id in the scene.

Fix the link.xml file

Warning: Rather than follow the link in step 5 [Unity SDK readme], use my link.xml The link listed in the readme has bugs in the xml files (including link.xml being incomplete and awsconfig.xml having compiler errors).

Fix the S3Example.cs code

The original file from the project was littered with bugs when I ran it:

  • HttpErrorResponseException in Post Object (fix by adding region to request)
  • NullPointerException when trying to log responses (fix by logging exception rather than http codes)
  • “InvalidOperationException: Cannot override system-specified headers” (fix by using AWSConfigs.HttpClientOption.UnityWebRequest http client)

Here’s my S3Example.cs that fixes the above.

Make your IAM and S3 permissions correct and secure

Don’t make your S3 bucket public.

I wanted to limit my Cognito roles to only access have write access to objects in my bucket (not the whole bucket), read access to my bucket, and list actions.

Here’s the managed IAM policy I created to add to my Cognito roles (Note: Change BUCKET_NAME in the resources section to your bucket twice!!!):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucketByTags",
                "s3:GetLifecycleConfiguration",
                "s3:GetBucketTagging",
                "s3:GetInventoryConfiguration",
                "s3:DeleteObjectVersion",
                "s3:GetObjectVersionTagging",
                "s3:ListBucketVersions",
                "s3:GetBucketLogging",
                "s3:ListBucket",
                "s3:GetAccelerateConfiguration",
                "s3:GetBucketPolicy",
                "s3:GetObjectVersionTorrent",
                "s3:GetObjectAcl",
                "s3:GetEncryptionConfiguration",
                "s3:GetBucketRequestPayment",
                "s3:GetObjectVersionAcl",
                "s3:GetObjectTagging",
                "s3:GetMetricsConfiguration",
                "s3:PutObjectTagging",
                "s3:DeleteObject",
                "s3:GetIpConfiguration",
                "s3:DeleteObjectTagging",
                "s3:ListBucketMultipartUploads",
                "s3:GetBucketWebsite",
                "s3:PutObjectVersionTagging",
                "s3:DeleteObjectVersionTagging",
                "s3:GetBucketVersioning",
                "s3:GetBucketAcl",
                "s3:GetBucketNotification",
                "s3:GetReplicationConfiguration",
                "s3:ListMultipartUploadParts",
                "s3:PutObject",
                "s3:GetObject",
                "s3:GetObjectTorrent",
                "s3:GetBucketCORS",
                "s3:GetAnalyticsConfiguration",
                "s3:GetObjectVersionForReplication",
                "s3:GetBucketLocation",
                "s3:GetObjectVersion"
            ],
            "Resource": [
                "arn:aws:s3:::BUCKET_NAME",
                "arn:aws:s3:::BUCKET_NAME/*"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:HeadBucket"
            ],
            "Resource": "*"
        }
    ]
}

Hope this helps you!

Follow me in social media:
Share this post:

Comments 6

  • Thanks for sharing, really painful process until I found your post!

  • hi,
    Thank you for detailing the process. it really makes things easy but I do have a question.
    I’m stuck at the point of adding fix using this line
    “AWSConfigs.HttpClient = AWSConfigs.HttpClientOption.UnityWebRequest;”.

    The issue is that somehow unity is giving me error that `Amazon.AWSConfigs’ does not contain a definition for `HttpClient’.
    The same goes for ‘HttpClientOption’. somehow ‘AWSConfigs’ is missing these entries.

    Anything you could say about it?

    • Usually errors like this are caused by spelling mistakes and typos. I wonder if you are using an IDE that’s supports auto fill if AWSConfigs has other definitions in it or if you could auto complete the http client?

      Please let me know what works for you.

  • Is this still valid as of Dec 2019? I followed your steps and when I click “List Buckets” this is the first error I get:

    HttpErrorResponseException: Exception of type ‘Amazon.Runtime.Internal.HttpErrorResponseException’ was thrown.
    Amazon.Runtime.Internal.UnityRequest.EndGetResponse (IAsyncResult asyncResult)
    Amazon.Runtime.Internal.HttpHandler`1[System.String].GetResponseCallbackHelper (System.Object state)
    UnityEngine.Debug:LogException(Exception)
    Amazon.Runtime.Internal.Util.UnityDebugLogger:Error(Exception, String, Object[])
    Amazon.Runtime.Internal.Util.Logger:Error(Exception, String, Object[])
    Amazon.Runtime.Internal.ErrorHandler:ProcessException(IExecutionContext, Exception)
    Amazon.Runtime.Internal.ErrorHandler:InvokeAsyncCallback(IAsyncExecutionContext)
    Amazon.Runtime.Internal.PipelineHandler:AsyncCallback(IAsyncExecutionContext)
    Amazon.Runtime.Internal.PipelineHandler:InvokeAsyncCallback(IAsyncExecutionContext)
    Amazon.S3.Internal.AmazonS3ResponseHandler:InvokeAsyncCallback(IAsyncExecutionContext)
    Amazon.Runtime.Internal.PipelineHandler:AsyncCallback(IAsyncExecutionContext)
    Amazon.Runtime.Internal.PipelineHandler:InvokeAsyncCallback(IAsyncExecutionContext)
    Amazon.Runtime.Internal.Unmarshaller:InvokeAsyncCallback(IAsyncExecutionContext)
    Amazon.Runtime.Internal.PipelineHandler:AsyncCallback(IAsyncExecutionContext)
    Amazon.Runtime.Internal.PipelineHandler:InvokeAsyncCallback(IAsyncExecutionContext)
    Amazon.Runtime.Internal.RedirectHandler:InvokeAsyncCallback(IAsyncExecutionContext)
    Amazon.Runtime.Internal.PipelineHandler:AsyncCallback(IAsyncExecutionContext)
    Amazon.Runtime.Internal.PipelineHandler:InvokeAsyncCallback(IAsyncExecutionContext)
    Amazon.Runtime.Internal.HttpHandler`1:GetResponseCallbackHelper(Object)

Leave a Reply

Your email address will not be published.