-
-
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; } | |
| } | |
| } |
Does it happen to fix it if you do the steps below manually, or do you still get the same issue?
Taking this file, and making a copy of it C:\Program Files\Unity\Hub\Editor\2019.3.0f1\Editor\Data\Resources\Layouts\Default.wlt
Then renaming the new copy to: CurrentLayout-default.dwlt
Then removing the file from C:\Users\xxxx\OneDrive\Desktop\new\Library\CurrentLayout-default.dwlt and then putting the new copy in it's place?
no it doesn't work
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
got it dude this works faster for me i guess. this does not currently fix the problem