158 lines
5.6 KiB
PowerShell
158 lines
5.6 KiB
PowerShell
param(
|
|
[string]$UnityPath = $env:UNITY_EXE,
|
|
[string]$ProjectPath,
|
|
[int]$Games = 1,
|
|
[int]$Players = 17,
|
|
[int]$Width = 30,
|
|
[int]$Height = 30,
|
|
[int]$Turns = 100,
|
|
[int]$TimeoutSeconds = 1800,
|
|
[int]$MaxActions = 20000,
|
|
[int]$MaxActionsPerPlayerTurn = 260,
|
|
[string]$OutDir,
|
|
[string]$Difficulty = "LUNATIC",
|
|
[switch]$KeepGoing,
|
|
[switch]$AllowProjectAlreadyOpen,
|
|
[switch]$DryRun
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$repoRoot = Split-Path -Parent $PSScriptRoot
|
|
if ([string]::IsNullOrWhiteSpace($ProjectPath)) {
|
|
$ProjectPath = Join-Path $repoRoot "Unity"
|
|
}
|
|
$ProjectPath = (Resolve-Path $ProjectPath).Path
|
|
|
|
if ([string]::IsNullOrWhiteSpace($OutDir)) {
|
|
$stamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
|
$OutDir = Join-Path $ProjectPath "Logs\AI_Batch\$stamp"
|
|
}
|
|
$OutDir = [System.IO.Path]::GetFullPath($OutDir)
|
|
[System.IO.Directory]::CreateDirectory($OutDir) | Out-Null
|
|
|
|
function Get-ProjectEditorVersion([string]$PathValue) {
|
|
$versionFile = Join-Path $PathValue "ProjectSettings\ProjectVersion.txt"
|
|
if (!(Test-Path $versionFile)) { return $null }
|
|
|
|
foreach ($line in Get-Content -LiteralPath $versionFile) {
|
|
$match = [regex]::Match($line, '^m_EditorVersion:\s*(\S+)')
|
|
if ($match.Success) { return $match.Groups[1].Value }
|
|
}
|
|
|
|
return $null
|
|
}
|
|
|
|
if ([string]::IsNullOrWhiteSpace($UnityPath)) {
|
|
$hubRoot = "C:\Program Files\Unity\Hub\Editor"
|
|
if (Test-Path $hubRoot) {
|
|
$projectEditorVersion = Get-ProjectEditorVersion $ProjectPath
|
|
if (![string]::IsNullOrWhiteSpace($projectEditorVersion)) {
|
|
$projectUnityPath = Join-Path $hubRoot "$projectEditorVersion\Editor\Unity.exe"
|
|
if (Test-Path $projectUnityPath) {
|
|
$UnityPath = $projectUnityPath
|
|
}
|
|
}
|
|
|
|
if ([string]::IsNullOrWhiteSpace($UnityPath)) {
|
|
$UnityPath = Get-ChildItem -Path $hubRoot -Directory |
|
|
Where-Object { $_.Name -match '^2022\.3\.(\d+)' } |
|
|
ForEach-Object {
|
|
[pscustomobject]@{
|
|
Path = Join-Path $_.FullName "Editor\Unity.exe"
|
|
Patch = [int]$Matches[1]
|
|
Name = $_.Name
|
|
}
|
|
} |
|
|
Where-Object { Test-Path $_.Path } |
|
|
Sort-Object Patch, Name -Descending |
|
|
Select-Object -ExpandProperty Path -First 1
|
|
}
|
|
}
|
|
}
|
|
|
|
if ([string]::IsNullOrWhiteSpace($UnityPath) -or !(Test-Path $UnityPath)) {
|
|
throw "Unity.exe not found. Pass -UnityPath or set UNITY_EXE."
|
|
}
|
|
|
|
function Normalize-ProjectPath([string]$PathValue) {
|
|
if ([string]::IsNullOrWhiteSpace($PathValue)) { return "" }
|
|
return [System.IO.Path]::GetFullPath($PathValue).TrimEnd('\', '/').ToLowerInvariant()
|
|
}
|
|
|
|
function Get-ProjectPathFromUnityCommandLine([string]$CommandLine) {
|
|
if ([string]::IsNullOrWhiteSpace($CommandLine)) { return $null }
|
|
$match = [regex]::Match($CommandLine, '(?i)-projectpath\s+(?:"([^"]+)"|([^\s]+))')
|
|
if (!$match.Success) { return $null }
|
|
if ($match.Groups[1].Success) { return $match.Groups[1].Value }
|
|
return $match.Groups[2].Value
|
|
}
|
|
|
|
function Quote-Argument([string]$Value) {
|
|
if ($null -eq $Value) { return '""' }
|
|
if ($Value -notmatch '[\s"]') { return $Value }
|
|
return '"' + ($Value -replace '"', '\"') + '"'
|
|
}
|
|
|
|
$logFile = Join-Path $OutDir "unity_batch.log"
|
|
$failFast = if ($KeepGoing) { "false" } else { "true" }
|
|
$args = @(
|
|
"-batchmode",
|
|
"-projectPath", $ProjectPath,
|
|
"-executeMethod", "TH1_Logic.Editor.AIDirectorBatchRunner.Run",
|
|
"-logFile", $logFile,
|
|
"-aiBatchGames", $Games,
|
|
"-aiBatchPlayers", $Players,
|
|
"-aiBatchWidth", $Width,
|
|
"-aiBatchHeight", $Height,
|
|
"-aiBatchTurns", $Turns,
|
|
"-aiBatchTimeoutSeconds", $TimeoutSeconds,
|
|
"-aiBatchMaxActions", $MaxActions,
|
|
"-aiBatchMaxActionsPerPlayerTurn", $MaxActionsPerPlayerTurn,
|
|
"-aiBatchDifficulty", $Difficulty,
|
|
"-aiBatchFailFast", $failFast,
|
|
"-aiBatchOut", $OutDir
|
|
)
|
|
|
|
Write-Host "[AI.Batch] Unity: $UnityPath"
|
|
Write-Host "[AI.Batch] Project: $ProjectPath"
|
|
Write-Host "[AI.Batch] Output: $OutDir"
|
|
Write-Host "[AI.Batch] Log: $logFile"
|
|
Write-Host "[AI.Batch] Args: $($args -join ' ')"
|
|
|
|
if ($DryRun) {
|
|
exit 0
|
|
}
|
|
|
|
$normalizedProjectPath = Normalize-ProjectPath $ProjectPath
|
|
$openEditors = Get-CimInstance Win32_Process -Filter "Name = 'Unity.exe'" |
|
|
Where-Object {
|
|
$openProject = Get-ProjectPathFromUnityCommandLine $_.CommandLine
|
|
(Normalize-ProjectPath $openProject) -eq $normalizedProjectPath
|
|
}
|
|
|
|
if ($openEditors -and !$AllowProjectAlreadyOpen) {
|
|
$ids = ($openEditors | Select-Object -ExpandProperty ProcessId) -join ", "
|
|
Write-Host "[AI.Batch] ERROR: Unity project is already open by process id(s): $ids. Close the editor first, or pass -AllowProjectAlreadyOpen if you intentionally want Unity to fail fast." -ForegroundColor Red
|
|
exit 20
|
|
}
|
|
|
|
$argumentLine = ($args | ForEach-Object { Quote-Argument ([string]$_) }) -join " "
|
|
$unityProcess = Start-Process -FilePath $UnityPath -ArgumentList $argumentLine -Wait -PassThru -WindowStyle Hidden
|
|
$unityExitCode = if ($null -ne $unityProcess.ExitCode) { $unityProcess.ExitCode } else { 0 }
|
|
|
|
$summaryPath = Join-Path $OutDir "batch_summary.json"
|
|
if (!(Test-Path $summaryPath)) {
|
|
Write-Host "[AI.Batch] ERROR: AI batch did not produce $summaryPath. Check $logFile." -ForegroundColor Red
|
|
if ($unityExitCode -ne 0) { exit $unityExitCode }
|
|
exit 21
|
|
}
|
|
|
|
if ($unityExitCode -ne 0) {
|
|
Write-Host "[AI.Batch] ERROR: Unity exited with code $unityExitCode. Check $logFile." -ForegroundColor Red
|
|
exit $unityExitCode
|
|
}
|
|
|
|
Write-Host "[AI.Batch] Summary: $summaryPath"
|
|
exit 0
|