Gain an in-depth understanding of how to build simple, powerful tools with Python to optimize performance and production. Together, we will install our Text Editor, explore the Unreal Python API structure, and begin writing our own Python scripts.
https://dev.epicgames.com/community/learning/courses/wk4/utilizing-python-for-editor-scripting-in-unreal-engine
In module 10, there’s a better way to assign the different materials using the Switch On Int node and creating a Material Interface variable:
I don’t mean to nitpick or anything, but this is useful flow control node and is definitely a little cleaner than what is done in the video.
Amazingly useful course, thanks so much. I really feel like I am learning a valuable skill that has very little resources anywhere on youtube or anything.
I have a question. Unless Python does something BP can’t (which I doubt since the Python API is just a wrapper for the C++ code, as mentioned in the video for module 10). Are there any contexts in which we prefer using python scripts over BP or vise versa? Let’s take the function getStaticMeshData() from module 6 as an example:
def get_SM_data():
static_meshes = get_asset_class('StaticMesh')
for mesh in static_meshes:
lod_group_info = mesh.get_editor_property('lod_group')
print (lod_group_info)
if lod_group_info == 'None':
if mesh.get_num_lods() == 1:
mesh.set_editor_property('lod_group', 'LargeProp')
We can achieve the exact same thing on an Editor Utility Widget here:
In having reconstructed the python code in the Editor Utility Widget, I am able to somewhat answer my own question. The BP code involved much more debugging due to any lack of documentation on how to implement this sort of thing. For example, the BP node GetEditorProperty returns a wildcard and when I initially attempted to Print String I was getting an error because it wanted to return a Name instead of string, so I figured out I had to use the type conversion node. The python code definitely makes editor scripting easier largely thanks to the documentation that makes implementation intuitive. On the other hand the BP code is more easily called from within the editor, makes use of both the event system and UMG so we can design the tools with buttons and text etc.
Hoping to hear from others their thoughts on this.
Thank you for sharing and the feedback. Getting to learn and see different approaches to doing things is exactly what makes having a community so valuable and special.
Cole, Epic Online Learning
Thank you for taking time to leave this useful tip - that is a much more manageable network!
Hi slim_sheady19 - Thanks for watching the course! I’m really glad you found it useful. There’s an important different between the two systems - Python is too slow to run during gameplay, so for runtime applications you have to use either BPs or C++. There are some contexts where blueprints can be run in editor, like Editor Utility Widgets, but the typical application is for gameplay. As with any complex system, there are usually a variety of different approaches to problem solving, each with its own advantages. I use Python to gather and modify data and to build tools. As your example demonstrates, for these kinds of tasks the well documented Python API is hard to beat, even as a cheat sheet for Blueprints. Thanks again for watching the course and taking time to leave such a detailed and thoughtful question!
import tutorial_script.py as TS — > DOES NOT WORK
import tutorial_script as TS —> DOES!
Here’s what I get when trying to import the tutorial_script:
LogPython: Error: Traceback (most recent call last):
LogPython: Error: File "<string>", line 1, in <module>
LogPython: Error: ModuleNotFoundError: No module named 'tutorial_script'```
Hello @ iLike2wina2- have you added the folder path to the project settings where you are saving your tutorial_script.py file?
Thank you for creating this course. I binged it over the weekend and I am looking forward to exploring Python for Editor and workflow automation.
@eco_bach2 You can use any project you like, the code is not project specific. You may run into issues that aren’t present in this level. If so just post here and I’ll try to get you sorted.
Getting an error with this module
The offending line seems to be
assetData = EAL.find_asset_data(assetPath)
But unclear how to correct.
It appears assetPath is an Objectpath and what I require is a FilePath. But cannot see any method in EditorAssetLibrary that returns a FilePath.
The error I am getting (in 5.1) is
…Accepting ObjectPaths is deprecated behavior and will be removed in a future release; TryConvertFilenameToLongPackageName will fail on ObjectPaths.
Also, any reason why my scripts take so long to execute? ie using the NorthWood project and the exact same methods in the tutorial, which take sometimes 20-30 seconds to execute.
Thanks in advance for any replies!
@eco_bach2
Yeah this is a new issue. It’s a simple fix - the assetPath has a dot at the end and the name of the asset repeated after. For some reason this is a problem. If you do a split at the dot and just use the path without the second instance of the name it should work fine. I have a more detailed explanation here:
Not sure why your scripts are taking a long time to execute. What are you trying to do, and how big is the project? Also, I don’t get an automatic ping when someone comments on this thread, so please @ me : )
@isaacoster Thanks Isaac!
Half a day later with a little help from ChatGPT I have a solution I wanted to share.
You’ll notice that I am using assetData.asset_class_path and not assetData.asset_class
def getAssetClass(classType):
EAL = unreal.EditorAssetLibrary
assetPaths = EAL.list_assets('/Game')
for i in range(len(assetPaths)):
assetPaths[i] = assetPaths[i].split(".", 1)[0]
assetData = EAL.find_asset_data(assetPaths[i])
assetClass = assetData.asset_class_path
#print(assetClass.asset_name)
if assetClass.asset_name == classType:
print(assetData)
In terms of Python execute time, I am using the Northwood project. When I run the above it takes about 7 seconds.
Have a AMD Threadripper CPU.
@isaacoster hoping to get your help with a problem posted here
Any ideas?
Thank you for this resource! I love python, is such a great addition to the engine. I’d love if i could use it even more maybe for small in-game scripts that are not time sensitive.
Small feedback on the course. Please consider using a bigger font/smaller screen resolution. i cant really read the font or icons everything is too small.
Also great idea to use the forum as a way to talk about the project and share doubts/solutions!
- Have a problem on module Getting Asset Class - Utilizing Python for Editor Scripting in Unreal Engine (epicgames.com)
It seems that asset_data.asset_class
is returning None
(string "None"
to be exact) for some reason. asset_data.get_class().get_name()
works though.
import unreal
def get_asset_class():
EAL = unreal.EditorAssetLibrary
asset_paths = EAL.list_assets('/Game')
for asset_path in asset_paths:
asset_data = EAL.find_asset_data(asset_path)
print(asset_data.asset_class, asset_data.get_class().get_name())
get_asset_class()
Output:
None TextureCube
None Texture2D
None Texture2D
None Texture2D
None Texture2D
None Texture2D
None Texture2D
- Noticed that on prelast module we just use
try
andexcept
to make sure material instance hastexture_parameter_values
editor property. Is there some other more safe way to check if object has editor property?
Currently I’ve made up my own function to check it:
def safe_get_editor_property(obj, attr: str, fallback_value = None):
try:
prop_value = obj.get_editor_property(attr)
return prop_value
except Exception as e:
missing_prop_error_msg = f": Failed to find property '{attr}' for attribute '{attr}' on "
if missing_prop_error_msg in str(e):
return fallback_value
raise e
For anyone who is taking a course on Unreal Engine 5.3 and has encountered a problem with the getAssetClass (Section: “Getting Asset Class”) function not working, I have the following fix:
def getAssetClassOld(classType):
EAL = unreal.EditorAssetLibrary
assetPaths = EAL.list_assets('/Game/')
assets = []
for assetPath in assetPaths:
assetData = EAL.find_asset_data(assetPath)
assetClass = assetData.asset_class_path
if assetClass.asset_name == classType:
assets.append(assetData.get_asset())
for asset in assets: print(asset)
return assets
So all the difference in “assetClass” variable. Since the “.asset_class” is deprecated, now we need to use “.asset_class_path” and also convert it to the class name with “assetClass.asset_name”.
All info found here:
https://docs.unrealengine.com/5.3/en-US/PythonAPI/class/AssetData.html#unreal.AssetData
https://docs.unrealengine.com/5.3/en-US/PythonAPI/class/TopLevelAssetPath.html#unreal.TopLevelAssetPath
I hope it will be useful to someone.
@isaacoster Thanks a lot for creating these great tutorials! Any chance of getting tutorials of Python and Niagara? Things like managing and setting various properties, user parameters, emitters, etc. Doesn’t seem to be as straight-forwards and other assets.