|
1 | 1 | # Plotting Graphs with Matplotlib and Unreal Engine Python |
2 | 2 |
|
| 3 | +In this tutorial we will see how to use third party python modules in your Unreal Engine projects. |
| 4 | + |
| 5 | +The module of choice is 'matplotlib' https://matplotlib.org/. |
| 6 | + |
| 7 | +From the official site: |
| 8 | + |
| 9 | +>Matplotlib is a Python 2D plotting library which produces publication quality figures in a variety of hardcopy formats and interactive environments across platforms. Matplotlib can be used in Python scripts, the Python and IPython shell, the jupyter notebook, web application servers, and four graphical user interface toolkits. |
| 10 | +
|
| 11 | +So our objective will be plotting graphs into Unreal Engine textures asset, both in the editor (to pre-generate assets) and during gameplay (to dynamically update texture-graph data) |
3 | 12 |
|
4 | 13 | ## Creating the project |
5 | 14 |
|
| 15 | +First step is obviously creating a new project. |
| 16 | + |
| 17 | +We will use the third person template |
| 18 | + |
6 | 19 |  |
7 | 20 |
|
8 | 21 | ## Installing the Python plugin |
@@ -60,6 +73,30 @@ ue.open_editor_for_asset(texture) |
60 | 73 |
|
61 | 74 | ## Our project: Plotting a Pie chart tracking overlap events |
62 | 75 |
|
| 76 | +Our objective is to have a special blueprint in our level exposing 3 cube in 3 different colors. |
| 77 | + |
| 78 | +Whenever you overlap one of the cubes with your character, their internal counter is incremented. |
| 79 | + |
| 80 | +A pie chart "carpet" is on the floor, and it is updated with overlap-counters data (the more you overlap a cube, the bigger will be its slice in the chart) |
| 81 | + |
| 82 | +### Setting up materials |
| 83 | + |
| 84 | +We need 4 materials and 1 material instance for the project: |
| 85 | + |
| 86 | +* a completely red material (just link a constant vector3 to base color) |
| 87 | + |
| 88 | +* a completely green material |
| 89 | + |
| 90 | +* a completely blue material |
| 91 | + |
| 92 | +* a material with a texture parameter linked to base color |
| 93 | + |
| 94 | +* an instance of the previous material exoosing the texture parameter (so it can be updated at runtime) |
| 95 | + |
| 96 | +### The "pie chart carpet" blueprint |
| 97 | + |
| 98 | + |
| 99 | + |
63 | 100 | ```python |
64 | 101 | import unreal_engine as ue |
65 | 102 | from unreal_engine.enums import EPixelFormat |
@@ -95,3 +132,69 @@ class PlotComponent: |
95 | 132 | self.fig.canvas.draw() |
96 | 133 | self.texture.texture_set_data(self.fig.canvas.buffer_rgba()) |
97 | 134 | ``` |
| 135 | + |
| 136 | +### The "Plotter Platforms" |
| 137 | + |
| 138 | +### Playing it |
| 139 | + |
| 140 | +### Writing a simple unit test |
| 141 | + |
| 142 | +Sorry, i will never stop telling you how important unit tests are, so, even if we have deloped a really simple script, we will write a unit test too :) |
| 143 | + |
| 144 | +We need to test that when a 'ComponentOverlap' event is triggered on a cube, the right counter is incremented: |
| 145 | + |
| 146 | +```python |
| 147 | +import unittest |
| 148 | +import unreal_engine as ue |
| 149 | +from unreal_engine.classes import Blueprint |
| 150 | + |
| 151 | +class TestPlotterPlatform(unittest.TestCase): |
| 152 | + |
| 153 | + def setUp(self): |
| 154 | + ue.allow_actor_script_execution_in_editor(True) |
| 155 | + ue.begin_transaction('test') |
| 156 | + self.world = ue.get_editor_world() |
| 157 | + self.blueprint = ue.load_object(Blueprint, '/Game/PlotterPlatforms.PlotterPlatforms') |
| 158 | + |
| 159 | + def tearDown(self): |
| 160 | + ue.end_transaction() |
| 161 | + ue.editor_undo() |
| 162 | + ue.allow_actor_script_execution_in_editor(False) |
| 163 | + |
| 164 | + def test_red_cube_overlap(self): |
| 165 | + actor = self.world.actor_spawn(self.blueprint.GeneratedClass) |
| 166 | + self.assertEqual(actor.RedCubeCounter, 0) |
| 167 | + actor.RedCube.broadcast('OnComponentBeginOverlap') |
| 168 | + self.assertEqual(actor.RedCubeCounter, 1) |
| 169 | + self.assertEqual(actor.GreenCubeCounter, 0) |
| 170 | + self.assertEqual(actor.BlueCubeCounter, 0) |
| 171 | + |
| 172 | + def test_green_cube_overlap(self): |
| 173 | + actor = self.world.actor_spawn(self.blueprint.GeneratedClass) |
| 174 | + self.assertEqual(actor.GreenCubeCounter, 0) |
| 175 | + actor.GreenCube.broadcast('OnComponentBeginOverlap') |
| 176 | + self.assertEqual(actor.RedCubeCounter, 0) |
| 177 | + self.assertEqual(actor.GreenCubeCounter, 1) |
| 178 | + self.assertEqual(actor.BlueCubeCounter, 0) |
| 179 | + |
| 180 | + def test_blue_cube_overlap(self): |
| 181 | + actor = self.world.actor_spawn(self.blueprint.GeneratedClass) |
| 182 | + self.assertEqual(actor.BlueCubeCounter, 0) |
| 183 | + actor.BlueCube.broadcast('OnComponentBeginOverlap') |
| 184 | + self.assertEqual(actor.RedCubeCounter, 0) |
| 185 | + self.assertEqual(actor.GreenCubeCounter, 0) |
| 186 | + self.assertEqual(actor.BlueCubeCounter, 1) |
| 187 | + |
| 188 | +if __name__ == '__main__': |
| 189 | + unittest.main(exit=False) |
| 190 | +``` |
| 191 | + |
| 192 | +You can run the unit test with: |
| 193 | + |
| 194 | +```python |
| 195 | +ue.sandbox_exec('test_plotter_platforms.py') |
| 196 | +``` |
| 197 | + |
| 198 | +the 'sanbox' execution, ensures a clean python subinterpeter is initialized, instead of clobberign the main one. |
| 199 | + |
| 200 | +Check how the test setUp and tearDown methods, ensure your world is cleaned up at the end (using the transaction api of unreal engine: https://github.com/20tab/UnrealEnginePython/blob/master/docs/Transactions_API.md) |
0 commit comments