This workflow combines Google Apps Script and Unity Editor code to streamline downloading assets from Google Drive
to Unity
. No more needing to manually download and import, it can all be done with a single button click!
This workflow is best run in bulk, once every week or every two weeks, as some of the processes are slow.
Warning
You must be connected to the Internet for this workflow to work!
▶️ Watch demoDriveToUnity-AssetWorkflow.mp4
- In Google Drive
, create a parent folder that you want. Title it whatever you need, having an "Art" parent folder and "2D" and "3D" subfolders is recommended. Upload your assets to their appropriate folders. See example Drive setup here.
Note
The entire folder must be public, otherwise Unity will throw an error when sending the Web Request. Below is a recommended folder structure.
- Art //This folder should be public, if the parent folder is public, all children folders and content will be as well.
|-- 2D
| -- UIButtons
|-- 3D
| -- Flowers
| -- etc
| -- etc
-
Create a spreadsheet in Google Drive
and create an Apps Script
by clicking Extensions > Apps Script. This will open the Apps Script IDE in a new tab. (no text needs to be input on the Google Sheet
, the running the Apps Script
will take care of that!)
-
In Unity
, navigate to a file called
AssetSync.gs
(Path:/Assets/AppsScript/AssetSync.gs
). Copy and paste the contents of this script into the Apps Scriptand save.
Expand to See Apps Script
Code
Starting from the root folder, it will check every sub folder and grab all assets of type:
png
,jpg
,jpeg
,psd
,fbx
,obj
(technically, it can download any asset of any type, but these are the ones you should generally be uploading, as this is a tool for syncing art assets!). It will then turn each of those assets into a downloadble link and populate that link, along with the asset path, to the Google Sheet.
// doGet is how Unity can trigger running this script! function doGet(e) { try { // Check if folderId was provided AND is not empty if (!e.parameter.folderId || e.parameter.folderId.trim() === "") { return ContentService.createTextOutput(JSON.stringify({ status: "error", message: "Missing required parameter: folderId" })).setMimeType(ContentService.MimeType.JSON); } var folderId = e.parameter.folderId; populate(folderId); // return the success response return ContentService.createTextOutput(JSON.stringify({ status: "success", message: "Spreadsheet populated successfully" })).setMimeType(ContentService.MimeType.JSON); } catch (error) { return ContentService.createTextOutput(JSON.stringify({ status: "error", message: error.toString() })).setMimeType(ContentService.MimeType.JSON); } } function populate(folderId) { var files = getAllPngsInFolder(folderId) // Sort by folder path, then by filename files.sort(function(a, b) { if (a.path === b.path) { return a.name.localeCompare(b.name); } return a.path.localeCompare(b.path); }); var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); sheet.clear(); sheet.appendRow(["File Name", "Direct Download Link", "Folder Path"]); files.forEach(function(fileObj) { sheet.appendRow([fileObj.name, fileObj.link, fileObj.path]); }); } //get all pngs in the folder and SUB folders function getAllPngsInFolder(folderId, parentPath) { var folder = DriveApp.getFolderById(folderId); var files = folder.getFiles(); var subfolders = folder.getFolders(); var results = []; var currentPath = parentPath ? parentPath + "/" + folder.getName() : folder.getName(); // Collect PNGs in current folder while (files.hasNext()) { var file = files.next(); var allowedTypes = ["image/png", "image/jpeg", "application/pdf"]; // etc. var fileName = file.getName().toLowerCase(); if (allowedTypes.includes(file.getMimeType()) || fileName.endsWith(".fbx") || fileName.endsWith(".obj")|| fileName.endsWith(".psd")) { results.push({ name: file.getName(), link: "https://drive.google.com/uc?export=download&id=" + file.getId(), path: currentPath }); } } // Recurse into subfolders while (subfolders.hasNext()) { var subfolder = subfolders.next(); results = results.concat(getAllPngsInFolder(subfolder.getId(), currentPath)); } return results; } function convertDriveLink(url) { if (!url) return ""; var match = url.match(/\/d\/(.*)\/view/); if (match && match[1]) { return "https://drive.google.com/uc?export=download&id=" + match[1]; } return "Invalid link"; }
Running this Apps Script will populate the Asset Manager Google Sheet
to look like this. Note that it has 3 columns: Asset Name, Download Link, File Path, and it will output onto the Sheet by folder first, then file name (alphabetically).
- Running the Apps Script
for the first time will require giving permissions manually. Click "Run" at the top. This will open a permissions window. Select all (as this will allow the Apps Script
to access your Drive and write to the sheet).
- Copy and paste your root Google Drive
folder ID into "Folder ID". The folder ID is the
string
after "/folders/" until the "?". For example, the link: https://drive.google.com/drive/folders/1pKIJrvFdqV3zNfmC8rYZzgt6yGeWsrE7?usp=sharing has a folder ID of1pKIJrvFdqV3zNfmC8rYZzgt6yGeWsrE7
💡 Engineering Explanation
It is recommended to paste in the correct folder ID, but there are several checks in place to grab a valid ID (as long as you have a valid ID somewhere in the string, it will work). If you enter an invalid ID (e.g. `123abc`), an error will be thrown and output to the console.
-
At the top right, click Deploy > New Deployment (Web App) and set the access to "Anyone". Copy that link and paste it into "Apps Script Link".
-
Go back to the Google Sheet
File > Share > Publish. Copy that link and paste it into "Read from Link"
-
In Unity, create a new .csv (recommended to call it
AssetList.csv
) and drag and drop that into "Target CSV". -
At this point, the "Run Apps Script" button should appear. This button will not be visible unless all 3 fields are filled, and a warning will show. Click "Run Apps Script". This action will:
a. Run the Apps Script, which searches for all .pngs in the Art folder and all of its subfolders, generate a downloadable link, and then populate that to the AssetManager Google Sheet
.
b. Populate
AssetList.csv
(in the Unityproject, Path:
Assets/Art/AssetList.csv
) with the same data from the AssetManager Google Sheet. You can preview the assets in the
AssetList.csv
by expanding the CSV Preview.
-
Once that process is complete (the editor window will show a status that says "Successfully synced!" or "Ready to Sync" (if 3 seconds have passed), click “Populate Assets”. This action will:
a. Download all .pngs from their downloadable links. The Unity folder structure will mirror the Drive structure under /Assets/Art/__2D. If an asset already exists, it will overwrite the data. If an asset does not already exist, it will create it to the correct folder. (If a folder doesn’t exist, it will also generate the folder)
There is an example setup attached with this repo.
Google Sample Folder: This is the folder with example assets that will be downloaded.
Example CSV: the example .csv Unity will read from.
Apps Script : The code used to generate downloadable links for all assets in the Google Sample Folder and populate it to the Example .csv. This code (and web app link) are accessible from the Example .csv under Extensions > Apps Script
-
On Google Drive
, navigate to AssetManager.
-
From the AssetManager Google Sheet
, open the Apps Script editor under Extensions > Apps Script. The Apps Script
editor will open in a new tab.
- Click Deploy > Manage Deployments in the top right and copy the Web App link for the latest deployment.
- Open the Drive Image Sync Editor under Tools > Drive Image Sync. Paste the link into “Apps Script Link”.
- On the Asset Manager Google Sheet
, get the published, downloadable link under File > Share > Publish to Web as a csv. Paste that link into “Read from Link”.
-
Assign the
AssetList.csv
TextAsset to "Target CSV". -
Paste this folder ID into Unity
:
1pKIJrvFdqV3zNfmC8rYZzgt6yGeWsrE7
-
Once it’s done, click “Populate Assets”. You will see the download progress.
- You can upload new assets and create new folders in Google Drive
. No problem! Try to come up with a good asset name and don’t change it after. Try to not move assets to other folders, or rename folders as well.
💡 Engineering Explanation
This won’t break the path, it will just create two assets in the Unity project. E.g. you have an asset named “Cat” in Unity. You upload the same .png but renamed it to "Cat-Brown” and still have "Cat" in Drive, the asset will appear in Unity twice with the different names. You can remove the duplicate asset from Unity either by manually removing it, or removing it from Drive.
- For updating existing assets, replace the existing asset by uploading a file with the exact same name and selecting “Replace existing file”.
Warning
Do not delete the old one and upload a new one, as this will break the download path.
- If an asset was updated in Drive, you do not need to sync the .csv again. This is because the asset download path is the same (if the asset was replaced as mentioned above). But, for best practice just, never hurts to Sync again :’)
- Ability to change Sprite Import settings via the editor window (right now they all download as a Sprite, alpha is transparency, Single Sprite mode.
- Ability to stop the download/populate
Common Errors When Running the Tool
Error Code | Console Output | Debugging Steps |
---|---|---|
0 | Cannot resolve destination host | Not connected to the Internet. Connect to the Internet! |
403 | HTTP/1.1 403 Forbidden | Apps Script does not have the correct permissions (see Step #5 in Initial Setup for steps |
