Phylliida / UnityWindowsCapture

A framework to capture individual windows or the entire desktop in Unity
MIT License
132 stars 15 forks source link

Editor hangs on 2nd play #4

Open Salbrox opened 5 years ago

Salbrox commented 5 years ago

In the editor when I play it works first time around and i can see both my monitors rendered great. However, the second time I press play it just hangs indefinitely. I checked to see if things were not being disposed of but the dispose methods are being called. Also when I build windows standalone it doesn't work, i just see the sky box. Any help is much appreciated!

On another note I had to remove all the chromium stuff as it would not run at all with that included. Its fine though as i only need desktop capture.

Salbrox commented 5 years ago

Looks like it only happens when VS is attached to Unity for debugging. Doesn't explain why build doesn't work though.

Phylliida commented 5 years ago

Did you make sure to add the current scene to the list before pressing build?

tkbala commented 5 years ago

Yes. I am facing a similar issue. The Unity editor seems to hang on some runs, and the code doesn't seem to run on build. Not sure why though. @Phylliida - any thoughts?

will-platy commented 5 years ago

Same issues. Any help would be greatly appreciated! Thanks @Phylliida

will-platy commented 5 years ago

Same issues. Any help would be greatly appreciated! Thanks @Phylliida

Actually, I just got it to work @tkbala. This issue was finding the shaders using Shader.find(). Played around with the suggestions here: https://answers.unity.com/questions/222523/shader-not-working-in-web-player.html

The key seemed to be to add the WinCapture shaders to the "Always Include Shaders" in the project settings. Hope this helps you. Checked this fix in two projects, 100% works.

ps. I am using the 2018 branch.

thesambassador commented 4 years ago

I have the same issues as the people above and am not able to find a solution.

The project works fine in the Editor on the first play. When I click Play again, the editor hangs and becomes unresponsive. Also when I do a build, nothing happens.

In order to get anything working at all, I had to delete the System.Drawing.dll file that's in the project and copy the one from my Unity's Mono directory. Not sure if that is involved.

I've added the scene to the build. I've included the WinCapture shaders in the Always Include Shaders just in case. I've also tried creating a plane and material with the DesktopShader in the scene and referencing that, instead of creating it at runtime like in your example. My update looks like this:

bool didChange = false;
Texture2D desktopTexture = desktopCapture.GetWindowTexture(out didChange);

if (didChange) {

            desktopPlane.transform.localScale = new Vector3(1920 * windowScale, 1, 1080 * windowScale);
            print(desktopCapture.desktopWidth);
            desktopPlaneRenderer.material.mainTexture = desktopTexture;
}

@Phylliida, any thoughts? @will-platy are you sure that there's nothing else that you did to get this working? Is there some other code that is necessary here that I'm missing?

Phylliida commented 4 years ago

Often why this happens is that you aren't cleaning up things properly (make sure you call dispose on objects you create)

grufkork commented 4 years ago

Having the same issue here, this library works wonders except for the part where it crashes :P How does one properly dispose of everything? On the classes I use, I can only find a dispose function on DesktopCapture. I have verified that the function in fact is called. If it helps, I have my script attached to a SteamVR camera, but I had the same issue with standard cameras too. I'm using the built-in RP by the way. Really neat lib otherwise, it does just what it needs to and integrates neatly with Unity-native stuff like Texture2D!

Phylliida commented 4 years ago

I can confirm that I can reproduce this issue with the standard example, looking into it now

Phylliida commented 4 years ago

Hey so I'll be looking more into this to see if I can figure out the issue, but in the meantime, my project does two things:

  1. Mirror windows using GDI, letting you mirror as many windows as you want (as long as they support mirror by GDI), at the cost of lower performance
  2. Use the Windows 8-10 Desktop Duplication API to mirror desktop.

(technically it also includes support for the Chromium thing, but it's a little buggy and not really recommended)

I have confirmed that this issue only happens for 2. If you don't use any DesktopCapture objects and only use the WindowCaptureManager type things, you should not run into the issue of unity crashing on playing again. That gives worse performance, but is nice for capturing individual windows (to capture chrome, you need to turn off hardware acceleration in chrome advanced settings). You can also capture the entire desktop using this method (the included example does this by only returning true in IsGoodWindow if (windowLowerTitle.Contains("desktop")). Make IsGoodWindow return true for everything to see lots of other windows.

If you want to capture just the desktop using Windows 8-10 Desktop Duplication API, I would actually recommend using https://github.com/hecomi/uDesktopDuplication instead, it is a much cleaner implementation of the same functionality. I'll be looking into this issue to see if I can fix it, but it may take me a little while. It seems that the way I was cleaning up things in the plugin (the cpp code) is no longer correct.

grufkork commented 4 years ago

It hit me that it might be that it doesn't have time to dispose and stop everything properly before it stops completely, because when I run Dispose() dispose early in Update() (only once though, got a flag for whether it's already been called or not) I can restart multiple times. I haven't tried the process inspection tool-thingy to see if there are any residual threads though.

Anyways, your library has worked fine as I can simply disable it while testing, and once I'm actually running it I don't need it to be restartable :) I'm using it for making video calls in VR, so I can see those calling and anything else I might need. Got to try it last Friday, and it worked great! But I'll check the other library too, thank you for the tip!

Phylliida commented 4 years ago

Yup I realized that the ExampleUsage doesn't properly dispose of the DesktopCapture object, oops. It's not the issue, when properly disposing of it you still have this issue of the editor hanging on the 2nd play. But it's still worth pointing out.

For anyone interested, the correct place to dispose of it in the ExampleUsage.cs should be either in OnApplicationQuit or OnDestroy, something like this:

    bool cleanedUp = false;
    void Cleanup()
    {
        if (!cleanedUp)
        {
            cleanedUp = true;
            desktopCapture1.Dispose();
        }
    }

    private void OnDestroy()
    {
        Cleanup();   
    }

    private void OnApplicationQuit()
    {
        Cleanup();
    }
}
cuikeqiang commented 1 year ago

Seems like it's blocking at this line: int textLen = GetWindowTextLength(Handle); (in Runtime/WindowInfo.cs)

I changed the code to this and it worked:

        public bool UpdateWindowTitle()
        {
            // int textLen = GetWindowTextLength(Handle);
            // if (textLen == 0)
            // {
            //     Title = "";
            //     return false;
            // }
            // else
            {
                var sb = new StringBuilder(200 + 1);
                GetWindowText(Handle, sb, sb.Capacity);

                Title = sb.ToString();
                return true;
            }
        }

@Phylliida You can try it and tell us what's wrong in GetWindowTextLength. :)