【UE4】Python读取Json数据创建对应关卡序列

前言:几个月前做项目时写的东西,主要的过程还是在python中拿json数据创序列打各种关键帧


1.准备工作:

  • UE4项目中启用Python插件:--Python Editor Script Plugin

  • 项目插件设置中启用Python编辑器插件:--Python Editor (BT)

MarketplaceURL:com.epicgames.launcher://ue/marketplace/product/f6b726c986ee42838882d004bdf94380

  • 项目插件设置中启用VaRest插件并重启:

MarketplaceURL:

com.epicgames.launcher://ue/marketplace/content/e47be161e7a24e928560290abd5dcc4f

2.基础文件与代码:

  • 在Python编辑器中创建CreateSequence.py:

【UE4】Python读取Json数据创建对应关卡序列_第1张图片

  •  示例createseq.Json文档(Content/JsonFile/...)--序列的开始结束时间,船与子弹的位移行动与关键帧:

{
  "starttimestamp": "0",
  "endtimestamp": "50",
  "commands": [
    {
      "commandtype": "Create",
      "objectcreateinfo": {
        "object": {
          "id": "1",
          "objecttype": "myship"
        },
        "propertys": [
          {
            "key": "DisplayName",
            "value": "我的船",
            "propertytype": "String",
            "displaystring": "我的船"
          }
        ],
        "rotation": {
          "roll": 60,
          "pitch": 0,
          "yaw": 0
        },
        "position": {
          "latitude": "0",
          "longitude": "0",
          "elevation": "0"
        }
      },
      "lasttimestamp": "0",
      "timestamp": "3"
    },
    {
      "commandtype": "Action",
      "objectactioninfo": {
        "object": {
          "id": "1",
          "objecttype": "myship"
        },
        "action": "Show",
        "propertys": []
      },
      "lasttimestamp": "3",
      "timestamp": "4"
    },
     {
      "commandtype": "Move",
      "objectmoveinfo": {
        "object": {
          "id": "1",
          "objecttype": "myship"
        },
        "rotation": {
          "pitch": 90,
          "roll": 0,
          "yaw": 0
        },
        "position": {
          "latitude": "50",
          "longitude": "300",
          "elevation": "600"
        }
      },
      "lasttimestamp": "4",
      "timestamp": "30"
    },
    {
      "commandtype": "Action",
      "objectactioninfo": {
        "object": {
          "id": "1",
          "objecttype": "myship"
        },
        "action": "Fire",
        "propertys": []
      },
      "lasttimestamp": "30",
      "timestamp": "32"
    },
    {
      "commandtype": "Create",
      "objectcreateinfo": {
        "object": {
          "id": "1_0",
          "objecttype": "bullet"
        },
        "propertys": [
          {
            "key": "DisplayName",
            "value": "子弹",
            "propertytype": "String",
            "displaystring": "子弹"
          }
        ],
        "rotation": {
          "roll": 0,
          "pitch": 0,
          "yaw": 0
        },
        "position": {
          "latitude": "0",
          "longitude": "0",
          "elevation": "0"
        }
      },
      "lasttimestamp": "32",
      "timestamp": "35"
    },
    {
      "commandtype": "Action",
      "objectactioninfo": {
        "object": {
          "id": "1_0",
          "objecttype": "Bullet"
        },
        "action": "Show",
        "propertys": []
      },
      "lasttimestamp": "35",
      "timestamp": "36"
    },
    {
      "commandtype": "Move",
      "objectmoveinfo": {
        "object": {
          "id": "1_0",
          "objecttype": "Bullet"
        },
        "rotation": {
          "pitch": 90,
          "roll": 0,
          "yaw": 0
        },
        "position": {
          "latitude": "50",
          "longitude": "300",
          "elevation": "600"
        }
      },
      "lasttimestamp": "36",
      "timestamp": "40"
    },
    {
      "commandtype": "Move",
      "objectmoveinfo": {
        "object": {
          "id": "2_0",
          "objecttype": "Bullet"
        },
        "rotation": {
          "pitch": 90,
          "roll": 0,
          "yaw": 0
        },
        "position": {
          "latitude": "50",
          "longitude": "300",
          "elevation": "800"
        }
      },
      "lasttimestamp": "36",
      "timestamp": "45"
    },
    {
      "commandtype": "Action",
      "objectactioninfo": {
        "object": {
          "id": "1_0",
          "objecttype": "Bullet"
        },
        "action": "Fire",
        "propertys": []
      },
      "lasttimestamp": "40",
      "timestamp": "50"
    }
  ]
}
  • CreateSequence.py中:

    # coding: utf-8
    #兼容utf-8
    
    import unreal,json,os,sequencer_key_examples
    #连接虚幻,json,os,sequence库
    
    #创建关卡序列函数,传入一个Str命名即可
    def create_seq(filename):
        
        #读取/项目目录/JsonFile中的JSON文件数据存入json_data
        root_path = unreal.SystemLibrary.get_project_directory() + 'Content/JsonFile/'
        final_path = root_path + filename + '.json'
        fp = open(final_path,'r',encoding='utf-8')
        json_str = fp.read()
        json_data = json.loads(json_str)
    
        #下面开始创建序列
    
        #获取开始/结束时间
        sequence_starttimestamp = float(float(json_data["starttimestamp"]) / 1000.0)
        sequence_endtimestamp = float(float(json_data["endtimestamp"]) / 1000.0)
        print(sequence_endtimestamp)
        
        #创建序列的路径
        package_path = '/Game/Sequence'
        
        print(package_path)
        
        #创建序列并设置开始/结束/显示格式
        sequence = unreal.AssetToolsHelpers.get_asset_tools().create_asset(str("LS_" + filename), package_path, unreal.LevelSequence, unreal.LevelSequenceFactoryNew())
        sequence.set_display_rate(unreal.FrameRate(numerator=1000, denominator=1))
        sequence.set_playback_start_seconds(sequence_starttimestamp)
        sequence.set_playback_end_seconds(sequence_endtimestamp)
        
        #读取各项数据创建关键帧
        commands = json_data["commands"]
        for index in range(0,len(commands)):
        #for command in commands:
            #json中commandtype为Create时执行
            if commands[index]["commandtype"] == "Create":
                #根据objecttype创建对应的actor
                
                #1.创建myship
                if commands[index]["objectcreateinfo"]["object"]["objecttype"] == "myship":
                    actor_name = "BP_myship"
                    #设置actor_location
                    actor_x = float(commands[index]["objectcreateinfo"]["position"]["uex"])
                    actor_y = float(commands[index]["objectcreateinfo"]["position"]["uey"])
                    actro_z = float(commands[index]["objectcreateinfo"]["position"]["uez"])
                    #设置actor_rotation
                    actor_roll = float(commands[index]["objectcreateinfo"]["rotation"]["roll"])
                    actor_pitch = float(commands[index]["objectcreateinfo"]["rotation"]["pitch"])
                    actor_yaw = float(commands[index]["objectcreateinfo"]["rotation"]["yaw"])
                                    
                #2.创建Bullet
                if commands[index]["objectcreateinfo"]["object"]["objecttype"] == "Bullet":
                    actor_name = "BP_Bullet"
                    #设置actor_location
                    actor_x = float(commands[index]["objectcreateinfo"]["position"]["uex"])
                    actor_y = float(commands[index]["objectcreateinfo"]["position"]["uey"])
                    actro_z = float(commands[index]["objectcreateinfo"]["position"]["uez"])
                    #设置actor_rotation
                    actor_roll = float(commands[index]["objectcreateinfo"]["rotation"]["roll"])
                    actor_pitch = float(commands[index]["objectcreateinfo"]["rotation"]["pitch"])
                    actor_yaw = float(commands[index]["objectcreateinfo"]["rotation"]["yaw"])
                    
                    
                    
                #根据路径创建对应的蓝图Actor--/Game/BP/'actor_name'
                actor_class = unreal.EditorAssetLibrary.load_blueprint_class('/Game/BP/' + actor_name)
                #打印actor_class到输出日志
                print(actor_class)
                #设置生成/位移/命名
                actor_location = unreal.Vector(actor_x,actor_y,actro_z)
                actor_rotation = unreal.Rotator(actor_roll,actor_pitch,actor_yaw)
                actor_self = unreal.EditorLevelLibrary.spawn_actor_from_class(actor_class,actor_location,actor_rotation)
    
                actor_self.set_actor_label(commands[index]["objectcreateinfo"]["object"]["id"],False)  
                
                #序列绑定actor/actor的创建关键帧
                binding = sequence.add_possessable(actor_self)
                
                #为actor添加一个位移关键帧/设置起始结束点
                transform_track = binding.add_track(unreal.MovieScene3DTransformTrack)
                transform_section = transform_track.add_section()
                transform_section.set_start_frame_seconds(0)
                transform_section.set_end_frame_seconds(sequence_endtimestamp)
                
                #为actor添加一个显示隐藏关键帧/设置起始结束点
                visibility_track = binding.add_track(unreal.MovieSceneVisibilityTrack)
                visibility_track.set_property_name_and_path('bHidden', 'bHidden')
                visibility_section = visibility_track.add_section()
                visibility_section.set_start_frame_seconds(0)
                visibility_section.set_end_frame_seconds(sequence_endtimestamp)
                
        
                #添加关键帧:
                #位移:
                #获取位置的xyz通道
                channel_location_x = transform_section.get_channels()[0]
                channel_location_y = transform_section.get_channels()[1]
                channel_location_z = transform_section.get_channels()[2]
                #获取旋转yz的关键帧
                channel_rotation_x = transform_section.get_channels()[3]
                channel_rotation_y = transform_section.get_channels()[4]
                channel_rotation_z = transform_section.get_channels()[5]
                #添加一个位移关键帧
                if index - 1 < 0:
                    index = 1
                new_time = unreal.FrameNumber(value = int(commands[index-1]["timestamp"]))
                channel_location_x.add_key(new_time, actor_x, 0.0)
                channel_location_y.add_key(new_time, actor_y, 0.0)
                channel_location_z.add_key(new_time, actro_z, 0.0)
                channel_rotation_x.add_key(new_time, actor_roll, 0.0)
                channel_rotation_y.add_key(new_time, actor_pitch, 0.0)
                channel_rotation_z.add_key(new_time, actor_yaw, 0.0)
                
                #设置显示隐藏:
                #为actor添加可视性(隐藏)关键帧
                channel_visibility_bool = visibility_section.get_channels()[0]
                channel_visibility_bool.add_key(new_time,False)
    
                
            #JSON中命令为move时执行    
            if commands[index]["commandtype"] == "Move":
                #位置
                actor_x = float(commands[index]["objectmoveinfo"]["position"]["uex"])
                actor_y = float(commands[index]["objectmoveinfo"]["position"]["uey"])
                actro_z = float(commands[index]["objectmoveinfo"]["position"]["uez"])
                #旋转
                actor_roll = float(commands[index]["objectmoveinfo"]["rotation"]["roll"])
                actor_pitch = float(commands[index]["objectmoveinfo"]["rotation"]["pitch"])
                actor_yaw = float(commands[index]["objectmoveinfo"]["rotation"]["yaw"])
                
                #添加关键帧
                #获取位置3个通道
                channel_location_x = transform_section.get_channels()[0]
                channel_location_y = transform_section.get_channels()[1]
                channel_location_z = transform_section.get_channels()[2]
     
                #获取旋转yz通道
                channel_rotation_x = transform_section.get_channels()[3]
                channel_rotation_y = transform_section.get_channels()[4]
                channel_rotation_z = transform_section.get_channels()[5]
                
                new_time1 = unreal.FrameNumber(value = int(commands[index]["timestamp"]))
                channel_location_x.add_key(new_time1, actor_x, 0.0)
                channel_location_y.add_key(new_time1, actor_y, 0.0)
                channel_location_z.add_key(new_time1, actro_z, 0.0)
                channel_rotation_x.add_key(new_time1, actor_roll, 0.0)
                channel_rotation_y.add_key(new_time1, actor_pitch, 0.0)
                channel_rotation_z.add_key(new_time1, actor_yaw, 0.0)
            
            #JSON中命令为action时执行    
            if commands[index]["commandtype"] == "Action":
                #添加可视性/发射子弹的关键帧
                new_time2 = unreal.FrameNumber(value = int(commands[index]["timestamp"]))
                if commands[index]["objectactioninfo"]["object"]["objecttype"] == "myship":
                    if commands[index]["objectactioninfo"]["action"] == "Show":
                        channel_visibility_bool.add_key(new_time2,True)           
                        print("Show!")
                    if commands[index]["objectactioninfo"]["action"] == "Fire":
                        print("Fire!")
                    if commands[index]["objectactioninfo"]["action"] == "Hide":
                        channel_visibility_bool.add_key(new_time,False)
    
                if commands[index]["objectactioninfo"]["object"]["objecttype"] == "Bullet":
    
                    if commands[index]["objectactioninfo"]["action"] == "Show":           
                        print("Show!")
                        channel_visibility_bool.add_key(new_time2,True)     
                    if commands[index]["objectactioninfo"]["action"] == "Fire":
                        print("Fire!")
                        #hide Missile,create particlesystem actor
                        channel_visibility_bool.add_key(new_time2,False)
                        new_time3 = unreal.FrameNumber(value = 0)
                        new_time4 = unreal.FrameNumber(value = int(commands[index]["timestamp"]))
                        #关卡中生成一个BP_Enemy
                        actor_class1 = unreal.EditorAssetLibrary.load_blueprint_class('/Game/BP/BP_Enemy')                    
                        actor_x1 = float(commands[index-1]["objectmoveinfo"]["position"]["uex"])
                        actor_y1 = float(commands[index-1]["objectmoveinfo"]["position"]["uey"])
                        actro_z1 = float(commands[index-1]["objectmoveinfo"]["position"]["uez"])
                        actor_location1 = unreal.Vector(actor_x1,actor_y1,actro_z1)
                        actor_rotation1 = unreal.Rotator(actor_roll,actor_pitch,actor_yaw)
                        actor_self1 = unreal.EditorLevelLibrary.spawn_actor_from_class(actor_class1,actor_location1,actor_rotation1)
                        #绑定到序列/设置隐藏与显示时间
                        binding1 = sequence.add_possessable(actor_self1)
                        visibility_track = binding1.add_track(unreal.MovieSceneVisibilityTrack)
                        visibility_track.set_property_name_and_path('bHidden', 'bHidden')
                        visibility_section = visibility_track.add_section()
                        visibility_section.set_start_frame_seconds(0)
                        visibility_section.set_end_frame_seconds(sequence_endtimestamp)
                        channel_visibility_bool = visibility_section.get_channels()[0]
                        channel_visibility_bool.add_key(new_time3,False)
                        channel_visibility_bool.add_key(new_time4,True)
                                                                                                                              
                    if commands[index]["objectactioninfo"]["action"] == "Hide":
                        channel_visibility_bool.add_key(new_time2,False)     
                        print("Hide!")
                        
                         
                #保存关卡序列
                unreal.EditorAssetLibrary.save_loaded_asset(sequence, False)    
        
    #create_seq("TestData")  #调用此函数运行 

    3.虚幻引擎中:

  •  菜单栏中-窗口-Python-PythonEditor并双击打开刚才写好的py文件点击运行:【UE4】Python读取Json数据创建对应关卡序列_第2张图片

  • 创建编辑器工具控件-添加文本输入框与按钮(创建sequence)-添加点击事件:

【UE4】Python读取Json数据创建对应关卡序列_第3张图片【UE4】Python读取Json数据创建对应关卡序列_第4张图片

4.蓝图中:

  •  创建函数GetStartEndTime-并且在细节栏中勾选纯函数:

【UE4】Python读取Json数据创建对应关卡序列_第5张图片

【UE4】Python读取Json数据创建对应关卡序列_第6张图片

  •  控件蓝图事件图表中:

【UE4】Python读取Json数据创建对应关卡序列_第7张图片

【UE4】Python读取Json数据创建对应关卡序列_第8张图片

  •  编译保存-右击运行该编辑器工具控件-输入json文件名创建序列:

【UE4】Python读取Json数据创建对应关卡序列_第9张图片

 【UE4】Python读取Json数据创建对应关卡序列_第10张图片


 后言:

这个例子只是一部分关键帧,其他的关键帧track类型可以在官方api文档中搜索自己添加

Python API For UE 4.26

还需要解决一个问题:每次运行函数前需要在PythonEditor中RUN一遍

希望这篇文档能帮到你!

你可能感兴趣的:(UE4,ue4,python,json,sequence)