This document describes how to upgrade the VRoid SDK ver. 0.0.21 or earlier, which is currently used in Unity applications, to ver. 0.1.0.

1. Updates from 0.0.21 to 0.1.0

For details on the changes, refer to the CHANGELOG.

1.1 Namespace changes

The namespaces of  VRoidSDKVRoidSDK.OAuth, and others have been changed and reorganized in 0.1.0. Features that used to belong to the same namespace have been subdivided and moved to different locations.

In particular, Authentication, HubApi, and HubModelDeserializer, which were implemented until 0.0.21, will be deprecated in 0.1.0, so they have been moved to the namespaces Pixiv.VroidSdk.Unity.Oauth.Legacy and Pixiv.VroidSdk.Api.Legacy. If you want to keep using them, please change the namespace to the appropriate one.

1.2 HubApi and HubModelDeserializer initialization

In 0.0.21 and earlier versions, HubApi and HubModelDeserializer could be used directly after authorization by Authentication, but in 0.1.0, initialization is required before execution. HubModelDeserializer is initialized at the same time as HubApi, so there is no need to explicitly launch the initialization.

class Hoge : MonoBehaviour
{
    void Start()
    {
      Authentication.Instance.Init(_sdkConfiguration.AuthenticateMetaData);

			// HubApi initialization is required from 0.1.0
      //"HubModelDeserializer.Instance" is also initialized automatically
      HubApi.Initialize(Authentication.Instance.Client, _sdkConfiguration.GetConfig());

			// Authorization
      Authentication.Instance.AuthorizeWithExistAccount(...);

			HubApi.GetAccountCharacterModels(
			    count: 10,
			    onSuccess: (List<CharacterModel> characterModels) => {
							HubModelDeserializer.Instance.LoadCharacterAsync(
							    characterModel: characterModels[0],
							    onDownloadProgress: (float progress) => {
							    },
							    onLoadComplete: (GameObject characterObj) => {
											characterObj.transform.parent = this.transform;
							    },
							    onError: (Exception error) => {
							    }
							);
					},
			    onError: (ApiErrorFormat errorFormat) => { /* When an error occurs (e.g. communication error) */ }
			);
    }
}

1.3 Encryption passwords

In 0.0.21 and earlier versions, you could use the API without specifying any particular password for model encryption, but starting from 0.1.0, as a measure for enhanced model data protection, you need to set an arbitrary string of one or more characters as the password for each application.

This password will be passed as an argument in HubModelDeserializer.Instance.LoadCharacterAsync and in the new model loading feature.

HubApi.GetAccountCharacterModels(
    count: 10,
    onSuccess: (List<CharacterModel> characterModels) => {
				HubModelDeserializer.Instance.LoadCharacterAsync(
				    characterModel: characterModels[0],
						encryptPassword: "PASSWORD_FOR_YOUR_APP", // Encryption password added since 0.1.0
				    onDownloadProgress: (float progress) => {
				    },
				    onLoadComplete: (GameObject characterObj) => {
								characterObj.transform.parent = this.transform;
				    },
				    onError: (Exception error) => {
				    }
				);
		},
    onError: (ApiErrorFormat errorFormat) => { /* When an error occurs (e.g. communication error) */ }
);

1.4 The DataModel of the response has been changed to a reference type, requiring action

In 0.0.21 and earlier versions, the response from VRoid Hub was received as a structure (value type), but since 0.1.0, it has been unified as a reference type. Code that expects a value type, such as using a nullable type, will result in a compile error and needs to be corrected.

using Pixiv.VroidSdk.Api.DataModel;

public class Model : ApplicationModel
{
	// Nullable types cause a compile error
-    public Account? CurrentUser { get; set; }
+    public Account CurrentUser { get; set; }

    public Model()
    {
        CurrentUser = null;
    }
}

1.5 Response fix for model material information

If you have obtained the model property information (number of bones, meshes, material information, etc.) before downloading, the type of GltfMaterial#extensions, the material extension information, has changed since 0.1.0. In 0.0.21 and earlier versions, it was Dictionary<string, object>, but now it is GltfMaterialExtension.

This changes the way to determine if KHR_materials_unlit exists.


public override void Init(GltfMaterial baseData)
{
    if (baseData.extensions != null)
    {
         // In 0.0.21 and earlier, it returns the Dictionary.
-        foreach (var x in baseData.extensions)
-        {
-            stringBuilder.AppendLine("\\t" + x.Key + ":" + x.Value);
-        }
   			 // From 0.1.0, objects with KHR_materials_unlit as a member variables become extensions.
+        if(baseData.extensions.KHR_materials_unlit != null)
+				 {
+						stringBuilder.AppendLine("\\t KHR_materials_unlit:{}");
+				 }
    }
}

2. Using New Features and the New API

Starting from VRoid SDK 0.1.0, the interface for using the basic features has been significantly changed.

The new features added in 0.1.0 can be implemented using the new interface.

Please note that the existing Authentication, HubApi, and HubModelDeserializer cannot be used together with the new features.

2.1 Changes to the authorization system

As of 0.1.0, the existing authorization flow using Authentication has been deprecated. From 0.1.0, the authorization process will be carried out using the new Pixiv.VroidSdk.OauthProvider, Pixiv.VroidSdk.Oauth.Client, and  Pixiv.VroidSdk.BrowserProvider.

In addition, the application information configuration using SDKConfiguration is now deprecated as well. In the future, you will need to download the credential.json.bytes file from the application management page and configure it.

class Login : MonoBehaviour
{
    void Start()
    {
				// ThreadContext used for communication
				var context = SynchronizationContext.Current;
				// Load the downloaded credential.json.bytes file
				var credential = Resources.Load<TextAsset>("credential.json");
				// App information used for configuration
				var credentialJson = credential.text;
				// Create a Config to be used for authorization
				var config = OauthProvider.LoadConfigFromCredential(credentialJson);
				// Create a Client to handle OAuth authorization
	      var oauthClient = OauthProvider.CreateOauthClient(config, context);
				// Create a Browser for login
	      var browser = BrowserProvider.Create(oauthClient, config);
				// Account files are saved locally and have not expired
				var isLoggedIn = oauthClient.IsAccountFileExist() && !oauthClient.IsAccessTokenExpired();				
				// Login
				if (!isLoggedIn)
				{
						// If already authorized but expired, it gets reauthorized.
						// Otherwise, opens a browser and starts the authorization flow.
						oauthClient.Login(
							browser,
							(account) => { /*if login is successful*/ },
					    (error) => { /*if login fails*/ }
						);
				}
    }
}

2.2 The new API interface

Since 0.1.0, the HubApi class used to access VRoid Hub's features has been deprecated. We will now use a new API object that uses the authorized Pixiv.VroidSdk.Oauth.Client.

class Login : MonoBehaviour
{
    private Account _account;
    void Start()
    {
        ...
        var oauthClient = OauthProvider.CreateOauthClient(config, context);
	
				// Creates a DefaultApi with the authorizing Client
				var defaultApi = new DefaultApi(oauthClient);
        // The HeartScope API uses HeartApi
        // var heartApi = new HeartApi(oauthClient);

				// Login
        if (!isLoggedIn)
        {
						// If already authorized but expired, it gets reauthorized. 
						// Otherwise, opens a browser and starts the authorization flow.
						oauthClient.Login(
							browser,
							(account) => {
									// Once the authorization has been completed, API functions are available.
									defaultApi.GetAccount((ac) => _account = ac, (error) => { });
							},
							(error) => { /*if login fails*/ }
						);
				}
    }
}

2.3 Loading models

Since 0.1.0, the HubModelDeserializer used for loading models has been deprecated.

Starting from 0.1.0, ModelLoader will be used to manage model usage and cache storage.

	oauthClient.Login(
		browser,
		(account) => {
			// Initialize the ModelLoader used for model loading
			ModelLoader.Initialize(
				config,                  // Config made from Credentials
				defaultApi,              // Authorized API
				"PASSWORD_FOR_YOUR_APP", // The model's encryption password
				10,                      // Maximum number of caches for a model
				context                  // Main thread's SynchronizationContext
			);

			defaultApi.GetAccountCharacterModels(10, (models) => {
				// Start model loading
				ModelLoader.LoadVrm(
					models[0],  // Model to load
					(gameObject) => {
						// Callback after loading is complete
						gameObject.transform.parent = this.transform;
					},
					(progress) => {
						// Loading progress callback
					},
					(error) => {
						// Callback when an error occurs
					},
	        (VRMData vrmData) => {
	          // Create VRMImporterContext from vrmData
	          return new VRMImporterContext(vrmData);
					}
				);
			}, (error) => { });
		},
    (error) => { /*if login fails*/ }
	);

2.4 Switching the back end for communication

Starting from 0.1.0, you can choose to use the old communication library UnityWebRequest or HttpClient.

By default, Authentication still uses UnityWebRequest.

Create Oauth.Client to work with HttpClient.

Make your selection during the initialization phase.

// Can be specified as the second argument of Authentication
Authentication.Instance.Init(
	metaData,
	new HttpClientDriver(SynchronizationContext.Current)
);

// Can be specified as the second argument when creating a Client from an OauthProvider
var oauthClient = OauthProvider.CreateOauthClient(
	config,
	new UnityWebRequestDriver(SynchronizationContext.Current)
);

2.5 OAuth authorization in desktop apps with Loopback interface redirect

Starting from 0.1.0, OAuth has introduced a system to receive authorization codes via Loopback interface redirect in the authorization flow.

In the past, when authorizing a desktop application, the only way to link VRoid Hub was to manually copy the authorization code from the browser and paste it into the application. This is no longer necessary with the Loopback interface redirect. Just log in on your browser and click the authorization button to complete the linkage.

This system can be implemented using Pixiv.VroidSdk.OauthProvider Pixiv.VroidSdk.Oauth.Client, and Pixiv.VroidSdk.BrowserProvider, as described in "2.1 Changes to the authorization system". Please note that this is not available for the old API, which is now deprecated.

2.5.1 Set http://127.0.0.1 as the redirect URI

スクリーンショット 2021-12-16 16.02.29.png

2.5.2 Download the credential.json.bytes file from the application management page.

Set the redirect URI for desktop devices at http://127.0.0.1 and download it.

If you would like to use the old login method of pasting the authorization code, please set it at urn:ietf:wg:oauth:2.0:oob.

スクリーンショット 2021-12-16 16.03.09.png

2.5.3 Proceed with the authorization as described in "2.1 Changes to the authorization system".

Set the Config as described in "2.1 Changes to the authorization system".

class Login : MonoBehaviour
{
    void Start()
    {
				...
				// Create a Config to be used for authorization
        // In iOS/Android, automatic login using URLScheme
        // In Windows/macOS, login with Loopback interface redirect
        var credential = Resources.Load<TextAsset>("credential.json");
				var config = OauthProvider.LoadConfigFromCredential(credential.text);
				...
    }
}