Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send to Unreal - Not working on mac #19

Closed
goatilus opened this issue Jun 20, 2024 · 22 comments · Fixed by #34
Closed

Send to Unreal - Not working on mac #19

goatilus opened this issue Jun 20, 2024 · 22 comments · Fixed by #34
Assignees
Labels
bug Something isn't working

Comments

@goatilus
Copy link

You mentioned that you tried to work on it but it is not quite working with your VM.
EpicGamesExt#695

I'm on a mac and could help you fixing this issue.

I've tinkered around on the mac like the others with ports and Multicast Bind Address but nothing helps.

Can you tell me how or where I can get logs from unreal regarding the initialisation of the python plugin?

@JoshQuake
Copy link
Collaborator

JoshQuake commented Jun 20, 2024

hey thanks for the assist! In blender can you please open blender console (in Window) and post the result of starting RPC servers? (pipeline->utilities->Start RPC Servers)

I dont think there are logs from initialization. None that I can find at any rate.

@JoshQuake JoshQuake self-assigned this Jun 20, 2024
@goatilus
Copy link
Author

So I played around a bit, added prints to the plugin code locally and started blender via console to see them but until now, I could not really track down completely, what the issue might be.

Via netstat -an | grep 6766 I can see that when I check the box in unreal for remote execution that it actually opens something on 127.0.0.1:6766 as expected but then, the plugin gets a socket timeout when _run_broadcast_listen_thread tries to data = self._broadcast_socket.recv(DEFAULT_RECEIVE_BUFFER_SIZE).

I'm not into python so I can't tell too much what would be needed here to fix it but what I tried was to change this
self._broadcast_socket.sendto(message.to_json_bytes(), self._config.multicast_group_endpoint) (runs on 239.0.0.1 normally)
to self._broadcast_socket.sendto(message.to_json_bytes(), ('127.0.0.1', 6766)) and in fact at least it is sending a ping now but that of course would not lead to a solution, was just playing around.

Here is the output of the plugin running with my custom prints where you can see a bit whats happening. If you need to dig in further, I also have discord and other tools where we could work together on the code and debugging.

image

@JoshQuake
Copy link
Collaborator

Awesome thank you for that! I'm unavailable this weekend but will be back Monday to dig in.

@andygagnon
Copy link

andygagnon commented Jun 24, 2024

I'm also trying to get this to work on a Macbook Pro M1 with Blender 4.1, UE 5.3.

Happy to help with debugging, looking at logs, running blender with debug flags e.g.
https://docs.blender.org/manual/en/latest/advanced/command_line/arguments.html#debug-options

I'm a s/w engineer, so don't hesitate about getting technical.

I also get the message, "No instance of Unreal Editor found", or no message at all.

@jack-yao91
Copy link

jack-yao91 commented Jun 24, 2024

Hey @andygagnon I do not have a M1 mac, but the issue has got to be within this remote_execution.py.

This is what I know. Send to Unreal has its own rpc package it uses for remote calls to unreal and thats all http over 9998

The only reason it needs remote_execution.py is to initially spawn its own rpc server. Once that is created and responding it doesn't need it anymore.

def bootstrap_unreal_with_rpc_server():

So hypothetically, I think just running this in the unreal python REPL would initialize the connection blender needs.

import sys
import os
import threading
for thread in threading.enumerate():
    if thread.name =="UnrealRPCServer":
        thread.kill()
        os.environ["RPC_TIME_OUT"] = "{rpc_response_timeout}"
        sys.path.append(r"{dependencies_path}")
        from rpc import unreal_server
        rpc_server = unreal_server.RPCServer()
        rpc_server.start(threaded=True)

Beyond that I would probably reccomend using a debugger and dropping some breakpoints in remote_exection.py probably some compatibility logic needs to be added for mac somewhere in there, maybe with the sockets api? But maybe it will be easy to find since you are on a M1 Mac.

@JoshQuake
Copy link
Collaborator

JoshQuake commented Jun 27, 2024

remote_execution.py was copied from Epic's Python plugin with no changes. I wonder if there's a conflict?

@JoshQuake
Copy link
Collaborator

JoshQuake commented Jun 27, 2024

I'm terrible with network stuff, but I see suggestions out there to try adding a 1 or 2 second sleep before searching for nodes. It looks like Epic has tried to account for that with a .1s sleep, maybe it's just not long enough for some systems?

Line 118 in dependencies/unreal.py
image

There could also be a secondary issue of some systems not having a 127.0.0.1 loopback thus relying on 0.0.0.0. Based on comments in remote_execution.py, changing the multicast to 0.0.0.0 could very well be a valid solution for some. If that is reliable, it could be possible to see if a 127 loopback adapter exists and if not fallback to 0.

@xBaaDf00d
Copy link

xBaaDf00d commented Jun 29, 2024

Sorry, guys, I am also looking into this issue, trying to figure out what is going on. I ran up a simple test python, to execute against unrealEditor. What I received back is confirmation to me that the problem is entirely blender plugin side.

Using the provided remote_execution,

import time
import send2ue

from send2ue.dependencies import unreal
from send2ue.dependencies import remote_execution

if __name__ ==  '__main__':
    '''
    remote_conf = remote_execution.RemoteExecutionConfig()
    remote_conf.multicast_ttl = 60
    remote_conf.command_endpoint = "0.0.0.0:6766"
    '''
    remot = remote_execution.RemoteExecution()  #remote_conf)
    remot.start()
    connection = unreal.UnrealRemoteCalls()
    unr = unreal.Unreal()

    while 1:
        time.sleep(1)
        print(str(unr))
        print(connection)

I managed to retrieve with tcpdump -A -I en0 & tcpdump -A -I lo0 on my Mac I was able to confirm that these files send appropriate messages into unrealEditor, and unreal editor responds with its node identification as one would expect.

tcpdump -A -ni lo0 host 239.0.0.1
tcpdump -A -ni en0 host 239.0.0.1

When getting the plugin to do this it sent the information from what I can tell, but unreal didn't receive it.

The two tcpdump commands were executing on my Network interface (wireless) and on the loopback interface and messages would appear on on each when working.

For clarity unreal was configured to listen on 0.0.0.0 as per previous discussion points the test python got responses from unreal.

Sorry im not usually into blender but started playing and want to get this pipeline working as well. So im trying to figure out what goes on inside the plugin.

20:44:51.522012 IP ##.##.##.171.6766 > 239.0.0.1.6766: UDP, length 98
E..~....<...
MX......n.n.jRu{"version": 1, "magic": "ue_py", "type": "ping", "source": "f6319000-0000-0000-9171-9f23039cf36f"}
20:44:51.854422 IP ##.##.##.171.6766 > 239.0.0.1.6766: UDP, length 381
E.......<.S.
MX......n.n..S.{"version":1,"magic":"ue_py","type":"pong","source":"9E09FD6EFAD55E3","dest":"f6319000-0000-0000-9171-9f23039cf36f","data":{"user":"####","machine":"MBP","engine_version":"5.3.2-29314046+++UE5+Release-5.3","engine_root":"/Users/Shared/Epic Games/UE_5.3/Engine/","project_root":"/Users/####/Documents/Unreal Projects/MyProject2/","project_name":"MyProject2"}}
20:44:52.573002 IP ##.##.##.171.6766 > 239.0.0.1.6766: UDP, length 98

When compared to the output of the blender start RPC call.. the output only appeared on the loopback ip 127.0.0.1, and Unreal didn't acknowledge it, where when the script worked communications were found on both interfaces. lo0 and en0

@xBaaDf00d
Copy link

xBaaDf00d commented Jun 30, 2024

Sorry, guys, I am also looking into this issue, trying to figure out what is going on. I ran up a simple test python, to execute against unrealEditor. What I received back is confirmation to me that the problem is entirely blender plugin side.

So I have dug a little deeper, and I have managed to get the ping pong to respond to Blender but this is not an advancement.
Between mowing the lawn and general other general activities today. I replaced this line in unreal.py

def bootstrap_unreal_with_rpc_server():
    """
    Bootstraps the running unreal editor with the unreal rpc server if it doesn't already exist.
    """
    if not os.environ.get('TEST_ENVIRONMENT'):
        if not is_connected():
            #import bpy
            #rpc_response_timeout = bpy.context.preferences.addons["send2ue"].preferences.rpc_response_timeout
            rpc_response_timeout = 60
            dependencies_path = os.path.dirname(__file__)
            result = run_commands(
                [ .......

Essentially I came across this issue a few times while debugging it but thought this was because I wasn't running blender.
bpy.context == None
Following the previous trend, of packet monitoring I noticed additional requests going through now ping / pong from ue, and then a new one open_connection but it was not responded to. I suspect it will be a similar issue. Now this didn't sit right why would context be a problem, its part of blender and confirmed its relevant to blender running.

altered it like so and received the same result. Where previously I did not receive anything except ping now its ping pong open and close connections. The open being an attempt to link up to Unreals Command Port.

def bootstrap_unreal_with_rpc_server():
    """
    Bootstraps the running unreal editor with the unreal rpc server if it doesn't already exist.
    """
    if not os.environ.get('TEST_ENVIRONMENT'):
        if not is_connected():
            import bpy
            send2ue_addon = bpy.context.preferences.addons.get("send2ue")
            rpc_response_timeout = send2ue_addon.preferences.get("rpc_response_timeout")
            dependencies_path = os.path.dirname(__file__)
            result = run_commands(
                [ .......

Anyway I dont know if I'm barking up the wrong tree or not. but my gut feeling is that Blender's bpy_struct base class and preferences implementations may have changed under the hood.

Anyway, my progress towards figuring this out got to the redirection to the command_port, at 6776. Alas I haven't figured out where this happens in the code yet. baby steps :)

22:07:36.752277 IP ##.##.##.171.6766 > 239.0.0.1.6766: UDP, length 210
E..........%
MX......n.n..R.{"version": 1, "magic": "ue_py", "type": "open_connection", "source": "c170####-####-####-####-c20d5ae8434f", "dest": "A751554D6########5A1B2CBB91515", "data": {"command_ip": "0.0.0.0", "command_port": 6776}}
22:07:37.316431 IP ##.##.##.171.6766 > 239.0.0.1.6766: UDP, length 154
E... .....Ge
MX......n.n..R.{"version": 1, "magic": "ue_py", "type": "close_connection", "source": "c170####-####-####-####-c20d5ae8434f", "dest": "A751554D6########5A1B2CBB91515"}

@JoshQuake
Copy link
Collaborator

Thank you everyone for your support!

I've committed some changes here 639b537 that I'd like tested please!

@xBaaDf00d
Copy link

xBaaDf00d commented Jul 1, 2024

Thank you everyone for your support!

I've committed some changes here 639b537 that I'd like tested please!

Hey so I ran that up, in my blender and it behaved the same as what I did was doing ti tries to reach out for the command endpoint on 6776. but ends in closing the connection. Looks like my biggest issue in figuring out this issue Is getting a development plugin running appropriately. Can load a plugin no problem but getting any useful information out of a running blender Logs dont seem to appear,

This is the logs from blender on a run with this configuration.
Screenshot 2024-07-01 at 1 59 02 PM
Hope it helps you, it sure doesnt look useful to me.

Further to this it is communicating with unreal. It reports missing module each time I reload the plugin or restart the rpc servers.

Screenshot 2024-07-02 at 12 35 02 AM

@JoshQuake
Copy link
Collaborator

any guess is as good as mine if not better lol. I just rely on printing to the console (Window > Toggle System Console)

Going back to your first comment, this is interesting
send2ue_addon = bpy.context.preferences.addons.get("send2ue") rpc_response_timeout = send2ue_addon.preferences.get("rpc_response_timeout")

So it works after making this change? I wonder why it works on Windows then?

@xBaaDf00d
Copy link

any guess is as good as mine if not better lol. I just rely on printing to the console (Window > Toggle System Console)

Going back to your first comment, this is interesting send2ue_addon = bpy.context.preferences.addons.get("send2ue") rpc_response_timeout = send2ue_addon.preferences.get("rpc_response_timeout")

So it works after making this change? I wonder why it works on Windows then?

So I think that is a red herring, I think I made that change after making a similar change to yours locally that caused it to work.

The Crux of the problem is this one.
I played around in unreal with changing directory and navigating to where it should be loading the python module from for RPC, And what I see is that the Mac OS is definitely stepping in and stopping unreal from loading files outside its ownership.

Essentially After Each print(os.getcwd()) I got these in the log

System Policy: UnrealEditor(2036) deny(1) file-read-data /Path/To/Plugin/BlenderTools/send2ue/dependencies
System Policy: UnrealEditor(2036) deny(1) file-read-data /Path/To/Plugin/BlenderTools/send2ue

Albeit I'm using an alias / symbolic link to link send2ue into blenders plugin directory.
Was reading some information about code signing, but think this is more a general Mac Developer configuration issue. Where applications have to be whitelisted to access files from another location.

In this instance send2ue contains a module that is loaded by unreal, one in blender one trying to load it from inside blenders safe area. Im going to have to dig some more I think in Mac forums to figure out how to either Whitelist this behaviour or figure out what the right way to handle it is.

@xBaaDf00d
Copy link

xBaaDf00d commented Jul 3, 2024

So I have gotten a significant step forward...

cd /Path/To/Send2UEPlugin/
cp -r dependencies /Users/Shared/Epic\ Games/UE_5.3/Engine/Plugins/Experimental/PythonScriptPlugin/Content/Python/

What this does is it allows someone to use the plugin while running Unreal 5.3 / 5.4 on a Mac.
What it does not do, is allow UE to save the model.
UE gets the temporary file and loads it but when it tries to save the asset it fails when creating the new asset, you will be able to place move the actor around but the asset will be lost when UE is closed.

To fix that issue you need to go to system settings -> Privacy and Security -> Files and Folders -> Unreal Editor etc etc, Enable both Documents Folder and Downloads Folder. One enabled saving the asset is possible.

Screenshot 2024-07-03 at 3 20 40 PM

@JoshQuake
Copy link
Collaborator

JoshQuake commented Jul 3, 2024

So I have gotten a significant step forward...

cd /Path/To/Send2UEPlugin/
cp -r dependencies /Users/Shared/Epic\ Games/UE_5.3/Engine/Plugins/Experimental/PythonScriptPlugin/Content/Python/

What this does is it allows someone to use the plugin while running Unreal 5.3 / 5.4 on a Mac. What it does not do, is allow UE to save the model. UE gets the temporary file and loads it but when it tries to save the asset it fails when creating the new asset, you will be able to place move the actor around but the asset will be lost when UE is closed.

To fix that issue you need to go to system settings -> Privacy and Security -> Files and Folders -> Unreal Editor etc etc, Enable both Documents Folder and Downloads Folder. One enabled saving the asset is possible.

Screenshot 2024-07-03 at 3 20 40 PM

Very interesting! I initially suspected there was a problem related to security but was expecting it be a firewall issue. Is there a way to prompt for permission request on mac instead of having to manually check Security for blocked actions or adding exceptions?

If there isn't then the solution may just be to create a first run guide for mac users. Which really sucks, I want this to be a smooth no hassle process for everyone.

EDIT: Looks like the closest you can get is opening system preferences to the Privacy page with
webbrowser.open('x-apple.systempreferences:com.apple.preference.security?Privacy')
which ironically prompted me to allow access to Documents for python in my VM lol

@xBaaDf00d
Copy link

xBaaDf00d commented Jul 4, 2024

Very interesting! I initially suspected there was a problem related to security but was expecting it be a firewall issue. Is there a way to prompt for permission request on mac instead of having to manually check Security for blocked actions or adding exceptions?

If there isn't then the solution may just be to create a first run guide for mac users. Which really sucks, I want this to be a smooth no hassle process for everyone.

EDIT: Looks like the closest you can get is opening system preferences to the Privacy page with webbrowser.open('x-apple.systempreferences:com.apple.preference.security?Privacy') which ironically prompted me to allow access to Documents for python in my VM lol

Possibly, That downloads folder issue may have been a misclick when playing with unreal, I can't remember when I installed it was a while back :(.

But with the python library needing to be somewhere it can be accessed by unreal is annoying. The dependencies either need to be copied over and overwritten each time it runs (which may be possible but fear the security layer will block this behavior as one app reaches inside another.)

Or, as you say Manual step for Mac Users to copy the dependencies into a place unreal can use them. Which I feel this may be the safest way forward but is prone to human error.

Edit: The thing that is confusing me, Unreal can edit / save projects make levels all without that permission but to load a module from python, it can't do it with out it enabled ? Seems like two different enforcement policies are being applied to Unreal Editor and the PythonScript Plugin.

@jack-yao91
Copy link

So I was able to get my hands on a Mac this weekend. The addon wasn't working until I changed the multicast bind address to 0.0.0.0 in both the unreal project and the remote_execution.py

mac-specs unreal remote_execution

After that and rebooting unreal and blender it works fine for me.

I didn't hit the permissions issue, but I didn't use a symlink though.

@JoshQuake
Copy link
Collaborator

okok. So then I think it would be worth pushing the following before diving into a full macos first-run process/guide:

  • Keep my lines setting the multicast and command endpoint IPs based on OS (127 for windows, else 0)
  • Add a visible red warning for macOS/linux users in the Addons preferences menu and/or at the top of the Send2UE settings menu that informs the need to verify/set the IP's in their Unreal python settings.

@jack-yao91
Copy link

Yea I think the 0.0.0.0 will work on any machine. I think the unreal python plugin defaults to 127.0.0.1 when creating a new project. If the default was updated to 0.0.0.0 in the addon code, and then we update the quick start with a step to change multicast bind address to 0.0.0.0 when they enable remote execution, then I think that would be the most universal configuration.

I know seeing 0.0.0.0 scares some people, but with multicast TTL set to 0 I don't think it matters since you shouldn't be able to connect to it from anything but your own computer's network interface. Maybe we can also have these be read from addon preferences instead of hardcoded values incase people want to customize these?

@JoshQuake
Copy link
Collaborator

Yeah good points. I will implement these changes in the next few days and upload a test package for everyone to try before pushing to main.

@andygagnon
Copy link

@JoshQuake I'm ready to test this on Mac OS, but I'm not sure how to get this recent build from github
onto my machine for testing.

The latest release is 2.4.5 from June 17.
https://github.com/poly-hammer/BlenderTools/releases

Suggestions? Thanks.

@JoshQuake
Copy link
Collaborator

We're close to pushing a release but in the meantime the src/addons/send2ue folder can be zipped and installed to test:
send2ue.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants