diff --git a/.github/latest.md b/.github/latest.md index 111164bf..2a6a71bd 100644 --- a/.github/latest.md +++ b/.github/latest.md @@ -1,5 +1,7 @@ ## Changelog +## Updated +- Updated handling of response data to reduce garbage allocation [#314](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/314) ## Fixed -- Fixed an issue causing json parsing to fail on iFrame events [#311](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/311/) \ No newline at end of file +- Preserve AssetId property in IAssetData [#313](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/313) \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index d41ed308..6469ae37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [7.2.0] - 2024.09.06 + +## Updated +- Updated handling of response data to reduce garbage allocation [#314](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/314) +## Fixed +- Preserve AssetId property in IAssetData [#313](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/313) + ## [7.1.1] - 2024.07.25 ## Fixed diff --git a/Runtime/AvatarCreator/Scripts/Extensions/ResponseExtensions.cs b/Runtime/AvatarCreator/Scripts/Extensions/ResponseExtensions.cs index 95900515..1a065988 100644 --- a/Runtime/AvatarCreator/Scripts/Extensions/ResponseExtensions.cs +++ b/Runtime/AvatarCreator/Scripts/Extensions/ResponseExtensions.cs @@ -14,7 +14,7 @@ public static void ThrowIfError(this IResponse response) } } - public static void ThrowIfError(this Response response) + public static void ThrowIfError(this ResponseText response) { if (!response.IsSuccess) { diff --git a/Runtime/AvatarCreator/Scripts/Interfaces/IAssetData.cs b/Runtime/AvatarCreator/Scripts/Interfaces/IAssetData.cs index 86861126..b6688f39 100644 --- a/Runtime/AvatarCreator/Scripts/Interfaces/IAssetData.cs +++ b/Runtime/AvatarCreator/Scripts/Interfaces/IAssetData.cs @@ -1,7 +1,10 @@ +using UnityEngine.Scripting; + namespace ReadyPlayerMe.AvatarCreator { public interface IAssetData { + [Preserve] public string Id { get; set; } public AssetType AssetType { get; set; } } diff --git a/Runtime/AvatarCreator/Scripts/WebRequests/AssetAPIRequests.cs b/Runtime/AvatarCreator/Scripts/WebRequests/AssetAPIRequests.cs index 4f8a060c..7409f345 100644 --- a/Runtime/AvatarCreator/Scripts/WebRequests/AssetAPIRequests.cs +++ b/Runtime/AvatarCreator/Scripts/WebRequests/AssetAPIRequests.cs @@ -98,7 +98,7 @@ public AssetAPIRequests(string appId) var url = BuildAssetListUrl(type, limit, pageNumber, AuthManager.UserSession.Id, appId, gender == OutfitGender.Masculine ? "male" : "female"); - var response = await authorizedRequest.SendRequest(new RequestData + var response = await authorizedRequest.SendRequest(new RequestData { Url = url, Method = HttpMethod.GET diff --git a/Runtime/AvatarCreator/Scripts/WebRequests/AuthAPIRequests.cs b/Runtime/AvatarCreator/Scripts/WebRequests/AuthAPIRequests.cs index d4458c02..283edf27 100644 --- a/Runtime/AvatarCreator/Scripts/WebRequests/AuthAPIRequests.cs +++ b/Runtime/AvatarCreator/Scripts/WebRequests/AuthAPIRequests.cs @@ -38,7 +38,7 @@ public AuthAPIRequests(string domain) public async Task LoginAsAnonymous(CancellationToken cancellationToken = default) { - var response = await webRequestDispatcher.SendRequest($"{rpmAuthBaseUrl}/users", HttpMethod.POST, headers, ctx:cancellationToken); + var response = await webRequestDispatcher.SendRequest($"{rpmAuthBaseUrl}/users", HttpMethod.POST, headers, ctx:cancellationToken); response.ThrowIfError(); var data = AuthDataConverter.ParseResponse(response.Text); @@ -60,7 +60,7 @@ public async Task SendCodeToEmail(string email, string userId = "",CancellationT var payload = AuthDataConverter.CreatePayload(data); - var response = await webRequestDispatcher.SendRequest($"{rpmAuthBaseUrl}/auth/start", HttpMethod.POST, headers, payload, ctx:cancellationToken); + var response = await webRequestDispatcher.SendRequest($"{rpmAuthBaseUrl}/auth/start", HttpMethod.POST, headers, payload, ctx:cancellationToken); response.ThrowIfError(); } @@ -76,7 +76,7 @@ public async Task LoginWithCode(string code, string userIdToMerge = } var payload = AuthDataConverter.CreatePayload(body); - var response = await webRequestDispatcher.SendRequest($"{rpmAuthBaseUrl}/auth/login", HttpMethod.POST, headers, payload, ctx:cancellationToken); + var response = await webRequestDispatcher.SendRequest($"{rpmAuthBaseUrl}/auth/login", HttpMethod.POST, headers, payload, ctx:cancellationToken); response.ThrowIfError(); var data = AuthDataConverter.ParseResponse(response.Text); @@ -93,7 +93,7 @@ public async Task Signup(string email, string userId, CancellationToken cancella }; var payload = AuthDataConverter.CreatePayload(data); - var response = await webRequestDispatcher.SendRequest($"{rpmAuthBaseUrl}/auth/start", HttpMethod.POST, headers, payload, ctx:cancellationToken); + var response = await webRequestDispatcher.SendRequest($"{rpmAuthBaseUrl}/auth/start", HttpMethod.POST, headers, payload, ctx:cancellationToken); response.ThrowIfError(); } @@ -122,7 +122,7 @@ private async Task RefreshRequest(string token, string refreshToken, Can { AuthConstants.REFRESH_TOKEN, refreshToken } }); - var response = await webRequestDispatcher.SendRequest(url, HttpMethod.POST, headers, payload, ctx:cancellationToken); + var response = await webRequestDispatcher.SendRequest(url, HttpMethod.POST, headers, payload, ctx:cancellationToken); response.ThrowIfError(); return AuthDataConverter.ParseResponse(response.Text); diff --git a/Runtime/AvatarCreator/Scripts/WebRequests/AvatarAPIRequests.cs b/Runtime/AvatarCreator/Scripts/WebRequests/AvatarAPIRequests.cs index e7dfdad6..caded4e4 100644 --- a/Runtime/AvatarCreator/Scripts/WebRequests/AvatarAPIRequests.cs +++ b/Runtime/AvatarCreator/Scripts/WebRequests/AvatarAPIRequests.cs @@ -34,7 +34,7 @@ public AvatarAPIRequests(CancellationToken ctx = default) public async Task> GetUserAvatars(string userId) { - var response = await authorizedRequest.SendRequest( + var response = await authorizedRequest.SendRequest( new RequestData { Url = $"{RPM_AVATAR_V1_BASE_URL}/?userId={userId}&select={ID},{PARTNER},{DATA}.{BODY_TYPE}", @@ -58,7 +58,7 @@ public async Task> GetUserAvatars(string userId) public async Task> GetAvatarTemplates() { - var response = await authorizedRequest.SendRequest( + var response = await authorizedRequest.SendRequest( new RequestData { Url = $"{RPM_AVATAR_V2_BASE_URL}/templates?{BODY_TYPE}={CoreSettingsHandler.CoreSettings.BodyType.GetDescription()}", @@ -83,7 +83,7 @@ public async Task CreateFromTemplateAvatar(string templateId, var payload = AuthDataConverter.CreatePayload(payloadData); - var response = await authorizedRequest.SendRequest( + var response = await authorizedRequest.SendRequest( new RequestData { Url = $"{RPM_AVATAR_V2_BASE_URL}/templates/{templateId}", @@ -109,7 +109,7 @@ public async Task GetAvatarColors(string avatarId, AssetType asset colorParameters = "skin,beard,hair,eyebrow"; } - var response = await authorizedRequest.SendRequest( + var response = await authorizedRequest.SendRequest( new RequestData { Url = $"{RPM_AVATAR_V2_BASE_URL}/{avatarId}/colors?type={colorParameters}", @@ -130,7 +130,7 @@ public async Task GetAvatarMetadata(string avatarId, bool isDr if (isDraft) url += "preview=true"; - var response = await authorizedRequest.SendRequest( + var response = await authorizedRequest.SendRequest( new RequestData { Url = url, @@ -148,7 +148,7 @@ public async Task GetAvatarMetadata(string avatarId, bool isDr public async Task CreateNewAvatar(AvatarProperties avatarProperties) { - var response = await authorizedRequest.SendRequest( + var response = await authorizedRequest.SendRequest( new RequestData { Url = RPM_AVATAR_V2_BASE_URL, @@ -175,7 +175,7 @@ public async Task GetAvatar(string avatarId, bool isPreview = false, str if (isPreview) url += "preview=true"; - var response = await authorizedRequest.SendRequest( + var response = await authorizedRequest.SendRequest( new RequestData { Url = url, @@ -192,7 +192,7 @@ public async Task GetAvatarProperties(string avatarId) ValidateAvatarId(avatarId); var url = $"{RPM_AVATAR_V2_BASE_URL}/{avatarId}.json?"; - var response = await authorizedRequest.SendRequest( + var response = await authorizedRequest.SendRequest( new RequestData { Url = url, @@ -211,7 +211,7 @@ public async Task UpdateAvatar(string avatarId, AvatarProperties avatarP ValidateAvatarId(avatarId); var url = $"{RPM_AVATAR_V2_BASE_URL}/{avatarId}?responseType=glb&{parameters}"; - var response = await authorizedRequest.SendRequest( + var response = await authorizedRequest.SendRequest( new RequestData { Url = url, @@ -228,7 +228,7 @@ public async Task PrecompileAvatar(string avatarId, PrecompileData precompileDat ValidateAvatarId(avatarId); var json = JsonConvert.SerializeObject(precompileData); - var response = await authorizedRequest.SendRequest( + var response = await authorizedRequest.SendRequest( new RequestData { Url = $"{RPM_AVATAR_V2_BASE_URL}/{avatarId}/precompile?{parameters ?? string.Empty}", @@ -243,7 +243,7 @@ public async Task PrecompileAvatar(string avatarId, PrecompileData precompileDat public async Task SaveAvatar(string avatarId) { ValidateAvatarId(avatarId); - var response = await authorizedRequest.SendRequest( + var response = await authorizedRequest.SendRequest( new RequestData { Url = $"{RPM_AVATAR_V2_BASE_URL}/{avatarId}", @@ -263,7 +263,7 @@ public async Task DeleteAvatar(string avatarId, bool isDraft = false) if (isDraft) url += "draft"; - var response = await authorizedRequest.SendRequest( + var response = await authorizedRequest.SendRequest( new RequestData { Url = url, diff --git a/Runtime/Core/Scripts/Analytics/AmplitudeEventLogger.cs b/Runtime/Core/Scripts/Analytics/AmplitudeEventLogger.cs index 6268162f..bed0f193 100644 --- a/Runtime/Core/Scripts/Analytics/AmplitudeEventLogger.cs +++ b/Runtime/Core/Scripts/Analytics/AmplitudeEventLogger.cs @@ -81,7 +81,7 @@ private static async Task Dispatch(string url, string payload) } var webRequestDispatcher = new WebRequestDispatcher(); - var response = await webRequestDispatcher.SendRequest(url, HttpMethod.POST, CommonHeaders.GetHeadersWithAppId(), payload); + var response = await webRequestDispatcher.SendRequest(url, HttpMethod.POST, CommonHeaders.GetHeadersWithAppId(), payload); if (!response.IsSuccess) { diff --git a/Runtime/Core/Scripts/Data/ApplicationData.cs b/Runtime/Core/Scripts/Data/ApplicationData.cs index 897aa8e9..6c7a9480 100644 --- a/Runtime/Core/Scripts/Data/ApplicationData.cs +++ b/Runtime/Core/Scripts/Data/ApplicationData.cs @@ -6,7 +6,7 @@ namespace ReadyPlayerMe.Core { public static class ApplicationData { - public const string SDK_VERSION = "v7.1.1"; + public const string SDK_VERSION = "v7.2.0"; private const string TAG = "ApplicationData"; private const string DEFAULT_RENDER_PIPELINE = "Built-In Render Pipeline"; private static readonly AppData Data; diff --git a/Runtime/Core/Scripts/Data/Response.cs.meta b/Runtime/Core/Scripts/Data/Response.cs.meta deleted file mode 100644 index b2804e30..00000000 --- a/Runtime/Core/Scripts/Data/Response.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: d39ab182772d4251ab0513ad2c601af1 -timeCreated: 1680726656 \ No newline at end of file diff --git a/Runtime/Core/Scripts/Data/Response.cs b/Runtime/Core/Scripts/Data/ResponseData.cs similarity index 80% rename from Runtime/Core/Scripts/Data/Response.cs rename to Runtime/Core/Scripts/Data/ResponseData.cs index ebc19e3d..664e5351 100644 --- a/Runtime/Core/Scripts/Data/Response.cs +++ b/Runtime/Core/Scripts/Data/ResponseData.cs @@ -2,9 +2,8 @@ namespace ReadyPlayerMe.Core { - public class Response : IResponse + public class ResponseData : IResponse { - public string Text; public byte[] Data; public bool IsSuccess { get; set; } @@ -18,7 +17,6 @@ public void Parse(UnityWebRequest request) return; } - Text = request.downloadHandler.text; Data = request.downloadHandler.data; } } diff --git a/Runtime/Core/Scripts/Data/ResponseData.cs.meta b/Runtime/Core/Scripts/Data/ResponseData.cs.meta new file mode 100644 index 00000000..25f5b134 --- /dev/null +++ b/Runtime/Core/Scripts/Data/ResponseData.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d303caaa8544cb14f890780f9a351900 \ No newline at end of file diff --git a/Runtime/Core/Scripts/Data/ResponseText.cs b/Runtime/Core/Scripts/Data/ResponseText.cs new file mode 100644 index 00000000..daa0c9aa --- /dev/null +++ b/Runtime/Core/Scripts/Data/ResponseText.cs @@ -0,0 +1,23 @@ +using UnityEngine.Networking; + +namespace ReadyPlayerMe.Core +{ + public class ResponseText : IResponse + { + public string Text; + + public bool IsSuccess { get; set; } + public string Error { get; set; } + public long ResponseCode { get; set; } + + public void Parse(UnityWebRequest request) + { + if (request.downloadHandler is DownloadHandlerFile) + { + return; + } + + Text = request.downloadHandler.text; + } + } +} diff --git a/Runtime/Core/Scripts/Data/ResponseText.cs.meta b/Runtime/Core/Scripts/Data/ResponseText.cs.meta new file mode 100644 index 00000000..e8492853 --- /dev/null +++ b/Runtime/Core/Scripts/Data/ResponseText.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e10c8c31cb527bf479d936ea81ee04fd \ No newline at end of file diff --git a/Runtime/Core/Scripts/Extensions/WebRequestDispatcherExtension.cs b/Runtime/Core/Scripts/Extensions/WebRequestDispatcherExtension.cs index ced70db2..eb338640 100644 --- a/Runtime/Core/Scripts/Extensions/WebRequestDispatcherExtension.cs +++ b/Runtime/Core/Scripts/Extensions/WebRequestDispatcherExtension.cs @@ -21,15 +21,15 @@ public static class WebRequestDispatcherExtension /// /// This asynchronous method makes GET request to the and returns the data in the - /// . + /// . /// /// WebRequestDispatcher object /// The URL to make the to. /// Can be used to cancel the operation. /// The number of seconds to wait for the WebRequest to finish before aborting. - /// A if successful otherwise it will throw an exception. - public static async Task DownloadIntoMemory(this WebRequestDispatcher webRequestDispatcher, string url, CancellationToken token, - int timeout = TIMEOUT) + /// A if successful otherwise it will throw an exception. + public static async Task DownloadIntoMemory(this WebRequestDispatcher webRequestDispatcher, string url, CancellationToken token, + int timeout = TIMEOUT) where T : IResponse, new() { if (!HasInternetConnection) { @@ -45,7 +45,7 @@ public static async Task DownloadIntoMemory(this WebRequestDispatcher headers.Add(CommonHeaders.GetAppIdHeader()); webRequestDispatcher.Timeout = timeout; - var response = await webRequestDispatcher.SendRequest(url, HttpMethod.GET, headers, ctx: token); + var response = await webRequestDispatcher.SendRequest(url, HttpMethod.GET, headers, ctx: token); token.ThrowCustomExceptionIfCancellationRequested(); if (!response.IsSuccess) diff --git a/Runtime/Core/Scripts/Operations/AvatarDownloader.cs b/Runtime/Core/Scripts/Operations/AvatarDownloader.cs index 68d282f6..e9b94d6f 100644 --- a/Runtime/Core/Scripts/Operations/AvatarDownloader.cs +++ b/Runtime/Core/Scripts/Operations/AvatarDownloader.cs @@ -105,7 +105,7 @@ public async Task Execute(AvatarContext context, CancellationToke try { - var response = await dispatcher.DownloadIntoMemory(url, token, Timeout); + var response = await dispatcher.DownloadIntoMemory(url, token, Timeout); return response.Data; } catch (CustomException exception) diff --git a/Runtime/Core/Scripts/Operations/MetadataDownloader.cs b/Runtime/Core/Scripts/Operations/MetadataDownloader.cs index e3ff56e4..2f29355e 100644 --- a/Runtime/Core/Scripts/Operations/MetadataDownloader.cs +++ b/Runtime/Core/Scripts/Operations/MetadataDownloader.cs @@ -81,9 +81,9 @@ private AvatarContext UpdateContext(AvatarContext avatarContext, AvatarMetadata { #if UNITY_WEBGL // add random tail to the url to prevent JSON from being loaded from the browser cache - var response = await dispatcher.DownloadIntoMemory(url + "?tail=" + Guid.NewGuid(), token, Timeout); + var response = await dispatcher.DownloadIntoMemory(url + "?tail=" + Guid.NewGuid(), token, Timeout); #else - Response response = await dispatcher.DownloadIntoMemory(url, token, Timeout); + ResponseText response = await dispatcher.DownloadIntoMemory(url, token, Timeout); #endif return ParseResponse(response.Text); } diff --git a/Runtime/Core/Shaders/glTFastShaderVariants.shadervariants b/Runtime/Core/Shaders/glTFastShaderVariants.shadervariants index 32bf5f24..b1eb71c6 100644 --- a/Runtime/Core/Shaders/glTFastShaderVariants.shadervariants +++ b/Runtime/Core/Shaders/glTFastShaderVariants.shadervariants @@ -10,4 +10,34 @@ ShaderVariantCollection: m_Shaders: - first: {fileID: 4800000, guid: 99fa998bbbed3408aafa652b466d261d, type: 3} second: - variants: [] + variants: + - keywords: DIRECTIONAL LIGHTPROBE_SH SHADOWS_SCREEN + passType: 4 + - keywords: DIRECTIONAL LIGHTPROBE_SH SHADOWS_SCREEN _EMISSION _METALLICGLOSSMAP + _NORMALMAP + passType: 4 + - keywords: DIRECTIONAL LIGHTPROBE_SH SHADOWS_SCREEN _METALLICGLOSSMAP _NORMALMAP + passType: 4 + - keywords: DIRECTIONAL LIGHTPROBE_SH SHADOWS_SCREEN _NORMALMAP + passType: 4 + - keywords: DIRECTIONAL LIGHTPROBE_SH _ALPHABLEND_ON + passType: 4 + - keywords: DIRECTIONAL LIGHTPROBE_SH _ALPHABLEND_ON _EMISSION _METALLICGLOSSMAP + _NORMALMAP + passType: 4 + - keywords: DIRECTIONAL LIGHTPROBE_SH _ALPHABLEND_ON _METALLICGLOSSMAP _NORMALMAP + passType: 4 + - keywords: + passType: 8 + - keywords: SHADOWS_DEPTH + passType: 8 + - keywords: SHADOWS_DEPTH _ALPHABLEND_ON + passType: 8 + - keywords: SHADOWS_DEPTH _ALPHABLEND_ON _METALLICGLOSSMAP + passType: 8 + - keywords: SHADOWS_DEPTH _METALLICGLOSSMAP + passType: 8 + - keywords: _ALPHABLEND_ON + passType: 8 + - keywords: _METALLICGLOSSMAP + passType: 8 diff --git a/Samples~/AvatarCreatorSamples/AvatarCreatorWizard/Scripts/UI/AvatarCreatorStateMachine.cs b/Samples~/AvatarCreatorSamples/AvatarCreatorWizard/Scripts/UI/AvatarCreatorStateMachine.cs index d5a97d2b..59d04bb6 100644 --- a/Samples~/AvatarCreatorSamples/AvatarCreatorWizard/Scripts/UI/AvatarCreatorStateMachine.cs +++ b/Samples~/AvatarCreatorSamples/AvatarCreatorWizard/Scripts/UI/AvatarCreatorStateMachine.cs @@ -113,7 +113,12 @@ private void OnStateChanged(StateType current, StateType previous) private bool CanShowBackButton(StateType current, StateType previous) { - return current != startingState && current != previous; + return AuthManager.IsSignedIn switch + { + true => current != StateType.AvatarSelection, + false => current != startingState && current != previous + }; + } public void OnCustomizeDraft(string avatarId) diff --git a/Samples~/AvatarCreatorSamples/AvatarCreatorWizard/Scripts/UI/SelectionScreens/AvatarCreatorSelection.cs b/Samples~/AvatarCreatorSamples/AvatarCreatorWizard/Scripts/UI/SelectionScreens/AvatarCreatorSelection.cs index a64923a2..d0aa0d3c 100644 --- a/Samples~/AvatarCreatorSamples/AvatarCreatorWizard/Scripts/UI/SelectionScreens/AvatarCreatorSelection.cs +++ b/Samples~/AvatarCreatorSamples/AvatarCreatorWizard/Scripts/UI/SelectionScreens/AvatarCreatorSelection.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading; using System.Threading.Tasks; using ReadyPlayerMe.AvatarCreator; using ReadyPlayerMe.Core; using UnityEngine; -using UnityEngine.Serialization; using UnityEngine.UI; using TaskExtensions = ReadyPlayerMe.AvatarCreator.TaskExtensions; diff --git a/package.json b/package.json index 5c888726..ba31710a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.readyplayerme.core", - "version": "7.1.1", + "version": "7.2.0", "displayName": "Ready Player Me Core", "description": "This Module contains all the core functionality required for using Ready Player Me avatars in Unity, including features such as: \n - Module management and automatic package setup logic\n - Avatar loading from .glb files \n - Avatar creation \n - Avatar and 2D render requests \n - Optional Analytics\n - Custom editor windows\n - Sample scenes and assets", "unity": "2020.3",