-
-
Save instance-id/3161cc2b5343db5bc3cef494d83a7449 to your computer and use it in GitHub Desktop.
#!/usr/bin/env pwsh | |
<# | |
.NOTES | |
============================================================ | |
Last Edit: 5/29/2021 | |
Created by: instance.id (https://github.com/instance-id) | |
Platform: Windows/Linux | |
Filename: unitytool.ps1 | |
PSVersion: Last tested with 7.2-preview5 | |
Requirements: fd : https://github.com/sharkdp/fd | |
============================================================ | |
.DESCRIPTION | |
Unity multi tool, launcher, version upgrade, package/asset installer, default layout fix | |
.EXAMPLE | |
.\unitytool.ps1 "MyProjectName" -Fix -Run | |
.\unitytool.ps1 "MyProjectName" -fr -s | |
.\unitytool.ps1 . -s | |
.PARAMETER Project | |
The name of the project/root folder | |
.PARAMETER Path | |
The Path to the project root folder | |
.PARAMETER Fix | |
Automatically fix the "Failed to load layout window" issue | |
.PARAMETER Run | |
Start the project up after fixing the issue if included, or will simply open the project if fix is not needed. | |
.PARAMETER FRun | |
Both -Fix and -Run combined for ease of use | |
.PARAMETER Open | |
Open the folder in the file explorer | |
.PARAMETER Setup | |
Add custom packages and assets to the project before starting it | |
.PARAMETER Create | |
Create a new Unity project, must include Project as name and Path for location | |
.PARAMETER Backup | |
Execute the specified backup script and pass it the project name and location | |
.PARAMETER SetVersion | |
Open project with a version that is different than the currently specified version | |
#> | |
Param ( | |
[Parameter(Position = 0)] | |
[string]$Project, | |
[Alias('p')][string]$Path, | |
[Alias('f')][switch]$Fix, | |
[Alias('r')][switch]$Run, | |
[Alias('o')][switch]$Open, | |
[Alias('s')][switch]$Setup, | |
[Alias('fr')][switch]$FRun, | |
[Alias('b')][switch]$Backup, | |
[Alias('c')][switch]$Create, | |
[Alias('v')][string]$SetVersion | |
) | |
# Checking to make sure project name and Unity version are included | |
if ($Project) { Write-Host "Locating ${Project}..." } | |
else { Write-Host 'Unity project name required...'; exit } | |
# -- Possibly needed for starting batch mode, so I have heard. | |
# -- I didn't find that I needed it, though | |
$licenseFile = '/.local/share/unity3d/Unity/Unity_lic.ulf' | |
# -------------------------------------- Packages | |
# -- Either create an environmental variable named $PACKAGES | |
# -- which points to the location you store your custom packages | |
# -- or change $packages below to the hardcoded path | |
# $packages = "/path/to/custom/packages" | |
$assets = $env:ASSETS | |
$packages = $env:PACKAGES | |
<# | |
Example package setup: | |
$packageDict = [PSCustomObject]@{ | |
'com.domain.githubpackage1' = "https://github.com/com.domain.package2/MyPackage1" | |
'com.domain.localpackage2' = "file:${packages}/com.domain.package2/Assets/instance.id/Package2" | |
'com.domain.package3' = "file:${packages}/com.domain.package2/Assets/instance.id/Package3" | |
} | |
#> | |
$packageDict = [PSCustomObject]@{ 'id.instance.projectinit' = "file:${packages}/id.instance.projectinit/Assets/instance.id/ProjectInit" } | |
# ------------------------------- System Specific | |
$projectBackupScript = '' | |
if ($IsWindows) { | |
$driveDir = 'E:' | |
$projectBackupScript = "$HOME/.backup/_projects/projects_backup.ps1" | |
$hubLocation = 'C:/Program Files/Unity/Hub/Editor' | |
$unity = 'Unity.exe' | |
} | |
if ($IsLinux) { | |
$driveDir = '/mnt/x' | |
$projectBackupScript = "$HOME/.backup/_projects/projects_backup.ps1" | |
$hubLocation = "$HOME/Unity/Hub/Editor" | |
$unity = 'Unity' | |
} | |
$projectFound = $false | |
$packageResult = $false | |
# ------------------------------------------------------------------------------------------ | |
# Input the root folder location that contain your Unity projects -------------------------- | |
# Ex: "C:/Unity/MyProjects" : If located in multiple folders, | |
# enter the parent which contains all of them. This now uses fd to search, and it is | |
# extremely fast. | |
# (Prior search, which took 3-4 minutes on a Sabrent 4.0 Rocket NVME, fd takes 4-5 seconds) | |
# -- Default Unnity project search root | |
$location = '/mnt/x/' | |
# -- Default is overridden by passing $Path from CLI | |
if (!([string]::IsNullOrEmpty($Path))) { $location = $Path } | |
# -- If you plan to also use my backup script, put it's path here | |
$projectBackupScript = "$HOME/.backup/_projects/projects_backup.ps1" | |
# -- Needed variables for file names and locations | |
# ------------------------------ Layout | |
$originalLayout = 'Default.wlt' | |
$destinationLayout = 'CurrentLayout-default.dwlt' | |
$destinationLayoutPath = "/Library/${destinationLayout}" | |
$editorLocation = '' | |
# ---------------------------- Location | |
$folderName = '' | |
$projectPath = '' | |
$destinationPath = '' | |
# --------------------- Project Version | |
$versionNumber = '' | |
$projectVersionFile = '' | |
$projectVersionTxt = 'ProjectVersion.txt' | |
$editorVersions = [System.Collections.ArrayList]::new() | |
# --------------------------------------------- Helper Functions | |
# -------------------------------------------------------------- | |
# ----------------------------- Select project version | |
function SelectVersion { | |
$editorPaths = (get-item $hubLocation).FullName | gci -Directory | |
$editorPaths | % { $versionNum = (get-item $_).BaseName; $null = $editorVersions.Add($versionNum) } | |
$editorVersions.Reverse() | |
$index = 0 | |
$indexVal = '' | |
write-host "Select Version of Unity for Project: ${Project}" | |
foreach ($item in $editorVersions) { | |
if ($index -lt 10) { $indexVal = "[0${index}]" } | |
else { $indexVal = "[${index}]" } | |
write-host "${indexVal} ${item}" | |
$index++ | |
} | |
[int]$result = Read-Host 'Enter integer value from above' | |
return $result | |
} | |
# ------------------------ Get project current version | |
function GetVersion { | |
$versionSearch = ‘*m_EditorVersion: *’ | |
$file_data = Get-Content $projectVersionFile | Where-Object { $_ -like "${versionSearch}"; } | |
$separator = ': ' | |
$versionString = $file_data.split($separator); | |
$version = ${versionString}[1] | |
return $version | |
} | |
# ----------------------------- Add packages to project manifest | |
# -------------------------------------------------------------- | |
function AddPackages { | |
# ----------------- Copy Standard Assets folder into project | |
$assetSource = [System.IO.Path]::Combine($assets, 'Standard Assets', 'Essentials') | |
$assetPath = [System.IO.Path]::Combine($projectPath, 'Assets') | |
if (Test-Path $assetSource) { | |
if (!(Test-Path $([System.IO.Path]::Combine($projectPath, 'Assets', 'Standard Assets', 'Essentials')))) { | |
Copy-item -Force -Recurse -Path $assetSource -Destination $assetPath | |
} else { write-host 'Essential assets already exist in project' } | |
} | |
# --------- Edit the project manifest to add custom packages | |
$manifest = [System.IO.Path]::Combine($projectPath, 'Packages', 'manifest.json') | |
if (!(Test-Path $manifest)) { Write-Host 'Could not locate project manifest.json. Skipping package injection' -ForegroundColor Red; return } | |
$json = Get-Content -Encoding UTF8 $manifest | ConvertFrom-Json | |
$packageDict.PSObject.Properties | % { | |
if (!($json.dependencies | Get-Member -Type NoteProperty -Name "$($_.Name)")) { | |
write-host "Adding Package $($_.Name) to manifest.json" | |
$json.dependencies | Add-Member -Type NoteProperty -Name "$($_.Name)" -Value "$($_.Value)" -ErrorAction SilentlyContinuepower | |
$packageResult = $true | |
} else { write-host "Package $($_.Name) already exists" } | |
} | |
if ($packageResult) { $json | ConvertTo-Json | Set-Content -Encoding UTF8 $manifest } | |
} | |
function WriteError($type, $path, $folder) { Write-Host "Error creating folder: ${folder} in ${path}"; exit } | |
# -------------------------------------------- Setup new project | |
# -------------------------------------------------------------- | |
function CreateProjectStructure($projPath, $version) { | |
$as = 'Assets' | |
$ps = 'ProjectSettings' | |
$pv = $projectVersionTxt | |
$pSettingsTxt = @" | |
m_EditorVersion: ${version} | |
m_EditorVersionWithRevision: ${version} | |
"@ | |
$projectPath = [System.IO.Path]::Combine($projPath, $Project) | |
$pPath = [System.IO.Path]::Combine($projectPath, 'ProjectSettings') | |
if (!(Test-Path $projectPath)) { New-Item -Path $projPath -ItemType Directory -Name $Project -Force } | |
$fPath = get-item $projectPath | |
if (Test-Path $fPath) { New-Item -Path $fPath -ItemType Directory -Name $as } else { WriteError 'Folder' $fPath $as } | |
if (Test-Path $fPath) { New-Item -Path $fPath -ItemType Directory -Name $ps } else { WriteError 'Folder' $fPath $ps } | |
if (Test-Path $pPath) { New-Item -Path $pPath -ItemType File -Name $pv -Value $pSettingsTxt } else { WriteError 'File' $pPath $pv } | |
write-host 'Project structure created..' | |
return $fPath | |
} | |
function CreateProject { | |
if ($([string]::IsNullOrEmpty($SetVersion))) { | |
$result = SelectVersion | |
$versionNumber = $editorVersions[$result] | |
} else { $versionNumber = $SetVersion } | |
write-host "Editor Version ${versionNumber}" | |
$editorLocation = "$hubLocation/$versionNumber/Editor/$unity" | |
if (!(Test-Path $editorLocation)) { Write-Host "Unity Editor version: ${versionNumber} not found. Please download or open in another version" -ForegroundColor Red; exit } | |
if ( [String]::IsNullOrEmpty($Path)) { $Path = Read-Host 'Path for new project?' } | |
$projectPath = CreateProjectStructure $Path $versionNumber | |
if ($Setup.IsPresent) { | |
write-host 'Creating initial project files' | |
& $editorLocation -projectPath $projectPath -Quit -BatchMode -manualLicenseFile $licenseFile | |
write-host "Adding custom packages to ${Project}"; AddPackages | |
& $editorLocation -projectPath $projectPath -Quit -BatchMode -manualLicenseFile $licenseFile | |
& $editorLocation -projectPath $projectPath | |
} else { & $editorLocation -projectPath $projectPath } | |
exit | |
} | |
# --------------------------------- Process the project requests | |
function ProcessProject { | |
Write-Host "Unity project $Project found: $projectPath" | |
if ($([string]::IsNullOrEmpty($SetVersion))) { | |
$versionNumber = GetVersion | |
$editorLocation = [System.IO.Path]::Combine($hubLocation, $versionNumber, 'Editor', $unity) | |
} else { | |
$versionNumber = $SetVersion | |
$editorLocation = [System.IO.Path]::Combine($hubLocation, $SetVersion, 'Editor', $unity) | |
Write-Host "Updating project editor version to ${setversion}. Using: ${editorLocation}" | |
} | |
# ------------------------------------------ Fix Layout file | |
if ($FRun -or $Fix) { | |
$destinationPath = [System.IO.Path]::Combine(${projectPath}, ${destinationLayoutPath}) | |
$originalLayoutFile = "$hubLocation/$versionNumber/Editor/Data/Resources/Layouts/$originalLayout" | |
if (Test-Path $originalLayoutFile) { | |
Write-Host "Original layout file for Unity version $versionNumber found..." | |
if ( [System.IO.File]::Exists($destinationPath)) { | |
Write-Host "Probematic layout file found: $destinationPath" | |
# Backup original layout file | |
Write-Host "Creating backup of original layout file at: ${destinationPath}.bak" | |
Copy-item -Force -Verbose -Path ${destinationPath} -Destination "${destinationPath}.bak" | |
# Copy Default layout for editor version from install folder and rename to required filename | |
Write-Host "Copying default layout for version $versionNumber to $Project Library..." | |
Copy-item -Force -Verbose -Path $originalLayoutFile -Destination "${destinationPath}" | |
} else { | |
Write-Host "Could not locate probematic layout file at location: $destinationPath" -ForegroundColor Red | |
Write-Host "Please check that Library folder exists at path: ${projectPath}/Library" -ForegroundColor Red | |
} | |
} else { | |
Write-Host "Unity $versionNumber not found" -ForegroundColor Red; return; | |
} | |
Write-Host 'Layout fix completed' -ForegroundColor Green | |
} | |
# --------------------------- Install any packages or assets | |
if ($Setup.IsPresent) { write-host "Adding custom packages to ${Project}"; AddPackages } | |
# -------------------------------------------- Start Project | |
if ($FRun.IsPresent -or $Run.IsPresent) { | |
if (Test-Path $editorLocation) { | |
Write-Host "Starting Project: ${Project}" -ForegroundColor Green | |
if ($packageResult) { | |
# -- Quickly opens the project in batch mode and automatically close it so that the newly added packages | |
# -- can be added, then opens it again normally, so that it will be ready to use | |
& $editorLocation -projectPath $projectPath -Quit -BatchMode <# -manualLicenseFile $licenseFile #> | |
& $editorLocation -projectPath $projectPath <# -manualLicenseFile $licenseFile #> | |
} else { | |
& $editorLocation -projectPath $projectPath <# -manualLicenseFile $licenseFile #> | |
} | |
} else { Write-Host "Unity Editor version: ${versionNumber} not found. Please download or open in another version" -ForegroundColor Red } | |
} | |
# ------------------------------------ Open Project Location | |
if ($Open.IsPresent) { | |
Write-Host "Opening location: ${foundProjectLocation}" | |
if ($IsWindows) { & explorer.exe $projectPath } else { & nemo $projectPath } | |
} | |
# ------------------------------------------- Backup project | |
if ($Backup.IsPresent) { | |
Write-Host "Backing up project ${Project}: ${foundProjectLocation}" | |
& $projectBackupScript -Project $Project -Source $projectPath | |
} else { Write-Host "Project: ${Project} Editor: ${versionNumber} Location: ${foundProjectLocation}" } | |
} | |
# -------------------------------------------- Program Execution | |
# -------------------------------------------------------------- | |
if ($Create) { | |
CreateProject | |
} | |
if ($Project -eq '.') { | |
$projectPath = [System.IO.Directory]::GetCurrentDirectory() | |
$projectName = (get-item $projectPath).Directory.BaseName | |
$projectVersionFile = [System.IO.Path]::Combine(${projectPath}, 'ProjectSettings', $projectVersionTxt) | |
if (!(Test-Path $projectVersionFile)) { Write-Host 'Could not find project version file' -ForegroundColor Red; exit } | |
if ($([string]::IsNullOrEmpty($SetVersion))) { $versionNumber = GetVersion } else { $versionNumber = $SetVersion } | |
$editorLocation = "$hubLocation/$versionNumber/Editor/$unity" | |
if (!(Test-Path $editorLocation)) { | |
Write-Host "Unity Editor version: ${versionNumber} not found. Please download or open in another version" -ForegroundColor Red; exit | |
} | |
if ($Setup.IsPresent) { | |
# -- Add custom packages and assets to project and run project | |
write-host "Adding custom packages to ${projectName}"; AddPackages | |
# -- Determine if Unity is already opened with this project | |
$Programs = 'Unity' | |
$Running = Get-Process -Name $Programs -ErrorAction SilentlyContinue | |
# -- If project is already running, exit script | |
$exists = $false | |
foreach ($item in $Running.CommandLine) { | |
write-host $item | |
if ( $item.ToString().EndsWith($Project)) { | |
$exists = $true | |
write-host "${Project} already running" | |
exit | |
} | |
} | |
} | |
if ($packageResult) { | |
# -- Quickly opens the project in batch mode and automatically close it so that the newly added packages | |
# -- can be added, then opens it again normally, so that it will be ready to use | |
& $editorLocation -projectPath $projectPath -Quit -BatchMode <# -manualLicenseFile $licenseFile #> | |
& $editorLocation -projectPath $projectPath <# -manualLicenseFile $licenseFile #> | |
} else { | |
& $editorLocation -projectPath $projectPath <# -manualLicenseFile $licenseFile #> | |
} | |
exit | |
} else { | |
# -- Using fd's extremely fast search, look for ProjectVersion.txt file in the location specified | |
[String[]]$results = & fd "${projectVersionTxt}" "${location}" --xdev --follow --hidden | |
# -- Iterate all found files and determine if they are Unity projects, and which is the one we requested | |
for ($i = 0; $i -lt $results.Count; $i++) { | |
$projectVersionFile = $results[$i] | |
$projectPath = (get-item $projectVersionFile).Directory.Parent | |
$folderName = (get-item $projectPath).BaseName | |
if ($folderName -eq $Project) { $projectFound = $true; } else { continue; } | |
# -- If the correct project has been found, pass it to the ProcessProject method | |
if ($projectFound) { ProcessProject } else { Write-Host "${Project} not found, or it is not a project folder." -ForegroundColor Red; exit; } | |
} | |
} |
You could try deleting everything within C:\Users\xxxx\OneDrive\Desktop\new\Library\ (or just move the folder to another location while Unity is closed) and then open Unity again so it can reimport everything. This can take a long time, though, if you have a lot of large files that it has to serialize, but unfortunately, even then it is not 100% guaranteed to work. I don't really know what causes this bug, but it drives me insane. I am assuming that you can't just update to a newer version of the editor? That would certainly be the ideal solution, but of course, that can't always be done with production projects.
When I upgrade, I encounter many errors in the project.
I will try this now
bro i need to update the version. We tried everything, it doesn't work, thank you very much
no it doesn't work