It does redirect to stdout, but as documentation says, stdout on Windows for GUI applications is not the console. Console is stdout for console applications, and as you observe, if you capture stdout from Unity in a standard application, and then write it to console, it appears just fine (which proves that Unity does output to stdout).
This is not exactly accurate. A Windows GUI process, will, by default, not inherit stdout handles, but the important caveat here is that they can, and more importantly, it should. It is absolutely be Unityâs job to use these available APIs to redirect stdout correctly and have a functioning build system. You have a command that is expected to be used from the console, it should be expected to behave like a console app. It doesnât matter that itâs running a GUI behind the scenes, itâs your job to figure out the correct APIs to use and fix this objectively broken behavior. This is why Windows API exposes these process flags.
The handle inheritance is set up by whatever launches a process, not the process itself. If whatever launches Unity makes it inherit stdout handle, then Unity will happily use it (as https://discussions.unity.com/t/622567/20 shows). Cmd.exe doesnât set up stdout inheritance for GUI programs and thatâs why you donât see it there.
By the way, Unity 2023.1 contains a second executable (unity.com) thatâs compiled as a console application, which will make cmd.exe pass stdout to Unity correctly. So you can now invoke that instead of you want it to run synchronously through cmd.exe.
Is documentation available anywhere for this functionality?
I am interested but encountering some issues and canât find any documentation actually detailing whatâs going on here.
Thanks
What issues are you seeing?
Iâve redirected my pointer from the .exe to the .com, trying with and without -logfile, and Iâm getting what appears to be a total activity freeze.
No response, no output, nothing.
Our existing pipeline is running through Powershell Start-Process, so Iâm wondering if that has something to do with it, but at the moment I havenât been able to test that yet.
Are you able to capture the dump of the process through task manager when it freezes? Does it only happen via .com and not .exe?
The .exe works and outputs to the output log file in realtime. Had no issues.
This is the code;
Start-Process -FilePath $unity -Wait -NoNewWindow -ArgumentList `
"-batchmode", `
"-quit", `
"-projectPath $unityProjectPath", `
"-logfile $unityLogFile", `
"-buildWindowsPlayer $clientBuildDestination"
When I redirected it towards the .com I removed the -logfile argument, trying both -logfile ` and no argument at all.
Iâll try and capture a dump for you now, the tricky thing is that Iâm not getting any visible errors at all. It just sort of goes into some kind of standby like nothing is happening and no output is being redirected.
I imagine there may be something Iâm missing here, but Iâm not sure what.
Edit:
Further investigation leads me to believe that Unity is indeed finishing compiling and completing the builds.
However, not only is my implementation not reading back to the console, but the console doesnât receive a completion record and as such gets stuck at that part of the script while it endlessly waits for one.
Try using â-logfile -â. That will make Unity output to stdout.
@Tautvydas-Zilys We want to log our logs to file but log some specific messages to console in Linux. We want to log specific messages to console like FPS statistiscs etc.
Currently we use â-nographics -logFile game_server.logâ as parameter and we want to keep this while only outputting statistics to console in Linux. Is there any way to accomplish this?
Thatâd be pretty hard, -logFile argument quite literally overrides the stdout handle in order to capture everything in the log file.
Hey, this has worked for the most part now.
Output is being correct passed back to Powershell, howeverânow it forcefully closes the powershell instance when it returns rather than allowing it to continue executing.
Iâve tried -Wait and also $process.WaitForExit() with -Passthru neither of which work as expected.
Using -NoNewWindow is also mandatory since otherwise it flashes a cmd on the screen for half a second and then forcefully closes the cmd and the powershell.
So far, this is the currently working code with the unexpected application exit.
$unityBuildProcess = Start-Process -FilePath $unity -NoNewWindow -PassThru -ArgumentList `
"-batchmode", `
"-quit", `
"-projectPath $unityProjectPath", `
"-logFile -", `
"-buildWindowsPlayer $clientBuildDestination"
$unityBuildProcess.WaitForExit()
Read-Host -prompt "`nFinished! Press any key to exit...`n"
The Read-Host following will never execute.
That is weird, we donât really interact with the parent process. Does the same thing happen if you start Unity from cmd.exe?
Just wanted to share our final setup here, for Unity 2023.2. This runs in Powershell, and we have it wrapped up in a Run-Unity commandlet.
& "C:\Program Files\Unity\Hub\Editor\$Env:UNITY_VERSION\editor\Unity.exe" -batchmode -disable-assembly-updater -silent-crashes -logFile - $AdditionalArguments | Write-Output
This will stream output from Unity as the output handle of the commandlet, meaning you can pipe it around as normal in Powershell.
A few notes:
- The
-logFile -is necessary, otherwise it will suppress all output. - The
| Write-Outputis required because it redirects the stdout handle to the output of the script. - You must use
Write-Output, notWrite-HostorWrite-Default, both of which write to the host console, not the stdout of the command.
Alternatively, you can remove the Write-Output if you execute editor\Unity.com instead of editor\Unity.exe. However, weâve chosen not to do that, given that the console build is undocumented, and Iâm not sure what lies in wait there.