Last active
October 28, 2025 18:00
-
-
Save sebas77/567156ec7f545c04c5b7dd4578a0c791 to your computer and use it in GitHub Desktop.
Windows Building Machine Hub-less Unity Installer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ============================================================================= | |
| # unityinstall.ps1 | |
| # ----------------------------------------------------------------------------- | |
| # Hub-less Windows install of: | |
| # • Unity Editor (Windows) + Windows IL2CPP + Linux IL2CPP | |
| # • Android Support module for the Editor | |
| # • Android toolchain: Microsoft OpenJDK 17, Android SDK (cmdline-tools, platform-tools, | |
| # build-tools 36.0.0, platform android-36), and NDK r27c | |
| # • Developer CLIs: AWS CLI v2, Git for Windows (Git Bash), jq (to C:\Windows\System32) | |
| # | |
| # Usage (PowerShell): | |
| # .\unityinstall.ps1 -Hash <UNITY_HASH> -Version <UNITY_VERSION> ` | |
| # [-LicenseServer <URL>] [-LicenseToolset <STRING>] [-Force] | |
| # | |
| # Examples: | |
| # https://download.unity3d.com/download_unity/4a4dcaec6541/Windows64EditorInstaller/UnitySetup64-6000.2.6f2.exe | |
| # .\unityinstall.ps1 -Hash 4a4dcaec6541 -Version 6000.2.6f2 | |
| # .\unityinstall.ps1 -Hash 4a4dcaec6541 -Version 6000.2.6f2 ` | |
| # -LicenseServer http://3.224.150.72:8080 -LicenseToolset LicenseServer_1375782320542_3 | |
| # .\unityinstall.ps1 -Hash 4a4dcaec6541 -Version 6000.2.6f2 -Force | |
| # | |
| # Optional flags (mapping from Linux-style you might see elsewhere): | |
| # --licenseServer <URL> => -LicenseServer <URL> | |
| # --licenseToolset <STR> => -LicenseToolset <STR> | |
| # -f / --force => -Force | |
| # -h / --help => Get-Help .\unityinstall.ps1 [-Detailed] | |
| # | |
| # Defaults: | |
| # -LicenseToolset defaults to 'LicenseServer_1375782320542_3' | |
| # | |
| # Notes: | |
| # - Editor/module downloads are skipped if already present unless -Force is used. | |
| # - Machine-level env vars (JAVA_HOME, ANDROID_*, UNITY_PATH) are set; open a new shell to pick them up. | |
| # - jq writes to C:\Windows\System32; run an elevated shell if you see access denied. | |
| # - Every downloaded URL is echoed for transparency. | |
| # ============================================================================= | |
| param( | |
| [Parameter(Mandatory=$true)] [string]$Hash, | |
| [Parameter(Mandatory=$true)] [string]$Version, | |
| [string]$LicenseServer, | |
| [string]$LicenseToolset = 'LicenseServer_1375782320542_3', | |
| [switch]$Force | |
| ) | |
| # -------------------------------------------- | |
| # Hardening | |
| # -------------------------------------------- | |
| $ErrorActionPreference = 'Stop' | |
| Write-Host "Unity hash: $Hash" | |
| Write-Host "Unity version: $Version" | |
| # -------------------------------------------- | |
| # Versioned tool variables (ONLY place for versions) | |
| # -------------------------------------------- | |
| $JdkVersion = "17.0.16" | |
| $AndroidCmdlineToolsBuild = "13114758" | |
| $AndroidNdkVersion = "r27c" | |
| $AndroidBuildToolsVersion = "36.0.0" | |
| $AndroidPlatformApiLevel = "36" | |
| # URLs (ZIP JDK to control target folder) | |
| $OpenJdkUrl = "https://aka.ms/download-jdk/microsoft-jdk-${JdkVersion}-windows-x64.zip" | |
| $SdkUrl = "https://dl.google.com/android/repository/commandlinetools-win-${AndroidCmdlineToolsBuild}_latest.zip" | |
| $NdkUrl = "https://dl.google.com/android/repository/android-ndk-${AndroidNdkVersion}-windows.zip" | |
| # Installation paths | |
| $ToolsBaseDir = 'C:\UnityTools' | |
| $JdkPath = Join-Path $ToolsBaseDir "jdk-$JdkVersion" | |
| $SdkPath = Join-Path $ToolsBaseDir "android-sdk" | |
| $NdkPath = Join-Path $ToolsBaseDir "android-ndk-$AndroidNdkVersion" | |
| # Unity paths | |
| $InstallRoot = Join-Path 'C:\Unity' $Hash # Unity ROOT (module installers must point here) | |
| $EditorDir = Join-Path $InstallRoot 'Editor' | |
| $UnityExe = Join-Path $EditorDir 'Unity.exe' | |
| # Temp dir | |
| $TmpDirObj = New-Item -ItemType Directory -Force -Path (Join-Path $env:TEMP ("unitydl_" + [Guid]::NewGuid())) | |
| $Tmp = $TmpDirObj.FullName | |
| # -------------------------------------------- | |
| # Helpers | |
| # -------------------------------------------- | |
| function Ensure-Dir ($Path) { | |
| if (-not (Test-Path -LiteralPath $Path)) { | |
| [void](New-Item -ItemType Directory -Path $Path -Force) | |
| } | |
| } | |
| function Get-WebFile { | |
| param([string]$Url, [string]$OutPath) | |
| Write-Host "[URL] $Url" | |
| Invoke-WebRequest -Uri $Url -OutFile $OutPath -UseBasicParsing | |
| } | |
| function Test-IL2CPPInstalled { | |
| param([string]$EditorDir) | |
| $il2cppExe = Join-Path $EditorDir "Data\il2cpp\build\deploy\il2cpp.exe" | |
| return (Test-Path -LiteralPath $il2cppExe) | |
| } | |
| function Test-AndroidSupportInstalled { | |
| param([string]$EditorDir) | |
| return Test-Path -LiteralPath (Join-Path $EditorDir "Data\PlaybackEngines\AndroidPlayer") | |
| } | |
| # Linux IL2CPP presence (folder-based check is sufficient for deciding whether to (re)install) | |
| function Test-LinuxSupportInstalled { | |
| param([string]$EditorDir) | |
| return Test-Path -LiteralPath (Join-Path $EditorDir "Data\PlaybackEngines\LinuxStandaloneSupport") | |
| } | |
| # -------------------------------------------- | |
| # Toolchain detection (VS C++ + Windows SDK) for IL2CPP | |
| # -------------------------------------------- | |
| function Test-VCToolsPresent { | |
| $vswhere = 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' | |
| if (-not (Test-Path -LiteralPath $vswhere)) { return $false } | |
| $out = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath 2>$null | |
| return [string]::IsNullOrWhiteSpace($out) -eq $false | |
| } | |
| function Test-WindowsSDKPresent { | |
| try { | |
| $reg = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows\v10.0' -ErrorAction Stop | |
| if ($reg.InstallationFolder) { return $true } | |
| } catch { } | |
| $signtool = Get-ChildItem 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.*\x64\signtool.exe' -ErrorAction SilentlyContinue | Select-Object -First 1 | |
| return $null -ne $signtool | |
| } | |
| function Ensure-VsBuildTools-AndSDK { | |
| param([switch]$ForceInstall = $false) | |
| $needVC = $ForceInstall.IsPresent -or (-not (Test-VCToolsPresent)) | |
| $needSDK = $ForceInstall.IsPresent -or (-not (Test-WindowsSDKPresent)) | |
| if (-not $needVC -and -not $needSDK) { | |
| Write-Host "[TOOLS] VS C++ tools and Windows SDK already present. Skipping." | |
| return | |
| } | |
| $VsBtExe = Join-Path $Tmp 'vs_BuildTools.exe' | |
| Get-WebFile -Url 'https://aka.ms/vs/17/release/vs_BuildTools.exe' -OutPath $VsBtExe | |
| if ($needVC) { | |
| $btArgsCore = @( | |
| '--quiet','--wait','--norestart','--nocache', | |
| '--installPath','"C:\BuildTools"', | |
| '--add','Microsoft.VisualStudio.Workload.VCTools', | |
| '--add','Microsoft.VisualStudio.Component.VC.Tools.x86.x64', | |
| '--add','Microsoft.VisualStudio.Component.VC.Redist.14.Latest' | |
| ) -join ' ' | |
| Write-Host "[INSTALL] VS Build Tools (C++ toolchain)…" | |
| Start-Process -FilePath $VsBtExe -ArgumentList $btArgsCore -NoNewWindow -Wait | |
| } else { | |
| Write-Host "[TOOLS] C++ toolchain present (vswhere check)." | |
| } | |
| if ($needSDK) { | |
| $btArgsSdk = @( | |
| '--quiet','--wait','--norestart','--nocache', | |
| '--installPath','"C:\BuildTools"', | |
| '--add','Microsoft.VisualStudio.Component.Windows11SDK.22621' | |
| ) -join ' ' | |
| Write-Host "[INSTALL] Windows SDK (10.0.22621)…" | |
| Start-Process -FilePath $VsBtExe -ArgumentList $btArgsSdk -NoNewWindow -Wait | |
| } else { | |
| Write-Host "[TOOLS] Windows SDK already present." | |
| } | |
| $vswhere = 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' | |
| if (Test-Path -LiteralPath $vswhere) { | |
| Write-Host "[VERIFY] vswhere:" | |
| & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath | |
| } else { | |
| Write-Warning "[VERIFY] vswhere.exe not found (VS Installer not present or path changed)." | |
| } | |
| $sdkSigntool = Get-ChildItem 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.*\x64\signtool.exe' -ErrorAction SilentlyContinue | Select-Object -First 1 | |
| if ($sdkSigntool) { | |
| Write-Host "[VERIFY] Windows SDK SignTool: $($sdkSigntool.FullName)" | |
| } else { | |
| Write-Warning "[VERIFY] Windows SDK (10.0.*) not found under Windows Kits\10\bin. Ensure SDK installed." | |
| } | |
| } | |
| # Detect AWS CLI v2 presence | |
| function Test-AwsCliV2Present { | |
| try { | |
| $null = Get-Command aws -ErrorAction Stop | |
| $out = & aws --version 2>$null | |
| if ($out -match '^aws-cli/(\d+)\.') { return ([int]$matches[1] -ge 2) } | |
| } catch { } | |
| # Fallback: default install path | |
| return (Test-Path 'C:\Program Files\Amazon\AWSCLIV2\aws.exe') | |
| } | |
| # -------------------------------------------- | |
| # Create directories | |
| # -------------------------------------------- | |
| Ensure-Dir $ToolsBaseDir | |
| Ensure-Dir $InstallRoot | |
| # -------------------------------------------- | |
| # Unity Editor (skip if already installed) | |
| # -------------------------------------------- | |
| $EditorUrl = "https://download.unity3d.com/download_unity/$Hash/Windows64EditorInstaller/UnitySetup64-$Version.exe" | |
| if ((-not (Test-Path $UnityExe)) -or $Force) { | |
| Write-Host "[DOWNLOAD] Unity Editor" | |
| $EditorExe = Join-Path $Tmp 'UnitySetup64.exe' | |
| Get-WebFile -Url $EditorUrl -OutPath $EditorExe | |
| Write-Host "[INSTALL] Unity Editor → $InstallRoot" | |
| $process = Start-Process -FilePath $EditorExe -ArgumentList @("/S", "/D=$InstallRoot") -Wait -PassThru | |
| if ($process.ExitCode -ne 0) { | |
| Write-Warning "Unity Editor installer exited with code $($process.ExitCode)" | |
| } | |
| } else { | |
| Write-Host "[SKIP] Editor already installed at $UnityExe" | |
| } | |
| # -------------------------------------------- | |
| # Windows IL2CPP (skip if already installed) | |
| # -------------------------------------------- | |
| $Il2cppUrl = "https://download.unity3d.com/download_unity/$Hash/TargetSupportInstaller/UnitySetup-Windows-IL2CPP-Support-for-Editor-$Version.exe" | |
| if ((-not (Test-IL2CPPInstalled -EditorDir $EditorDir)) -or $Force) { | |
| Write-Host "[DOWNLOAD] Windows IL2CPP" | |
| $Il2cppExe = Join-Path $Tmp 'UnitySetup-Windows-IL2CPP.exe' | |
| Get-WebFile -Url $Il2cppUrl -OutPath $Il2cppExe | |
| Write-Host "[INSTALL] Windows IL2CPP → $InstallRoot" | |
| $process = Start-Process -FilePath $Il2cppExe -ArgumentList @("/S", "/D=$InstallRoot") -Wait -PassThru | |
| if ($process.ExitCode -ne 0) { | |
| Write-Warning "Windows IL2CPP installer exited with code $($process.ExitCode)" | |
| } | |
| } else { | |
| Write-Host "[SKIP] Windows IL2CPP already installed" | |
| } | |
| # -------------------------------------------- | |
| # Linux IL2CPP Support (skip if already installed) | |
| # -------------------------------------------- | |
| $LinuxIl2cppUrl = "https://download.unity3d.com/download_unity/$Hash/TargetSupportInstaller/UnitySetup-Linux-IL2CPP-Support-for-Editor-$Version.exe" | |
| if ((-not (Test-LinuxSupportInstalled -EditorDir $EditorDir)) -or $Force) { | |
| Write-Host "[DOWNLOAD] Linux IL2CPP" | |
| $LinuxIl2cppExe = Join-Path $Tmp 'UnitySetup-Linux-IL2CPP.exe' | |
| Get-WebFile -Url $LinuxIl2cppUrl -OutPath $LinuxIl2cppExe | |
| Write-Host "[INSTALL] Linux IL2CPP → $InstallRoot" | |
| $process = Start-Process -FilePath $LinuxIl2cppExe -ArgumentList @("/S", "/D=$InstallRoot") -Wait -PassThru | |
| if ($process.ExitCode -ne 0) { | |
| Write-Warning "Linux IL2CPP installer exited with code $($process.ExitCode)" | |
| } | |
| } else { | |
| Write-Host "[SKIP] Linux IL2CPP already installed" | |
| } | |
| # -------------------------------------------- | |
| # Prerequisite toolchain: VS 2022 C++ Build Tools + Windows SDK | |
| # (required by IL2CPP build pipeline; install only if missing) | |
| # -------------------------------------------- | |
| try { | |
| Ensure-VsBuildTools-AndSDK | |
| } catch { | |
| Write-Warning "[TOOLS] Failed to install VS Build Tools / SDK: $($_.Exception.Message)" | |
| } | |
| # -------------------------------------------- | |
| # CLI tools: AWS CLI, Git (Git Bash), jq | |
| # -------------------------------------------- | |
| # AWS CLI (skip if v2 already installed; otherwise install via MSI URL) | |
| if (Test-AwsCliV2Present) { | |
| $v = (& aws --version 2>$null) | |
| Write-Host "[TOOLS] AWS CLI v2 already installed. $v" | |
| } else { | |
| Write-Host "[TOOLS] Installing AWS CLI v2…" | |
| $awsProc = Start-Process -FilePath "msiexec.exe" -ArgumentList @("/i","https://awscli.amazonaws.com/AWSCLIV2.msi","/qn","/norestart") -Wait -PassThru | |
| if ($awsProc.ExitCode -ne 0) { | |
| Write-Warning "[TOOLS] AWS CLI MSI exit code $($awsProc.ExitCode)" | |
| } else { | |
| try { | |
| $v = (& aws --version 2>$null) | |
| if ($v) { Write-Host "[VERIFY] $v" } | |
| } catch { } | |
| } | |
| } | |
| # Git for Windows (brings Git Bash); install if not present | |
| $gitBash = "C:\Program Files\Git\bin\bash.exe" | |
| if (-not (Test-Path $gitBash)) { | |
| Write-Host "[TOOLS] Installing Git for Windows…" | |
| $gitExe = Join-Path $Tmp 'Git-64-bit.exe' | |
| Get-WebFile -Url 'https://github.com/git-for-windows/git/releases/download/v2.51.1.windows.1/Git-2.51.1-64-bit.exe' -OutPath $gitExe | |
| $gitProc = Start-Process -FilePath $gitExe -ArgumentList @('/VERYSILENT','/NORESTART','/NOCANCEL','/SP-') -Wait -PassThru | |
| if ($gitProc.ExitCode -ne 0) { Write-Warning "[TOOLS] Git installer exit code $($gitProc.ExitCode)" } | |
| } | |
| if (Test-Path $gitBash) { | |
| $gitVer = & "$gitBash" -lc 'git --version 2>/dev/null || true' | |
| if ($gitVer) { Write-Host "[VERIFY] $gitVer" } | |
| # Ensure ONLY Git Bash (bash.exe) is on PATH | |
| $gitBin = 'C:\Program Files\Git\bin' | |
| if (-not (Test-Path $gitBin)) { $gitBin = Split-Path $gitBash -Parent } | |
| $machinePath = [Environment]::GetEnvironmentVariable('Path','Machine') | |
| if ((Test-Path $gitBin) -and ($machinePath -notlike "*$gitBin*")) { | |
| $machinePath = $machinePath.TrimEnd(';') + ";" + $gitBin | |
| [Environment]::SetEnvironmentVariable('Path', $machinePath, 'Machine') | |
| Write-Host "[ENV] Added Git Bash to Machine PATH: $gitBin" | |
| } | |
| if ((Test-Path $gitBin) -and ($env:Path -notlike "*$gitBin*")) { | |
| $env:Path = $env:Path + ";" + $gitBin | |
| Write-Host "[ENV] Added Git Bash to session PATH: $gitBin" | |
| } | |
| } else { | |
| Write-Warning "[TOOLS] Git Bash not found after install." | |
| } | |
| # jq (install via Git Bash curl into System32 as requested) | |
| if (Test-Path $gitBash) { | |
| Write-Host "[TOOLS] Installing jq via Git Bash curl…" | |
| & "$gitBash" -lc 'curl -L -o /c/Windows/System32/jq.exe https://github.com/stedolan/jq/releases/latest/download/jq-win64.exe' | |
| if (Test-Path 'C:\Windows\System32\jq.exe') { | |
| $jqv = & 'C:\Windows\System32\jq.exe' --version 2>$null | |
| if ($jqv) { Write-Host "[VERIFY] jq: $jqv" } | |
| } else { | |
| Write-Warning "[TOOLS] jq install appears to have failed. (If not elevated, writing to System32 may be blocked.)" | |
| } | |
| } else { | |
| Write-Warning "[TOOLS] Skipped jq install because Git Bash is unavailable." | |
| } | |
| # -------------------------------------------- | |
| # Android Support (skip if already installed) | |
| # -------------------------------------------- | |
| $AndroidSupportUrl = "https://download.unity3d.com/download_unity/$Hash/TargetSupportInstaller/UnitySetup-Android-Support-for-Editor-$Version.exe" | |
| if ((-not (Test-AndroidSupportInstalled -EditorDir $EditorDir)) -or $Force) { | |
| Write-Host "[DOWNLOAD] Android Support" | |
| $AndroidSupportExe = Join-Path $Tmp 'UnitySetup-Android-Support.exe' | |
| Get-WebFile -Url $AndroidSupportUrl -OutPath $AndroidSupportExe | |
| Write-Host "[INSTALL] Android Support → $InstallRoot" | |
| $process = Start-Process -FilePath $AndroidSupportExe -ArgumentList @("/S", "/D=$InstallRoot") -Wait -PassThru | |
| if ($process.ExitCode -ne 0) { | |
| Write-Warning "Android Support installer exited with code $($process.ExitCode)" | |
| } | |
| } else { | |
| Write-Host "[SKIP] Android Support already installed" | |
| } | |
| # -------------------------------------------- | |
| # OpenJDK Installation (ZIP → deterministic target) | |
| # -------------------------------------------- | |
| if ((-not (Test-Path $JdkPath)) -or $Force) { | |
| Write-Host "[DOWNLOAD] OpenJDK" | |
| $OpenJdkZip = Join-Path $Tmp "jdk-$JdkVersion.zip" | |
| Get-WebFile -Url $OpenJdkUrl -OutPath $OpenJdkZip | |
| Write-Host "[EXTRACT] OpenJDK" | |
| if (Test-Path $JdkPath) { Remove-Item $JdkPath -Recurse -Force } | |
| $JdkTempExtract = Join-Path $Tmp "jdk-extract" | |
| if (Test-Path $JdkTempExtract) { Remove-Item $JdkTempExtract -Recurse -Force } | |
| Expand-Archive -Path $OpenJdkZip -DestinationPath $JdkTempExtract -Force | |
| $jdkRootFolder = Get-ChildItem -Path $JdkTempExtract -Directory | Select-Object -First 1 | |
| if ($null -eq $jdkRootFolder) { Write-Error "OpenJDK extraction failed - no root folder found"; exit 1 } | |
| if ($jdkRootFolder.FullName -ne $JdkPath) { | |
| Move-Item -Path $jdkRootFolder.FullName -Destination $JdkPath -Force | |
| } | |
| } else { | |
| Write-Host "[SKIP] OpenJDK already installed at $JdkPath" | |
| } | |
| # -------------------------------------------- | |
| # Android SDK Installation (cmdline-tools) | |
| # -------------------------------------------- | |
| if ((-not (Test-Path $SdkPath)) -or $Force) { | |
| Write-Host "[DOWNLOAD] Android SDK Command Line Tools" | |
| $SdkZip = Join-Path $Tmp "commandlinetools.zip" | |
| Get-WebFile -Url $SdkUrl -OutPath $SdkZip | |
| Write-Host "[INSTALL] Android SDK → $SdkPath" | |
| Ensure-Dir $SdkPath | |
| Expand-Archive -Path $SdkZip -DestinationPath "$SdkPath" -Force | |
| } else { | |
| Write-Host "[SKIP] Android SDK already installed at $SdkPath" | |
| } | |
| # Ensure 'cmdline-tools\latest\bin' layout (Unity/gradle friendly) | |
| $CmdlineToolsRoot = Join-Path $SdkPath "cmdline-tools" | |
| $LatestDir = Join-Path $CmdlineToolsRoot "latest" | |
| if (Test-Path $CmdlineToolsRoot) { | |
| if (-not (Test-Path $LatestDir)) { | |
| Write-Host "[SDK] Reorganizing cmdline-tools → latest" | |
| Ensure-Dir $LatestDir | |
| Get-ChildItem -Path $CmdlineToolsRoot -Force | | |
| Where-Object { $_.Name -ne "latest" } | | |
| ForEach-Object { Move-Item -LiteralPath $_.FullName -Destination $LatestDir -Force } | |
| } | |
| } | |
| # Resolve sdkmanager path (supports both structures just in case) | |
| $CmdlineToolsBin = Join-Path $LatestDir "bin" | |
| if (-not (Test-Path $CmdlineToolsBin)) { $CmdlineToolsBin = Join-Path $CmdlineToolsRoot "bin" } | |
| $sdkManager = Join-Path $CmdlineToolsBin "sdkmanager.bat" | |
| # -------------------------------------------- | |
| # Install core SDK packages (non-interactive, robust STDIN feed) | |
| # -------------------------------------------- | |
| if (Test-Path $sdkManager) { | |
| # Ensure env for this session (sdkmanager relies on JAVA_HOME) | |
| $env:JAVA_HOME = $JdkPath | |
| $env:ANDROID_SDK_ROOT = $SdkPath | |
| # Prepare a big 'yes' file and feed it via STDIN (Windows-safe) | |
| $yesFile = Join-Path $Tmp "sdk-yes.txt" | |
| Set-Content -Path $yesFile -Encoding ASCII -NoNewline -Value (("y`r`n") * 400) | |
| Write-Host "[SDKMANAGER] Accepting licenses (stdin file)…" | |
| & cmd.exe /c "type `"$yesFile`" | `"$sdkManager`" --sdk_root=`"$SdkPath`" --licenses" | |
| if ($LASTEXITCODE -ne 0) { Write-Warning "[SDKMANAGER] License acceptance returned $LASTEXITCODE (continuing)"; } | |
| $packages = @( | |
| "platform-tools", | |
| "build-tools;$AndroidBuildToolsVersion", | |
| "platforms;android-$AndroidPlatformApiLevel" | |
| ) | |
| foreach ($package in $packages) { | |
| Write-Host "[SDKMANAGER] Installing $package" | |
| & cmd.exe /c "type `"$yesFile`" | `"$sdkManager`" --sdk_root=`"$SdkPath`" `"$package`"" | |
| if ($LASTEXITCODE -ne 0) { Write-Error "[SDKMANAGER] Failed to install $package (exit $LASTEXITCODE)"; exit 1 } | |
| } | |
| } else { | |
| Write-Warning "[SDK] sdkmanager not found at $sdkManager - skipping package installation" | |
| } | |
| # -------------------------------------------- | |
| # Android NDK Installation (ZIP → deterministic target) | |
| # -------------------------------------------- | |
| if ((-not (Test-Path $NdkPath)) -or $Force) { | |
| Write-Host "[DOWNLOAD] Android NDK" | |
| $NdkZip = Join-Path $Tmp "android-ndk.zip" | |
| Get-WebFile -Url $NdkUrl -OutPath $NdkZip | |
| Write-Host "[INSTALL] Android NDK → $NdkPath" | |
| if (Test-Path $NdkPath) { Remove-Item $NdkPath -Recurse -Force } | |
| Expand-Archive -Path $NdkZip -DestinationPath $ToolsBaseDir -Force | |
| $expected = Join-Path $ToolsBaseDir "android-ndk-$AndroidNdkVersion" | |
| if (-not (Test-Path $expected)) { | |
| # Fallback: pick the dir that matches android-ndk-* exactly for our version, else fail | |
| $ndkCandidates = Get-ChildItem -Path $ToolsBaseDir -Directory -Filter "android-ndk-$AndroidNdkVersion*" | |
| $ndk = $ndkCandidates | Sort-Object Name -Descending | Select-Object -First 1 | |
| if ($null -eq $ndk) { Write-Error "NDK extraction failed - no 'android-ndk-$AndroidNdkVersion*' folder found"; exit 1 } | |
| $expected = $ndk.FullName | |
| } | |
| if ($expected -ne $NdkPath) { | |
| Move-Item -Path $expected -Destination $NdkPath -Force | |
| } | |
| } else { | |
| Write-Host "[SKIP] Android NDK already installed at $NdkPath" | |
| } | |
| # -------------------------------------------- | |
| # Environment Variables (always set/update) | |
| # -------------------------------------------- | |
| Write-Host "[ENV] Setting environment variables..." | |
| [System.Environment]::SetEnvironmentVariable('JAVA_HOME', $JdkPath, 'Machine') | |
| [System.Environment]::SetEnvironmentVariable('ANDROID_HOME', $SdkPath, 'Machine') | |
| [System.Environment]::SetEnvironmentVariable('ANDROID_SDK_ROOT', $SdkPath, 'Machine') | |
| [System.Environment]::SetEnvironmentVariable('ANDROID_NDK_HOME', $NdkPath, 'Machine') | |
| # Build tools dir (after install) | |
| $BuildToolsDir = Join-Path $SdkPath "build-tools\$AndroidBuildToolsVersion" | |
| # Update PATH (dedup + ensure existence now that installs finished) | |
| $machinePath = [System.Environment]::GetEnvironmentVariable('Path', 'Machine') | |
| $pathsToAdd = @( | |
| "$JdkPath\bin", | |
| (Join-Path $CmdlineToolsBin ""), # ensures trailing \bin path | |
| "$SdkPath\platform-tools", | |
| $BuildToolsDir | |
| ) | ForEach-Object { $_.TrimEnd('\') } | Select-Object -Unique | |
| foreach ($p in $pathsToAdd) { | |
| if (-not (Test-Path $p)) { Write-Warning "[ENV] Skipping PATH add, not found: $p"; continue } | |
| if ($machinePath -notlike "*$p*") { $machinePath = $machinePath.TrimEnd(';') + ";" + $p } | |
| } | |
| [System.Environment]::SetEnvironmentVariable('Path', $machinePath, 'Machine') | |
| # Set for current session too | |
| $env:JAVA_HOME = $JdkPath | |
| $env:ANDROID_HOME = $SdkPath | |
| $env:ANDROID_SDK_ROOT = $SdkPath | |
| $env:ANDROID_NDK_HOME = $NdkPath | |
| foreach ($p in $pathsToAdd) { | |
| if ((Test-Path $p) -and ($env:Path -notlike "*$p*")) { $env:Path = $env:Path + ";" + $p } | |
| } | |
| # -------------------------------------------- | |
| # License Configuration (optional) | |
| # -------------------------------------------- | |
| if ($LicenseServer) { | |
| Write-Host "[LICENSE] Writing license configuration..." | |
| $ServiceCfgMachineDir = Join-Path $env:PROGRAMDATA 'Unity\config' | |
| $ServiceCfgMachinePath = Join-Path $ServiceCfgMachineDir 'services-config.json' | |
| Ensure-Dir $ServiceCfgMachineDir | |
| $LicenseConfig = @{ | |
| "licensingServiceBaseUrl" = $LicenseServer | |
| "enableEntitlementLicensing" = $true | |
| "clientConnectTimeoutSec" = 60 | |
| "clientHandshakeTimeoutSec" = 30 | |
| "toolset" = $LicenseToolset | |
| } | ConvertTo-Json -Depth 3 | |
| $LicenseConfig | Out-File -FilePath $ServiceCfgMachinePath -Encoding utf8 -Force | |
| Write-Host "[LICENSE] Written to: $ServiceCfgMachinePath" | |
| } | |
| # -------------------------------------------- | |
| # UNITY_PATH Environment Variable | |
| # -------------------------------------------- | |
| if (Test-Path $UnityExe) { | |
| Write-Host "[ENV] Setting UNITY_PATH..." | |
| [System.Environment]::SetEnvironmentVariable('UNITY_PATH', $UnityExe, 'Machine') | |
| $env:UNITY_PATH = $UnityExe | |
| Write-Host "[ENV] UNITY_PATH set to: $UnityExe" | |
| } else { | |
| Write-Error "Unity binary not found at $UnityExe" | |
| exit 1 | |
| } | |
| # -------------------------------------------- | |
| # Cleanup | |
| # -------------------------------------------- | |
| Write-Host "[CLEAN] Removing temporary files..." | |
| Remove-Item -Path $Tmp -Recurse -Force -ErrorAction SilentlyContinue | |
| # -------------------------------------------- | |
| # Summary | |
| # -------------------------------------------- | |
| Write-Host "" | |
| Write-Host "✔ Installation completed!" | |
| Write-Host "✔ Editor: $InstallRoot\Editor" | |
| Write-Host "✔ Android Support: $EditorDir\Data\PlaybackEngines\AndroidPlayer" | |
| Write-Host "✔ Linux Support: $EditorDir\Data\PlaybackEngines\LinuxStandaloneSupport" | |
| Write-Host "✔ SDK: $SdkPath" | |
| Write-Host "✔ NDK: $NdkPath" | |
| Write-Host "✔ Java: $JdkPath" | |
| if ($LicenseServer) { Write-Host "✔ License config: $ServiceCfgMachinePath" } | |
| Write-Host "✔ UNITY_PATH: $env:UNITY_PATH" | |
| Write-Host "" | |
| Write-Host "Environment variables set:" | |
| Write-Host " JAVA_HOME: $env:JAVA_HOME" | |
| Write-Host " ANDROID_SDK_ROOT: $env:ANDROID_SDK_ROOT" | |
| Write-Host " ANDROID_NDK_HOME: $env:ANDROID_NDK_HOME" | |
| Write-Host " UNITY_PATH: $env:UNITY_PATH" | |
| Write-Host "" | |
| Write-Host "NOTE: You may need to restart your shell or IDE for all environment changes to take effect." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment