在Blender中无线读取数据时运行游戏引擎

1 投票
1 回答
2259 浏览
提问于 2025-04-17 15:26

我有一段Blender的代码,它可以从一个csv文件中读取数据,然后用这些数据来旋转一个机器人手臂和一个人形模型在游戏引擎里。这个代码运行得很好,但现在我想通过无线连接把数据发送到Blender。

我在Blender里设置了一个服务器代码(这个是用Python 3写的)

# Server Program
# Make sure the client is being run on the data generation computer

SERVER_LOOP = True

import socket
import sys
import json
import bge

cont = bge.logic.getCurrentController()
owner = cont.owner

print ('INFO: Starting up')


# Create a TCP/IP socket to listen on
print ('INFO: Creating TCP/IP Socket')
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Prevent from 'ADDRESS ALREADY IN USE' upon restart
print ('INFO: Housekeeping...')
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# Bind the socket to port 8081 on all interfaces
server_address = ('localhost', 8081)
print ('INFO: Binding and starting up on %s port %s' % server_address)
server.bind(server_address)
print ('INFO: Server bound')

def send_welcome(cont):
    cont.send('SERVER: Welcome'.encode('utf8'))

# Listen for connectons for 5 seconds
server.listen(5)

# Connection is the SOCKET OBJECT for the connection
# Client_address is the connected peer(the client)
connection, client_address = server.accept()
print ('INFO: Connection from', connection.getpeername())
print ('INFO: Sending welcome msg')
send_welcome(connection)
print ()

while SERVER_LOOP:

    # Receive data
    try:
        data = connection.recv(10000)

    # Unless there's an error
    except OSError:
        print (connection)

    # Decode the data into usable lists
    if type(data) != type(''): 
        data = data.decode()

    # If we want to end the client stream but keep the server running    
    if data=='end' or data=='End' or data=='END':
        print ('INFO: Closing connection with ',connection.getpeername())
        connection.shutdown(socket.SHUT_RD | socket.SHUT_WR)
        print ()
        connection.close()
        connection, client_address = server.accept()
        print ('INFO: Connection from', connection.getpeername())
        print ('INFO: Sending welcome msg')
        send_welcome(connection)
        print ()

    # If we want to stop running the server
    elif data=='end server' or data=='End server' or data=='End Server':
        print ()
        print ('SERVER SHUT DOWN')
        SERVER_LOOP = False

    # Display when data is loaded back on the client side
    else:
            # gives feedback in server command line
            data = json.loads(data)
            owner['test'] = data
            print ('CLIENT: %s' % data)
            message = 'ping'
            connection.send(('SERVER: %s' % message).encode('utf-8'))
            print ('SERVER: %s' % message)

还有一个客户端代码(这个是用Python 2.7写的)

# Client Program
# Make sure the server is being run in Blender

import socket
import time
import json

print 'INFO: Creating Socket'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

ip_addr = raw_input('IP: ')
port_addr = raw_input('PORT: ')

# Type 'localhost' in the IP field
# Type '8081' in the PORT field

print 'INFO: Connecting to server'
s.settimeout(5) # Times out if 5 seconds without connecting to client
s.connect((ip_addr, int(port_addr)))

# Listen for welcome
data = s.recv(10000)
print data
print ''
while 1:
    message = raw_input('CLIENT: ')
    if message=='end' or message=='End' or message=='END':
            print ''
            print 'SHUTTING DOWN CLIENT, SERVER STILL RUNNING'
            s.send(message)
            break
    elif message=='end server' or message=='End server' or message=='End Server':
            print ''
            print 'SHUTTING DOWN SERVER'
            s.send(message)
            break
    else:
            s.send(message)
            data = s.recv(10000)
            print data

print 'INFO: Closing socket'
s.close()
print 'INFO: Quitting'

现在,这个代码显然并没有进行旋转;它只是一个测试脚本,用来确保两个之间的数据传输是有效的。结果是有效的——在Blender的系统控制台里,数据正如我所希望的那样显示出来。不过,我在Blender里有一个叫“test”的字符串调试属性,它应该显示客户端刚输入的当前数字,但直到我关闭整个程序才会显示。

举个例子:

  • 我在Blender里运行服务器脚本
  • 我在IDLE里运行客户端脚本
  • 我在客户端输入数字
  • 这些数字在服务器端的系统控制台上出现,但在游戏引擎里却没有显示
  • 我从客户端关闭服务器
  • 现在,我最后输入的数字终于在服务器端显示出来了

所以问题是,Blender先运行我的脚本,然后再运行游戏引擎,但我希望它们能够同时运行。

如果我的解释不清楚,请告诉我;如果需要的话,我可以提供我的代码下载。

1 个回答

1

我不知道这个问题现在是否还存在——你是在二月份发的帖子,现在已经八月份了。不过我刚好在找类似问题的答案。你的问题是,Blender在脚本运行完之前不会更新帧。你的游戏实际上卡在了它播放的第一帧,因为一到那一帧就开始执行脚本,而由于你的脚本的特性,它永远也不会结束。

现在,你使用server.listen(5)来表示它监听五秒钟,但这个函数里的数字5其实是指等待连接的数量,而不是时间长度。[source]。socket.listen()会让你的游戏无限期地停滞,就像一个无限循环一样,至少我理解是这样的。

这可能不是你想要的答案,但这确实是一个答案。

撰写回答