Applying collision to multiple meshes via Python

This is a continuation of an old thread from 2014, here:

Applying collision to multiple models? - World Creation - Epic Developer Community Forums

I’m using the python plugin by Roberto De Loris to generate collisions for multiple meshes (Thanks for the tip ex3me).
Source: GitHub - 20tab/UnrealEnginePython: Embed Python in Unreal Engine 4

Currently with one mesh selected in the scene, I run the following Python:

import unreal_engine as ue
from unreal_engine.classes import StaticMesh, StaticMeshComponent

actors = ue.editor_get_selected_actors()
print(actors)
staticMesh = actors[0].get_component_by_type(StaticMeshComponent)
aggregateGeom = staticMesh.StaticMesh.BodySetup.AggGeom
struct = aggregateGeom.get_struct()
print(aggregateGeom.as_dict())
#LogPython: {'SphereElems': [], 'BoxElems': [], 'SphylElems': [], 'ConvexElems': []}
print(aggregateGeom.set_field("ConvexElems"))
#LogPython:[]

This generates no collision and prints the following:

[<unreal_engine.UObject object at 0x000000000652FF60>]
{'SphereElems': [], 'BoxElems': [], 'SphylElems': [], 'ConvexElems': []}
set_field() takes at least 2 arguments (1 given)
Traceback (most recent call last):
File "<string>", line 11, in <module>
TypeError: set_field() takes at least 2 arguments (1 given)

I’ve tried with only one mesh or multiple meshes selected and get the same outcome.

Looking at lines 7 and 8 where I guess the action is supposed to be I see nothing but variable assignments so I’m not sure how this supposed to do anything anyway!

I’m kinda stumped!

Any help much appreciated!

Cheers, Graham

Hey, me again :slight_smile:

It seems the error you are getting on line 11 is caused by not passing enough parameters to function set_field(). As a first parameter you should pass the name of the field (string, as you do) and the second parameter should be the object (value) you are setting.

I assume second parameter should be the collision object you want to set. I think this piece of code should help you to generate some of the basic kdop collision objects available in UE: UnrealEnginePython/kdop.py at master · 20tab/UnrealEnginePython · GitHub

Hope it helps.

Thanks ex3me.

Thing is line 11 is just a print line. If I remove it I get no error message but still no collision is generated.

I did find that link too, and I’ve got it to add kdop10x/10y/10z/18 and 26 collisions just fine.

Working code: (need to select mesh in content browser for this one)

import unreal_engine as ue
from unreal_engine.structs import KAggregateGeom


mesh = ue.get_selected_assets()
for x in mesh:
	x.BodySetup.AggGeom = KAggregateGeom()
	x.static_mesh_generate_kdop10x()

My preference would be a “Box Simplified Collision” as that should be cheaper than the kdop10x.
I see no Python command to add “Box Simplified Collision” at that link and don’t see anything helpful in the documentation.

On line 11 you in fact also set the collisions (or you should), then you print the result of it, as far as I understand it (there are actually 2 functions called, print, and set_field, I believe the former is the one that is causing the issue).

For your second code, try saving the result of line 8 to a variable and see what it returns (via print). Then use set_field method as on line 11 (above above), but use that variable as the second parameter of the set_field() method.

As for the Box Collision…as far as I understand, the Python allows you to access C++ classes in some manner, so you could work with FKAggregateGeom | Unreal Engine Documentation (that should be what you have in x.BodySetup.AggGeom, if I get it correctly). If you notice, the class has method CalcAABB that should give you axis aligned bounding box, you can probably use that in the set_field method then (just a guess though, so I might be completly off).

How to use C++ methods is kinda sorta described in the readme file of the UnrealEnginePython such as:

vec = self.uobject.GetActorRightForward()

(sorry can’t tell you what specifically you need to call in your case as I don’t have access to UE at the moment)…but basically this means that if you find any way to generate bounding box in C++ this can be used in Python.

Thanks for the continued help. Its really appreciated!

I can’t seem to get “set_field” to work.

import unreal_engine as ue
from unreal_engine.structs import KAggregateGeom

mesh = ue.get_selected_assets()
for x in mesh:
	x.BodySetup.AggGeom = KAggregateGeom()
	MykdopVar = x.static_mesh_generate_kdop10x()
	print(MykdopVar)
	print(aggregateGeom.set_field("ConvexElems", MykdopVar))

Which prints:

[<unreal_engine.FVector object at 0x0000000008513130>, <unreal_engine.FVector object at 0x0000000008513230>, <unreal_engine.FVector object at 0x0000000008513210>, <unreal_engine.FVector object at 0x00000000085131F0>, <unreal_engine.FVector object at 0x00000000085131B0>, <unreal_engine.FVector object at 0x0000000008513250>, <unreal_engine.FVector object at 0x00000000085131D0>, <unreal_engine.FVector object at 0x0000000008513190>, <unreal_engine.FVector object at 0x0000000008513290>, <unreal_engine.FVector object at 0x00000000085132B0>]
unable to set property ConvexElems
Traceback (most recent call last):
  File "<string>", line 9, in <module>
Exception: unable to set property ConvexElems

I’m going to look into the C++ you mentioned now, in case “set_field” is not the answer.
But if I needed to understand how to use “set_field” is there a website I can go to read up on it? (I can’t expect to be hand held all the way!)
The Docs, tutorials and examples here:

GitHub - 20tab/UnrealEnginePython: Embed Python in Unreal Engine 4

have some info but it seems like it’s missing a great deal.

Hmm, this might be just a wrong type you are trying to set, but would be good if you could find what set_field takes :slight_smile:

From what I’m understanding this

aggregateGeom.set_field("ConvexElems", MykdopVar))

is equivalent to

aggregateGeom.ConvexElems = MykdopVar

and that would mean that you could get AABB as

box = aggregateGeom.CalcAABB()

nevertheless I’m not seeing the definition of aggregateGeom.

Secondly in Python you can check what methods can be called on the object (although I’m not sure this is gonna work if object is just a wrapper around C++), in this case by calling

print(dir(aggregateGeom))

but it should give you the methods available to you. Check if it has ConvexElems and CalcAABB, might give you some information about what you are against.

You can also try to get the documentation of the set_field() method by running

print(aggregateGeom.set_field.__doc__)

This might not tell you much, but you should at least see what parameters it takes. Goes same for other methods too.

I’m not seeing CalcAABB() anywhere (see results below), although in order to actually use it I think I’m going to have to run through a Python course or two as my lack of knowledge is severe! :frowning:
The more we get into this the more lost I’m getting (I don’t want to waste your efforts)

I don’t have the knowledge to understand how to utilise this yet, but in case you or anyone else is curious, I get the following info:

print(dir(aggregateGeom))

Result:

['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'as_dict', 'clone', 'fields', 'get_field', 'get_field_array_dim', 'get_struct', 'ref', 'set_field']

print(aggregateGeom.set_field.doc)

Result:

None

print(dir(aggregateGeom.set_field.doc))

Result:

['__bool__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

print(dir(aggregateGeom.ConvexElems))

Result:

['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

Thank again for your help!

well as one last effort then you could try to do

aggregateGeom.ConvexElems.append(MykdopVar)

it should insert created kdop as Convex Element…not sure it will fix the issue but eh.

Anyway, Python is easy to learn and fun to use so you should definetly go for it. It also seems this plugin came be very useful once you know what to look at a what to do ~~

This:

import unreal_engine as ue
from unreal_engine.structs import KAggregateGeom

mesh = ue.get_selected_assets()
for x in mesh:
	x.BodySetup.AggGeom = KAggregateGeom()
	MykdopVar = x.static_mesh_generate_kdop10x()
	aggregateGeom.ConvexElems.append(MykdopVar)

Returns this:

name 'aggregateGeom' is not defined
Traceback (most recent call last):
  File "<string>", line 8, in <module>
NameError: name 'aggregateGeom' is not defined

It still puts the kdop10x collision on my mesh but no box simplified collision in site!

For now I think I’ll have to just use the kdop10x collision for testing, then, when all is finalised I can convert to box simplified manually just the once. :slight_smile:

Time to bury myself in python tutorials now!
Thanks for the help, sorry it didn’t come to a proper result! (yet!!)