Skip to content

Commit 766ea83

Browse files
author
Roberto De Ioris
committed
2 parents edabdb5 + 9c61c31 commit 766ea83

File tree

1 file changed

+23
-22
lines changed

1 file changed

+23
-22
lines changed

docs/MemoryManagement.md

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,13 @@ import unreal_engine as ue
3131
from unreal_engine.classes import BlueprintFactory
3232

3333
factory = BlueprintFactory()
34+
texture = ue.create_transient_texture(512, 512)
3435
# run GC
3536
ue.console_exec('obj gc')
36-
# this will raise an exception as the UObject mapped to factory has been destroyed by the GC run
37+
3738
print(factory)
39+
# this will raise an exception as the UObject mapped to factory has been destroyed by the GC ru
40+
print(texture)
3841
```
3942

4043
By running this script you will end with something like this:
@@ -46,6 +49,10 @@ Traceback (most recent call last):
4649
Exception: PyUObject is in invalid state
4750
```
4851

52+
Here we are seeing two different behaviours between factory and texture. The first one survived the GC run, the second has been destroyed.
53+
54+
This is because only UObject's created explicitely by Python with a classic constructor (like BlueprintFactory()) are bound to the related ue_PyUObject. All of the others obey the Unreal GC rules. This is a pretty complex choice aimed at improving performance and avoiding too much competition between the two GCs.
55+
4956
Very long scripts, that do lot of stuff, often triggering UE4 GC, could be blocked in the middle of their execution by this kind of errors. In such a case (like you would do in C++) you need to inform the UE GC on how to deal with them (for avoiding their destruction).
5057

5158
Pay attention, as once you tell the UE GC to not destroy a UObject, that UObject (and its python mapping) will stay in memory (so you will end with a leak)
@@ -61,15 +68,13 @@ You can change this bitmask with the set_obj_flags() python function:
6168
```python
6269
import unreal_engine as ue
6370

64-
from unreal_engine.classes import BlueprintFactory
65-
66-
factory = BlueprintFactory()
71+
texture = ue.create_transient_texture(512, 512)
6772
# assign mask 0x00000001|0x00000002
68-
factory.set_obj_flags(ue.RF_PUBLIC|ue.RF_STANDALONE)
73+
texture.set_obj_flags(ue.RF_PUBLIC|ue.RF_STANDALONE)
6974
# run GC
7075
ue.console_exec('obj gc')
7176
# this will normally print the UObject repr
72-
print(factory)
77+
print(texture)
7378
```
7479

7580
The RF_Standalone flag (RF_STANDALONE in python api) will marks a UObject as 'standalone' so it will remain resident in memory forever.
@@ -79,23 +84,21 @@ Eventually you can reset/set the flags:
7984
```python
8085
import unreal_engine as ue
8186

82-
from unreal_engine.classes import BlueprintFactory
83-
84-
factory = BlueprintFactory()
85-
factory.set_obj_flags(ue.RF_PUBLIC|ue.RF_STANDALONE)
86-
87+
texture = ue.create_transient_texture(512, 512)
88+
# assign mask 0x00000001|0x00000002
89+
texture.set_obj_flags(ue.RF_PUBLIC|ue.RF_STANDALONE)
8790

8891
ue.console_exec('obj gc')
8992

90-
print(factory)
93+
print(texture)
9194

9295
# the second True argument will reset the flags (otherwise set_obj_flags will work in append mode)
9396
# eventually you can call factory.reset_obj_flags()
94-
factory.set_obj_flags(ue.RF_PUBLIC, True)
97+
texture.set_obj_flags(ue.RF_PUBLIC, True)
9598

9699
ue.console_exec('obj gc')
97100

98-
print(factory)
101+
print(texture)
99102
```
100103

101104
The second print will raise the error.
@@ -109,20 +112,18 @@ The root set is a very specific part of the GC tree. If you want to hold control
109112
```python
110113
import unreal_engine as ue
111114

112-
from unreal_engine.classes import BlueprintFactory
113-
114-
factory = BlueprintFactory()
115-
factory.add_to_root()
115+
texture = ue.create_transient_texture(512, 512)
116+
texture.add_to_root()
116117

117118
ue.console_exec('obj gc')
118119

119-
print(factory)
120+
print(texture)
120121

121-
factory.remove_from_root()
122+
texture.remove_from_root()
122123

123124
ue.console_exec('obj gc')
124125

125-
print(factory)
126+
print(texture)
126127
```
127128

128129
as before, the first GC run will not destroy the UObject (as it is in the root set), while the second one will remove if from the memory as it is no more in the root set.
@@ -150,7 +151,7 @@ tracker = Tracker()
150151
Now you can create UObject from python and track them automatically. When the python GC destroys the tracker object, all of the UObject's tracked by it will be destroyed too:
151152

152153
```python
153-
factory = tracker.track(BlueprintFactory())
154+
texture = tracker.track(ue.create_transient_texture(512, 512))
154155
```
155156

156157
As an example when running a script multiple times, the 'tracker' id will be overwritten, triggering the destruction of the mapped python object (and its ```__del__``` method)

0 commit comments

Comments
 (0)