├── .github ├── logo.png └── screenshot1.png ├── LICENSE.meta ├── README.md.meta ├── package.json.meta ├── Editor.meta ├── ConfigureNow.asset.meta ├── Editor ├── Skibitsky.Unity.UnityNow.Editor.asmdef.meta ├── DeployNow.cs.meta ├── ConfigureNow.cs.meta ├── DeploymentFile.cs.meta ├── DeploymentContent.cs.meta ├── DeploymentFileReference.cs.meta ├── DeploymentFile.cs ├── DeploymentContent.cs ├── Skibitsky.Unity.UnityNow.Editor.asmdef ├── DeploymentFileReference.cs ├── ConfigureNow.cs └── DeployNow.cs ├── .idea └── .idea.unity-now │ └── .idea │ └── projectSettingsUpdater.xml ├── ConfigureNow.asset ├── package.json ├── LICENSE ├── README.md └── .gitignore /.github/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skibitsky/unity-now/HEAD/.github/logo.png -------------------------------------------------------------------------------- /.github/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skibitsky/unity-now/HEAD/.github/screenshot1.png -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8f719c9f849f04f8689105c4efc1e30b 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7a983b94261e84637af4f048b1c69bef 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c14a358713c0347d091bd3a9ef512aec 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: be52e0ca115d04b71a1fea63fa03150f 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /ConfigureNow.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 80d4cf5b3225d44bf9763962ffd0d300 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Skibitsky.Unity.UnityNow.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d1ddeafbdb7c34156bf18c10fb9de12d 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /.idea/.idea.unity-now/.idea/projectSettingsUpdater.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /Editor/DeployNow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ba758e051ab5544adbe7d6572749d8e4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/ConfigureNow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: abe6ce0c1c4944ba3bd8f4b0c1bb1cf4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/DeploymentFile.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2ef60503fadb34e95a20015b8c396527 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/DeploymentContent.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad9f9dd05c6ca4a379a050033bf507b8 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/DeploymentFileReference.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ce17c8a548a9c4ae69bce9f8b51d5b4e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/DeploymentFile.cs: -------------------------------------------------------------------------------- 1 | namespace Skibitsky.Unity.Editor 2 | { 3 | public class DeploymentFile 4 | { 5 | public long FileSize { get; set; } 6 | 7 | public string RelativePath { get; set; } 8 | 9 | public string Checksum { get; set; } 10 | 11 | public byte[] Data { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Editor/DeploymentContent.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace Skibitsky.Unity.Editor 4 | { 5 | public class DeploymentContent 6 | { 7 | [JsonProperty("name")] public string Name { get; set; } 8 | 9 | [JsonProperty("version")] public int Version { get; set; } 10 | 11 | [JsonProperty("files")] public DeploymentFileReference[] Files { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /ConfigureNow.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: abe6ce0c1c4944ba3bd8f4b0c1bb1cf4, type: 3} 13 | m_Name: ConfigureNow 14 | m_EditorClassIdentifier: 15 | -------------------------------------------------------------------------------- /Editor/Skibitsky.Unity.UnityNow.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Skibitsky.Unity.UnityNow.Editor", 3 | "references": [ 4 | "Skibitsky.Unity.StaticAssetLoader.Editor" 5 | ], 6 | "includePlatforms": [ 7 | "Editor" 8 | ], 9 | "excludePlatforms": [], 10 | "allowUnsafeCode": false, 11 | "overrideReferences": false, 12 | "precompiledReferences": [], 13 | "autoReferenced": true, 14 | "defineConstraints": [], 15 | "versionDefines": [], 16 | "noEngineReferences": false 17 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.skibitsky.unity-now", 3 | "version": "1.1.1", 4 | "displayName": "Unity Now", 5 | "description": "\u25b2 Vercel Now plugin for Unity. Deploy WebGL builds with ease", 6 | "repository": "skibitsky/unity-now", 7 | "author": { 8 | "name": "Gleb Skibitsky", 9 | "email": "gleb@skibitsky.com", 10 | "url": "https://skibitsky.com" 11 | }, 12 | "unity": "2018.3", 13 | "license": "MIT", 14 | "dependencies": { 15 | "com.unity.nuget.newtonsoft-json": "2.0.0", 16 | "com.skibitsky.static-asset-loader": "1.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Editor/DeploymentFileReference.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace Skibitsky.Unity.Editor 4 | { 5 | public class DeploymentFileReference 6 | { 7 | private readonly DeploymentFile _deploymentFile; 8 | 9 | public DeploymentFileReference(DeploymentFile deploymentFile) 10 | { 11 | _deploymentFile = deploymentFile; 12 | } 13 | 14 | [JsonProperty("file")] public string RelativePath => _deploymentFile.RelativePath; 15 | 16 | [JsonProperty("sha")] public string Checksum => _deploymentFile.Checksum; 17 | 18 | [JsonProperty("size")] public int FileSize => (int) _deploymentFile.FileSize; 19 | } 20 | } -------------------------------------------------------------------------------- /Editor/ConfigureNow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Skibitsky.Unity.Editor 4 | { 5 | /// 6 | /// Configuration Scriptable Object. Must be located at Assets/unity-now/ConfigureNow 7 | /// 8 | // Uncomment the line bellow if you lost the Scriptable Object and need to create a new one. 9 | // [CreateAssetMenu(fileName = "ConfigureNow", menuName = "unity-now/ConfigureNow", order = 0)] 10 | public class ConfigureNow : ScriptableObject 11 | { 12 | [SerializeField] public string BaseUrl = "https://api.zeit.co/v9/now"; 13 | 14 | [SerializeField] public bool CopyUrl = true; 15 | [SerializeField] public string Token; 16 | } 17 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Gleb Skibitsky 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Unity Now

4 |

5 | Deploy Unity WebGL builds on Vercel serverless platform with ease. 6 |

7 | 8 |
9 | 10 | ## Installation 11 | 12 | ### Install via OpenUPM 13 | 14 | The package is available on the [openupm registry](https://openupm.com). It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli). 15 | 16 | ``` 17 | openupm add com.skibitsky.unity-now 18 | ``` 19 | 20 | ### Install via Git URL 21 | 22 | Open *Packages/manifest.json* with your favorite text editor. Add the following line to the dependencies block. 23 | 24 | { 25 | "dependencies": { 26 | "com.skibitsky.unity-now": "https://github.com/skibitsky/unity-now.git" 27 | } 28 | } 29 | 30 | Notice: Unity Package Manager records the current commit to a lock entry of the *manifest.json*. To update to the latest version, change the hash value manually or remove the lock entry to resolve the package. 31 | 32 | "lock": { 33 | "com.skibitsky.unity-now": { 34 | "revision": "master", 35 | "hash": "..." 36 | } 37 | } 38 | 39 | 40 | ## Usage 41 | 0. Add your [access token](https://vercel.com/account/tokens) to the **Configure Now** assets (Assets/ConfigureNow) 42 | 1. Run Now→ Deploy from the menu bar 43 |
44 | 2. Select your WebGL build 45 | 3. Wait till deployment completes 46 | 47 | ## Configuration 48 | You can configure Unity Now using **Configure Now** scriptable object. By default it is located at *Assets/ConfigureNow* and contains the following properties: 49 | 50 | | Name | Description | 51 | | --- | --- | 52 | | **Token** | Vercel access token. You can generate a new one [here](https://vercel.com/account/tokens) | 53 | | **Base URL** | Endpoint base URL. You can change it if you need a certain server location. [Read more](https://zeit.co/docs/api/#api-basics/server-specs/origins) | 54 | | **Copy URL** | If enabled, Unity Now will save the deployment URL to the clipboard after the deployment is complete | 55 | 56 | ## License 57 | MIT © [skibitsky](http://skibitsky.com) 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /[Ll]ogs/ 7 | /[Mm]emoryCaptures/ 8 | /[Aa]ssets/AssetStoreTools* 9 | 10 | # Visual Studio cache directory 11 | .vs/ 12 | .vscode/ 13 | 14 | # Rider User-specific stuff 15 | .idea/**/workspace.xml 16 | .idea/**/tasks.xml 17 | .idea/**/usage.statistics.xml 18 | .idea/**/dictionaries 19 | .idea/**/shelf 20 | 21 | # Rider Sensitive or high-churn files 22 | .idea/**/dataSources/ 23 | .idea/**/dataSources.ids 24 | .idea/**/dataSources.local.xml 25 | .idea/**/sqlDataSources.xml 26 | .idea/**/dynamic.xml 27 | .idea/**/uiDesigner.xml 28 | .idea/**/dbnavigator.xml 29 | 30 | # Rider Gradle 31 | .idea/**/gradle.xml 32 | .idea/**/libraries 33 | 34 | # Rider Mongo Explorer plugin 35 | .idea/**/mongoSettings.xml 36 | 37 | # Rider File-based project format 38 | *.iws 39 | 40 | # Other rider rubbish 41 | .idea/**/dbnavigator.xml 42 | .idea/**/encodings.xml 43 | .idea/**/indexLayout.xml 44 | .idea/**/misc.xml 45 | .idea/**/.idea/modules.xml 46 | .idea/**/.idea/vcs.xml 47 | .idea/**/riderModule.iml 48 | 49 | # IntelliJ 50 | out/ 51 | 52 | # Rider mpeltonen/sbt-idea plugin 53 | .idea_modules/ 54 | 55 | # JIRA plugin 56 | atlassian-ide-plugin.xml 57 | 58 | # Rider Cursive Clojure plugin 59 | .idea/replstate.xml 60 | 61 | # Rider Crashlytics plugin (for Android Studio and IntelliJ) 62 | com_crashlytics_export_strings.xml 63 | crashlytics.properties 64 | crashlytics-build.properties 65 | fabric.properties 66 | 67 | # Rider Editor-based Rest Client 68 | .idea/httpRequests 69 | 70 | # Generated files 71 | .idea/**/contentModel.xml 72 | 73 | # Autogenerated VS/MD/Consulo solution and project files 74 | ExportedObj/ 75 | .consulo/ 76 | *.csproj 77 | *.unityproj 78 | *.sln 79 | *.suo 80 | *.tmp 81 | *.user 82 | *.userprefs 83 | *.pidb 84 | *.booproj 85 | *.svd 86 | *.pdb 87 | *.mdb 88 | *.VC.db 89 | 90 | # Gradle cache directory 91 | .gradle/ 92 | 93 | # TextMesh Pro files 94 | [Aa]ssets/TextMesh*Pro/ 95 | 96 | # Autogenerated Jetbrains Rider plugin 97 | [Aa]ssets/Plugins/Editor/JetBrains* 98 | 99 | # Unity3D generated meta files 100 | *.pidb.meta 101 | *.pdb.meta 102 | *.mdb.meta 103 | 104 | # Unity3D Generated File On Crash Reports 105 | sysinfo.txt 106 | 107 | # Builds 108 | *.apk 109 | *.unitypackage 110 | 111 | # Windows image file caches 112 | Thumbs.db 113 | ehthumbs.db 114 | 115 | # Folder config file 116 | Desktop.ini 117 | 118 | # Recycle Bin used on file shares 119 | $RECYCLE.BIN/ 120 | 121 | # Mac desktop service store files 122 | .DS_Store 123 | 124 | # iCloud Drive sync meta 125 | .icloud 126 | 127 | # Crashlytics generated file 128 | crashlytics-build.properties 129 | 130 | # Vuforia license 131 | QCAR/somedata16 132 | -------------------------------------------------------------------------------- /Editor/DeployNow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net.Http; 7 | using System.Security.Cryptography; 8 | using System.Text; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | using Newtonsoft.Json; 12 | using Newtonsoft.Json.Linq; 13 | using UnityEditor; 14 | using UnityEngine; 15 | 16 | namespace Skibitsky.Unity.Editor 17 | { 18 | public static class DeployNow 19 | { 20 | [MenuItem("Now/Deploy", false, 0)] 21 | public static async void Deploy() 22 | { 23 | var configuration = StaticAssetLoader.LoadAsset(); 24 | 25 | // If configuration file doesn't exist, create one 26 | if (configuration == null) 27 | { 28 | configuration = ScriptableObject.CreateInstance(); 29 | var assetPath = AssetDatabase.GenerateUniqueAssetPath("Assets/ConfigureNow.asset"); 30 | AssetDatabase.CreateAsset(configuration, assetPath); 31 | } 32 | 33 | // Check if access token is not empty 34 | if (string.IsNullOrWhiteSpace(configuration.Token)) 35 | { 36 | Debug.LogError( 37 | $"[unity-now]: Vercel Now access token is missing. Please set token in {AssetDatabase.GetAssetPath(configuration)}." + 38 | "\nYou can create a new token at: https://vercel.com/account/tokens"); 39 | return; 40 | } 41 | 42 | // Use Unity project name for deployment name 43 | var deploymentName = PlayerSettings.productName; 44 | 45 | var httpClient = new HttpClient(); 46 | 47 | var deploymentFileReferences = new ConcurrentBag(); 48 | var uploadFileRequests = new ConcurrentBag(); 49 | 50 | var path = EditorUtility.OpenFolderPanel("Select the folder to deploy", "", ""); 51 | 52 | Debug.Log("Syncing files..."); 53 | 54 | Parallel.ForEach(Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories), file => 55 | { 56 | var deploymentFile = new DeploymentFile(); 57 | 58 | using (var stream = File.OpenRead(file)) 59 | { 60 | // File size in bytes 61 | var contentLength = stream.Length; 62 | deploymentFile.FileSize = contentLength; 63 | 64 | // File relative path 65 | deploymentFile.RelativePath = file.Replace($"{path}/", ""); 66 | 67 | // File data 68 | var data = new byte[contentLength]; 69 | stream.Read(data, 0, (int) contentLength); 70 | deploymentFile.Data = data; 71 | 72 | // File SHA1 used to check the integrity 73 | using (var sha = SHA1.Create()) 74 | { 75 | deploymentFile.Checksum = BitConverter.ToString(sha.ComputeHash(data)).ToLowerInvariant() 76 | .Replace("-", ""); 77 | } 78 | } 79 | 80 | deploymentFileReferences.Add(new DeploymentFileReference(deploymentFile)); 81 | uploadFileRequests.Add(UploadFileRequest(deploymentFile, httpClient, configuration)); 82 | }); 83 | 84 | // Wait for all files to upload 85 | await Task.WhenAll(uploadFileRequests); 86 | Debug.Log($"[unity-now]: All files synced! Creating deployment for {deploymentName}..."); 87 | 88 | // Create Deployment 89 | await CreateDeploymentRequest(deploymentFileReferences, deploymentName, httpClient, configuration); 90 | } 91 | 92 | /// 93 | /// Creates new Now deployment 94 | /// 95 | private static async Task CreateDeploymentRequest(IEnumerable deploymentFileReferences, 96 | string deploymentName, HttpMessageInvoker httpClient, ConfigureNow configuration, 97 | CancellationToken cancellationToken = default) 98 | { 99 | var content = new DeploymentContent 100 | { 101 | Name = deploymentName, 102 | Version = 2, 103 | Files = deploymentFileReferences.ToArray() 104 | }; 105 | 106 | var jsonContent = JsonConvert.SerializeObject(content); 107 | 108 | var httpMessage = new HttpRequestMessage 109 | { 110 | Method = HttpMethod.Post, 111 | RequestUri = new Uri($"{configuration.BaseUrl}/deployments"), 112 | Headers = 113 | { 114 | {"Authorization", $"Bearer {configuration.Token}"} 115 | }, 116 | Content = new StringContent(jsonContent, Encoding.UTF8, "application/json") 117 | }; 118 | 119 | using (var response = await httpClient.SendAsync(httpMessage, cancellationToken)) 120 | { 121 | var responseMessage = await response.Content.ReadAsStringAsync(); 122 | if (response.IsSuccessStatusCode) 123 | { 124 | var jObject = JObject.Parse(responseMessage); 125 | var deploymentUrl = jObject["url"].ToString(); 126 | 127 | // Copy URL to clipboard 128 | if (configuration.CopyUrl) 129 | GUIUtility.systemCopyBuffer = deploymentUrl; 130 | 131 | Debug.Log($"[unity-now]: Ready! https://{deploymentUrl} " + 132 | $"{(configuration.CopyUrl ? "(copied)" : "")}"); 133 | } 134 | else 135 | { 136 | Debug.LogError($"[unity-now]: Something went wrong during deployment creation.\n{responseMessage}"); 137 | } 138 | } 139 | } 140 | 141 | /// 142 | /// Uploads one file to the Now 143 | /// 144 | private static async Task UploadFileRequest(DeploymentFile deploymentFile, HttpMessageInvoker httpClient, 145 | ConfigureNow configuration, 146 | CancellationToken cancellationToken = default) 147 | { 148 | var httpMessage = new HttpRequestMessage 149 | { 150 | Method = HttpMethod.Post, 151 | RequestUri = new Uri($"{configuration.BaseUrl}/files"), 152 | Headers = 153 | { 154 | {"Authorization", $"Bearer {configuration.Token}"}, 155 | {"x-now-digest", deploymentFile.Checksum} 156 | }, 157 | Content = new ByteArrayContent(deploymentFile.Data) 158 | }; 159 | 160 | httpMessage.Content.Headers.ContentLength = deploymentFile.FileSize; 161 | 162 | using (var response = await httpClient.SendAsync(httpMessage, cancellationToken)) 163 | { 164 | var responseMessage = await response.Content.ReadAsStringAsync(); 165 | if (!response.IsSuccessStatusCode) 166 | Debug.LogError($"[unity-now]: Something went wrong during file upload.\n{responseMessage}"); 167 | } 168 | } 169 | } 170 | } --------------------------------------------------------------------------------