feudal_ 2026-01-06 14:56 采纳率: 75%
浏览 4
已采纳

ue 二次开放 开放exec遇到线程问题IsInGameThread()

img

img

asset_tools.import_asset_tasks([import_task])运行就死了
https://zhuanlan.zhihu.com/p/639729563
IsInGameThread()好像是这个问题


Assertion failed: IsInGameThread() [File:D:/Build/++UE4/Sync/Engine/Source/Runtime/CoreUObject/Private/UObject/UObjectGlobals.cpp] [Line: 1092] Unable to load /Game/Characters/_Shared/Materials/Master/M_CharaMaster_Cloth. Objects and Packages can only be loaded from the game thread.

UE4Editor_Core
UE4Editor_Core
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_UnrealEd
UE4Editor_UnrealEd
UE4Editor_UnrealEd
UE4Editor_UnrealEd
UE4Editor_AssetTools
UE4Editor_AssetTools
UE4Editor_AssetTools
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_PythonScriptPlugin
UE4Editor_PythonScriptPlugin
UE4Editor_PythonScriptPlugin
UE4Editor_PythonScriptPlugin
UE4Editor_PythonScriptPlugin
python37!_PyObject_FastCallKeywords() [c:\a\18\s\objects\call.c:199]
python37!call_function() [c:\a\18\s\python\ceval.c:4619]
python37!_PyEval_EvalFrameDefault() [c:\a\18\s\python\ceval.c:3095]
python37!_PyEval_EvalCodeWithName() [c:\a\18\s\python\ceval.c:3930]
python37!PyEval_EvalCodeEx() [c:\a\18\s\python\ceval.c:3966]
python37!PyEval_EvalCode() [c:\a\18\s\python\ceval.c:530]
python37!run_mod() [c:\a\18\s\python\pythonrun.c:1036]
python37!PyRun_StringFlags() [c:\a\18\s\python\pythonrun.c:959]
python37!builtin_exec_impl() [c:\a\18\s\python\bltinmodule.c:1096]
python37!builtin_exec() [c:\a\18\s\python\clinic\bltinmodule.c.h:283]
python37!_PyMethodDef_RawFastCallKeywords() [c:\a\18\s\objects\call.c:655]
python37!call_function() [c:\a\18\s\python\ceval.c:4568]
python37!_PyEval_EvalFrameDefault() [c:\a\18\s\python\ceval.c:3126]
python37!call_function() [c:\a\18\s\python\ceval.c:4616]
python37!_PyEval_EvalFrameDefault() [c:\a\18\s\python\ceval.c:3111]
python37!_PyFunction_FastCallDict() [c:\a\18\s\objects\call.c:322]
python37!method_call() [c:\a\18\s\objects\classobject.c:309]
python37!_PyEval_EvalFrameDefault() [c:\a\18\s\python\ceval.c:3191]
python37!call_function() [c:\a\18\s\python\ceval.c:4616]
python37!_PyEval_EvalFrameDefault() [c:\a\18\s\python\ceval.c:3111]
python37!call_function() [c:\a\18\s\python\ceval.c:4616]
python37!_PyEval_EvalFrameDefault() [c:\a\18\s\python\ceval.c:3111]
python37!_PyFunction_FastCallDict() [c:\a\18\s\objects\call.c:322]
python37!method_call() [c:\a\18\s\objects\classobject.c:309]
python37!PyObject_Call() [c:\a\18\s\objects\call.c:247]
python37!t_bootstrap() [c:\a\18\s\modules\_threadmodule.c:994]
python37!bootstrap() [c:\a\18\s\python\thread_nt.h:174]
ucrtbase
kernel32
ntdll


```python
import unreal
import socket
import threading
import json
import queue
import time

class PythonExecServer:
    def __init__(self, port=8070):
        self.port = port
        self.server_socket = None
        self.running = False
        self.command_queue = queue.Queue()
        self.result_queue = queue.Queue()
        
    def start_server(self):
        """启动服务器监听8070端口"""
        try:
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.server_socket.bind(('localhost', self.port))
            self.server_socket.listen(5)
            self.running = True
            
            print(f"Python exec server started on port {self.port}")
            
            while self.running:
                try:
                    client_socket, address = self.server_socket.accept()
                    print(f"Connection from {address}")
                    
                    # 在新线程中处理客户端请求
                    client_thread = threading.Thread(
                        target=self.handle_client, 
                        args=(client_socket,)
                    )
                    client_thread.daemon = True
                    client_thread.start()
                    
                except socket.error:
                    if self.running:
                        continue
                    break
                    
        except Exception as e:
            print(f"Error starting server: {e}")
    
    def handle_client(self, client_socket):
        """处理客户端请求"""
        try:
            data = client_socket.recv(4096).decode('utf-8')
            if data:
                # 解析JSON命令
                command_data = json.loads(data)
                command = command_data.get('command', '')
                
                # 直接执行命令(注意:这可能需要在UE主线程中执行)
                result = self.execute_command(command)
                
                # 发送响应
                response = json.dumps({'result': result})
                client_socket.send(response.encode('utf-8'))
                
        except Exception as e:
            error_response = json.dumps({'error': str(e)})
            client_socket.send(error_response.encode('utf-8'))
        finally:
            client_socket.close()
    
    def execute_command(self, command):
        """执行Unreal命令"""
        try:
            # 使用exec执行命令
            exec_globals = {'unreal': unreal}
            exec(command, exec_globals)
            return "Command executed successfully"
        except Exception as e:
            return f"Error executing command: {str(e)}"
    
    def stop_server(self):
        """停止服务器"""
        self.running = False
        if self.server_socket:
            self.server_socket.close()

# 全局服务器实例
server = PythonExecServer(port=8070)

def start_exec_server():
    """启动exec服务器的函数"""
    global server
    server_thread = threading.Thread(target=server.start_server)
    server_thread.daemon = True
    server_thread.start()
    return "Server started on port 8070"

def stop_exec_server():
    """停止exec服务器的函数"""
    global server
    server.stop_server()
    return "Server stopped"

if __name__ == "__main__":
    start_exec_server()
    print("啊卡夏")

```

  • 写回答

3条回答 默认 最新

  • feudal_ 2026-01-06 17:09
    关注

    用这个就行了unreal.register_slate_post_tick_callback

    
    ```python
    import unreal
    import socket
    import select
    import threading
    from queue import Queue
    import os
    import json
    
    def execute_unreal_command(code_string):
        """
        执行传入的Python代码字符串
        """
        try:
            # 添加调试输出,完整记录执行的代码
           
            unreal.log(f"执行的代码:\n{code_string}")
            # 使用globals()和locals()提供当前环境的上下文
            # exec执行代码并捕获输出
            local_vars = {'unreal': unreal}
            # 使用compile来预编译代码,可以更好地处理多行代码
            compiled_code = compile(code_string, '<string>', 'exec')
            
            exec(compiled_code, globals(), local_vars)
            return "代码执行成功"
        except SyntaxError as e:
            error_msg = f"语法错误: {str(e)} (文件: {e.filename}, 行号: {e.lineno}, 文本: {e.text})"
            unreal.log_error(error_msg)
            return error_msg
        except Exception as e:
            error_msg = f"执行错误: {str(e)}"
            unreal.log_error(error_msg)
            return error_msg
    
    class SimpleJsonServer:
        def __init__(self):
            self.socket = None
            self.clients = []
            self.should_stop = False
            self.tick_handle = None
            
        def start_server(self, port=8070):
            """启动基于Tick的简单JSON服务器"""
            try:
                # 创建非阻塞socket
                self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                self.socket.bind(('', port))
                self.socket.listen(5)
                self.socket.setblocking(False)  # 设置为非阻塞模式
                
                # 注册tick函数
                self.tick_handle = unreal.register_slate_post_tick_callback(
                    self.process_requests
                )
                
                unreal.log(f"基于Tick的简单JSON服务器启动在端口 {port}")
                return True
                
            except Exception as e:
                unreal.log_error(f"服务器启动失败: {str(e)}")
                return False
        
        def process_requests(self, delta_time):
            """在UE的tick中处理请求"""
            if self.should_stop:
                self.stop_server()
                return
                
            try:
                # 检查是否有新的连接或数据
                ready, _, error = select.select([self.socket] + self.clients, [], self.clients, 0)
                
                # 处理错误的连接
                for err_sock in error:
                    if err_sock in self.clients:
                        self.clients.remove(err_sock)
                        err_sock.close()
                
                for sock in ready:
                    if sock == self.socket:
                        # 新连接
                        try:
                            client, addr = self.socket.accept()
                            client.setblocking(False)  # 客户端也设为非阻塞
                            self.clients.append(client)
                            unreal.log(f"新连接来自: {addr}")
                        except:
                            pass  # 非阻塞accept可能失败
                    else:
                        # 处理客户端数据
                        try:
                            # 尝试接收完整的JSON数据
                            full_data = b""
                            while True:
                                try:
                                    chunk = sock.recv(4096)  # 增加接收缓冲区大小
                                    if not chunk:
                                        break
                                    full_data += chunk
                                    # 如果数据块小于缓冲区大小,可能数据接收完毕
                                    if len(chunk) < 4096:
                                        break
                                except BlockingIOError:
                                    # 非阻塞socket没有数据可读,跳出循环
                                    break
                                except ConnectionResetError:
                                    # 连接被重置
                                    if sock in self.clients:
                                        self.clients.remove(sock)
                                    sock.close()
                                    raise
                                except Exception as e:
                                    # 其他错误
                                    unreal.log_error(f"接收数据时出错: {str(e)}")
                                    if sock in self.clients:
                                        self.clients.remove(sock)
                                    sock.close()
                                    raise
                            
                            # 如果接收到数据
                            if full_data:
                                data_str = full_data.decode('utf-8')
                                self.handle_request(sock, data_str)
                            else:
                                # 客户端断开连接
                                if sock in self.clients:
                                    self.clients.remove(sock)
                                sock.close()
                        except BlockingIOError:
                            # 非阻塞socket没有数据可读
                            pass
                        except ConnectionResetError:
                            # 连接被重置
                            if sock in self.clients:
                                self.clients.remove(sock)
                            sock.close()
                        except Exception as e:
                            # 其他错误
                            unreal.log_error(f"处理客户端数据时出错: {str(e)}")
                            if sock in self.clients:
                                self.clients.remove(sock)
                            sock.close()
                            
            except Exception as e:
                unreal.log_warning(f"处理请求时出错: {str(e)}")
        
        def handle_request(self, client_socket, data):
            """处理请求并发送响应 - 纯JSON格式"""
            try:
                # 直接解析JSON数据,不处理HTTP头部
                request_data = json.loads(data)
                code_to_execute = request_data.get('code', '')
                
                if code_to_execute:
                    # 执行传入的代码
                    result = execute_unreal_command(code_to_execute)
                    # 直接返回结果,不使用HTTP响应格式
                    client_socket.send(result.encode('utf-8'))
                else:
                    error_msg = "错误: 未提供要执行的代码"
                    client_socket.send(error_msg.encode('utf-8'))
                
            except json.JSONDecodeError as e:
                error_msg = f"错误: 无效的JSON格式 - {str(e)}"
                unreal.log_error(error_msg)
                try:
                    client_socket.send(error_msg.encode('utf-8'))
                except:
                    pass
            except Exception as e:
                error_msg = f"处理请求时发生未知错误: {str(e)}"
                unreal.log_error(error_msg)
                try:
                    client_socket.send(error_msg.encode('utf-8'))
                except:
                    pass
            finally:
                # 关闭连接
                if client_socket in self.clients:
                    self.clients.remove(client_socket)
                try:
                    client_socket.close()
                except:
                    pass
        
        def stop_server(self):
            """停止服务器"""
            self.should_stop = True
            
            # 移除tick回调
            if self.tick_handle:
                unreal.unregister_slate_tick_callback(self.tick_handle)
                self.tick_handle = None
            
            # 关闭所有连接
            for client in self.clients:
                try:
                    client.close()
                except:
                    pass
            self.clients.clear()
            
            # 关闭服务器socket
            if self.socket:
                try:
                    self.socket.close()
                except:
                    pass
                self.socket = None
            
            unreal.log("简单JSON服务器已停止")
    
    def start_simple_json_server():
        """启动简单JSON服务器"""
        server = SimpleJsonServer()
        if server.start_server(8070):
            # 保存服务器实例以便后续控制
            if not hasattr(start_simple_json_server, 'server_instance'):
                start_simple_json_server.server_instance = server
            return server
        return None
    
    def stop_simple_json_server():
        """停止简单JSON服务器"""
        if hasattr(start_simple_json_server, 'server_instance'):
            start_simple_json_server.server_instance.stop_server()
            start_simple_json_server.server_instance = None
            return True
        return False
    
    # 使用示例
    if __name__ == "__main__":
        # 启动简单JSON服务器
        server = start_simple_json_server()
        if server:
            unreal.log("简单JSON服务器已启动")
        else:
            unreal.log_error("服务器启动失败")
    
    

    ```

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 已采纳回答 1月6日
  • 修改了问题 1月6日
  • 修改了问题 1月6日
  • 创建了问题 1月6日