官网PythonAPI教程
教程链接https://dev.epicgames.com/community/learning/courses/wk4/an-in-depth-look-at-using-python-for-game-development/vymW/an-in-depth-look-at-using-python-for-game-development-introduction
获得路径下的所有文件路径
def listAssetPaths(path=‘/Game’): assetPaths = unreal.EditorAssetLibrary.list_assets(path) for assetPath in assetPaths: print(assetPath)
EditorUtilityLibrary和EditorActorSubsystem
EditorUtilityLibrary可以让我们获取和内容浏览器有关的功能 EditorActorSubsystem可以可以提供和世界大纲视图有关的功能(这个类在UE5里面有,UE4.27里面没有) EditorLevelLibrary 和 EditorActorSubsystem具有差不多的功能,UE4.27可以用这个来尝试代替EditorActorSubsystem
EditorUtilityLibrary
方法:get_selected_assets (获取选择的资产) 举例: # 输出选择的资产的对象信息 def getSelectionContentBrowser(): selectAssets = unreal.EditorUtilityLibrary.get_selected_assets() for selectAsset in selectAssets: print(selectAsset)
EditorActorSubsystem(这个类在UE5里面有,UE4.27里面没有)
方法: get_all_level_actors(获取关卡中的所有ACtor) EAS是变量名无需深究
get_selected_level_actors(获取选择的关卡actor)
EditorLevelLibrary(4.27可以使用的和EditorActorSubSystem差不多功能的类)(UE5虽然也能使用但是将要废弃这个类)
方法:get_all_level_actors(获取关卡中的所有ACtor) 同样是获取关卡中的所有ACtor经过测试4.27版本的UE使用这个类是不需要参数传递的,EditorActorSubsystem的这个方法需要传递参数。
按类组织资产
EditorAssetLibrary
方法:find_asset_data(asset_path)→AssetData 接受资产路径返回资产的数据,类型为AssetData。什么是AssetData类型:AssetData类型存取了资产的各种信息,可以直接print AssetData类型的变量可以发现它是一个字典。这个类型也自带一些方法,比如获取资产的名字,长名,资产的类型,判断是否加载等。https://docs.unrealengine.com/4.27/en-US/PythonAPI/class/AssetData.html#unreal.AssetData
1 2 3 4 5 6 7 8 9 10 11 def getAssetClass (classType ): assetPaths = unreal.EditorAssetLibrary.list_assets('/Game/MyAsset' ) print (assetPaths) assets = [] for assetPath in assetPaths: assetData = unreal.EditorAssetLibrary.find_asset_data(assetPath) assetClass = assetData.asset_class if assetClass == classType: assets.append(assetData.get_export_text_name()) for asset in assets: print (asset)
获取特定类的信息
首先看到这一节可以明确的感知到,UEPython中有很多自定义的类型,然后这些类型都有属于自己的函数,因此帮助文档很重要。 staticMesh, 编辑器属性就是这种类型的可调节的属性,我们可以通过staticMesh类型的对象中的get_editor_property方法来获取这些属性 它们都继承自_ObjectBase 所以对象也可以使用这些方法,例如get_name
StaticMesh的AssetImportData与lod_group属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 def getAssetClass (classType ): assetPaths = unreal.EditorAssetLibrary.list_assets('/Game' ) assets = [] for assetPath in assetPaths: assetData = unreal.EditorAssetLibrary.find_asset_data(assetPath) assetClass = assetData.asset_class if assetClass == classType: assets.append(assetData.get_asset()) return assets def getStaticMeshData (): staticMeshs = getAssetClass('StaticMesh' ) for staticMesh in staticMeshs: if staticMesh.get_editor_property('lod_group' ) == 'None' : if staticMesh.get_num_lods() == 1 : staticMesh.set_editor_property('lod_group' , 'LargeProp' )
获取staticMesh的lod数据
先提一下名词解释,这里使用的方法除了利用了lod的索引外还利用了分段的索引,通过观看教程理解分段的意义:首先我们的目的是获取这里模型的三角形的数量 ,当切换一个LOD时分段数量跟材质球的数量是相同的,也就是说分段的意思是当前LOD对应的模型的组成数量。 涉及到的类与方法: ProceduralMeshLibrary:get_section_from_static_meshhttps://docs.unrealengine.com/4.27/en-US/PythonAPI/class/ProceduralMeshLibrary.html?highlight=proceduralmeshlibrary#unreal.ProceduralMeshLibrary 得到的数据经过输出可以看出来得到的是一个元组,元组里面有多个数组元素组成,有意向可以遍历这些数组来观察数组中的内容。因为我们需要得到三角形的数量遍历三角形的数据后发现官方输出了很多重复的数据,当我们把数组的长度除以3以后才能够得到我们需要的正确的三角形的数量。 “很多数值是重复的 我想这是因为输出了 和每个三角形有关的所有顶点 之所以这么认为是因为 如果让这个数字 这个长度 我们可以生成它 然后除以3 得到的结果 就是我们想要的数据 这是个窍门 只是个小窍门 只要让这个数组的长度除以3”这是官方教程的原话
StaticMesh: get_num_sections(lod)得到模型的lod对应的分段数https://docs.unrealengine.com/4.27/en-US/PythonAPI/class/StaticMesh.html?highlight=staticmesh#unreal.StaticMesh.get_num_sections
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 def getAssetClass (classType ): assetPaths = unreal.EditorAssetLibrary.list_assets('/Game' ) assets = [] for assetPath in assetPaths: assetData = unreal.EditorAssetLibrary.find_asset_data(assetPath) assetClass = assetData.asset_class if assetClass == classType: assets.append(assetData.get_asset()) return assets def getStaticMeshLODData (): staticMeshs = getAssetClass('StaticMesh' ) for staticMesh in staticMeshs: staticMeshTriCount = [] numLODs = staticMesh.get_num_lods() for i in range (numLODs): LODTriCount = 0 numSections = staticMesh.get_num_sections(i) for j in range (numSections): sectionData = unreal.ProceduralMeshLibrary.get_section_from_static_mesh(staticMesh, i, j) sectionTriCount = (len (sectionData[1 ]) / 3 ) LODTriCount += sectionTriCount staticMeshTriCount.append(LODTriCount) staticMeshReductions = [100 ] for i in range (1 , numLODs): staticMeshReductions.append(int (staticMeshTriCount[i]/staticMeshTriCount[0 ]*100 )) print (staticMesh.get_name()) print (staticMeshTriCount) print (staticMeshReductions)
获取关卡中的模型以及出现的数量
因为是要获取实例化的数量也即获取关卡中存在的Actor,因此要使用EditorLevelLibrary中的方法 在这里获得到了个小知识点, 当我们将内容浏览器中的资产拖入到关卡中,ue会自动将其变成staticMeshActor类型,因此找到关卡中出现的Actor以后还需要找到这个Acotr对应的组件,然后再根据组件找到对应的静态网格体。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 def getStaticMeshInstanceCounts (): levelActors = unreal.EditorLevelLibrary().get_all_level_actors() staticMeshActors = [] staticMeshActorCounts = [] for levelActor in levelActors: if (levelActor.get_class().get_name()) == 'StaticMeshActor' : staticMeshComponent = levelActor.static_mesh_component staticMesh = staticMeshComponent.static_mesh staticMeshActors.append(staticMesh.get_name()) processedActors = [] for staticMeshActor in staticMeshActors: if staticMeshActor not in processedActors: actorCounts = (staticMeshActor, staticMeshActors.count(staticMeshActor)) staticMeshActorCounts.append(actorCounts) processedActors.append(staticMeshActor) staticMeshActorCounts.sort(key=lambda a: a[1 ], reverse=True ) for item in staticMeshActorCounts: print (item)
LOD视图的开启与介绍
白色代表LOD0,红色代表LOD1,依次往后是绿色蓝色
获取关卡中的模型名字以及对应的在场景中的LOD1的三角形数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 def getStaticMeshLODData (): staticMeshs = getAssetClass('StaticMesh' ) staticMeshLODData = [] for staticMesh in staticMeshs: staticMeshTriCount = [] numLODs = staticMesh.get_num_lods() for i in range (numLODs): LODTriCount = 0 numSections = staticMesh.get_num_sections(i) for j in range (numSections): sectionData = unreal.ProceduralMeshLibrary.get_section_from_static_mesh(staticMesh, i, j) sectionTriCount = (len (sectionData[1 ]) / 3 ) LODTriCount += sectionTriCount staticMeshTriCount.append(LODTriCount) staticMeshReductions = [100 ] for i in range (1 , numLODs): staticMeshReductions.append(int (staticMeshTriCount[i] / staticMeshTriCount[0 ] * 100 )) try : LODData = (staticMesh.get_name(), staticMeshTriCount[1 ]) except : pass staticMeshLODData.append(LODData) return staticMeshLODData def getStaticMeshInstanceCounts (): levelActors = unreal.EditorLevelLibrary().get_all_level_actors() staticMeshActors = [] staticMeshActorCounts = [] for levelActor in levelActors: if (levelActor.get_class().get_name()) == 'StaticMeshActor' : staticMeshComponent = levelActor.static_mesh_component staticMesh = staticMeshComponent.static_mesh staticMeshActors.append(staticMesh.get_name()) processedActors = [] for staticMeshActor in staticMeshActors: if staticMeshActor not in processedActors: actorCounts = (staticMeshActor, staticMeshActors.count(staticMeshActor)) staticMeshActorCounts.append(actorCounts) processedActors.append(staticMeshActor) staticMeshActorCounts.sort(key=lambda a: a[1 ], reverse=True ) LODData = getStaticMeshLODData() aggregateTriCounts = [] for i in range (len (staticMeshActorCounts)): for j in range (len (LODData)): if staticMeshActorCounts[i][0 ] == LODData[j][0 ]: aggregateTriCount = (staticMeshActorCounts[i][0 ],staticMeshActorCounts[i][1 ] * LODData[j][1 ]) aggregateTriCounts.append(aggregateTriCount) aggregateTriCounts.sort(key=lambda a: a[1 ], reverse=True ) for item in aggregateTriCounts: print (item)
dir()与help(),材质实例
当知道一个类的名字以后,如果想要得到这个类对应的所有方法,可以通过dir()函数来得到,并且有的方法官方文档可能没有。 例如如果想知道StaticMeshComponent的方法可以通过: for item in dir(unreal.StaticMeshComponent): print (item) 得到类对应的所有方法,并且可以通过搜索得到对应的方法,知道方法的名字后可以使用help()函数来得到方法的细节:help(unreal.StaticMeshComponent.get_num_materials) 将场景中的所有模型的材质更改为/Game/python/MI_test这个材质实例
1 2 3 4 5 6 7 8 9 10 11 def returnMaterialInformationSMC () : levelActors = unreal.EditorLevelLibrary ().get_all_level_actors () testMat = unreal.EditorAssetLibrary.find_asset_data ('/Game/python/MI_test' ).get_asset () for levelActor in levelActors: if (levelActor.get_class ().get_name ()) == 'StaticMeshActor' : staticMeshComponent = levelActor.static_mesh_component for i in range (staticMeshComponent.get_num_materials ()): staticMeshComponent.set_material (i, testMat)
使用关卡蓝图更改模型材质
根据场景中的staticmesh的material数量决定使用不同的材质实例,只在运行游戏时启用。