test_perf_contacts.gd 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. extends Test
  2. const OPTION_TYPE_ALL = "Shape type/All"
  3. const OPTION_TYPE_BOX = "Shape type/Box"
  4. const OPTION_TYPE_SPHERE = "Shape type/Sphere"
  5. const OPTION_TYPE_CAPSULE = "Shape type/Capsule"
  6. const OPTION_TYPE_CYLINDER = "Shape type/Cylinder"
  7. const OPTION_TYPE_CONVEX = "Shape type/Convex"
  8. @export var spawns = []
  9. @export var spawn_count = 100
  10. @export var spawn_randomize = Vector3.ZERO
  11. var _object_templates = []
  12. var _log_physics = false
  13. var _log_physics_time = 0
  14. var _log_physics_time_start = 0
  15. func _ready():
  16. await start_timer(0.5).timeout
  17. if is_timer_canceled():
  18. return
  19. while $DynamicShapes.get_child_count():
  20. var type_node = $DynamicShapes.get_child(0)
  21. _object_templates.push_back(type_node)
  22. $DynamicShapes.remove_child(type_node)
  23. $Options.add_menu_item(OPTION_TYPE_ALL)
  24. $Options.add_menu_item(OPTION_TYPE_BOX)
  25. $Options.add_menu_item(OPTION_TYPE_SPHERE)
  26. $Options.add_menu_item(OPTION_TYPE_CAPSULE)
  27. $Options.add_menu_item(OPTION_TYPE_CYLINDER)
  28. $Options.add_menu_item(OPTION_TYPE_CONVEX)
  29. $Options.option_selected.connect(self._on_option_selected)
  30. await _start_all_types()
  31. func _exit_tree():
  32. for object_template in _object_templates:
  33. object_template.free()
  34. func _physics_process(delta):
  35. super._physics_process(delta)
  36. if _log_physics:
  37. var time = Time.get_ticks_usec()
  38. var time_delta = time - _log_physics_time
  39. var time_total = time - _log_physics_time_start
  40. _log_physics_time = time
  41. Log.print_log(" Physics Tick: %.3f ms (total = %.3f ms)" % [0.001 * time_delta, 0.001 * time_total])
  42. func _log_physics_start():
  43. _log_physics = true
  44. _log_physics_time_start = Time.get_ticks_usec()
  45. _log_physics_time = _log_physics_time_start
  46. func _log_physics_stop():
  47. _log_physics = false
  48. func _on_option_selected(option):
  49. cancel_timer()
  50. _despawn_objects()
  51. match option:
  52. OPTION_TYPE_ALL:
  53. await _start_all_types()
  54. OPTION_TYPE_BOX:
  55. await _start_type(_find_type_index("Box"))
  56. OPTION_TYPE_SPHERE:
  57. await _start_type(_find_type_index("Sphere"))
  58. OPTION_TYPE_CAPSULE:
  59. await _start_type(_find_type_index("Capsule"))
  60. OPTION_TYPE_CYLINDER:
  61. await _start_type(_find_type_index("Cylinder"))
  62. OPTION_TYPE_CONVEX:
  63. await _start_type(_find_type_index("Convex"))
  64. func _find_type_index(type_name):
  65. for type_index in range(_object_templates.size()):
  66. var type_node = _object_templates[type_index]
  67. if String(type_node.name).find(type_name) > -1:
  68. return type_index
  69. Log.print_error("Invalid shape type: " + type_name)
  70. return -1
  71. func _start_type(type_index):
  72. if type_index < 0:
  73. return
  74. if type_index >= _object_templates.size():
  75. return
  76. await start_timer(1.0).timeout
  77. if is_timer_canceled():
  78. return
  79. _log_physics_start()
  80. _spawn_objects(type_index)
  81. await wait_for_physics_ticks(5).wait_done
  82. _log_physics_stop()
  83. await start_timer(1.0).timeout
  84. if is_timer_canceled():
  85. return
  86. _log_physics_start()
  87. _activate_objects()
  88. await wait_for_physics_ticks(5).wait_done
  89. _log_physics_stop()
  90. await start_timer(5.0).timeout
  91. if is_timer_canceled():
  92. return
  93. _log_physics_start()
  94. _despawn_objects()
  95. await wait_for_physics_ticks(5).wait_done
  96. _log_physics_stop()
  97. await start_timer(1.0).timeout
  98. func _start_all_types():
  99. Log.print_log("* Start all types.")
  100. for type_index in range(_object_templates.size()):
  101. await _start_type(type_index)
  102. if is_timer_canceled():
  103. return
  104. Log.print_log("* Done all types.")
  105. func _spawn_objects(type_index):
  106. var template_node = _object_templates[type_index]
  107. Log.print_log("* Spawning: " + String(template_node.name))
  108. for spawn in spawns:
  109. var spawn_parent = get_node(spawn)
  110. for _node_index in range(spawn_count):
  111. # Create a new object and shape every time to avoid the overhead of connecting many bodies to the same shape.
  112. var collision = template_node.get_child(0).duplicate()
  113. collision.shape = collision.shape.duplicate()
  114. var body = template_node.duplicate()
  115. body.transform = Transform3D.IDENTITY
  116. if spawn_randomize != Vector3.ZERO:
  117. body.transform.origin.x = randf() * spawn_randomize.x
  118. body.transform.origin.y = randf() * spawn_randomize.y
  119. body.transform.origin.z = randf() * spawn_randomize.z
  120. var prev_collision = body.get_child(0)
  121. body.remove_child(prev_collision)
  122. prev_collision.queue_free()
  123. body.add_child(collision)
  124. body.set_sleeping(true)
  125. spawn_parent.add_child(body)
  126. func _activate_objects():
  127. Log.print_log("* Activating")
  128. for spawn in spawns:
  129. var spawn_parent = get_node(spawn)
  130. for node_index in range(spawn_parent.get_child_count()):
  131. var node = spawn_parent.get_child(node_index) as RigidBody3D
  132. node.set_sleeping(false)
  133. func _despawn_objects():
  134. Log.print_log("* Despawning")
  135. for spawn in spawns:
  136. var spawn_parent = get_node(spawn)
  137. # Remove objects in reversed order to avoid the overhead of changing children index in parent.
  138. var object_count = spawn_parent.get_child_count()
  139. for object_index in range(object_count):
  140. var node = spawn_parent.get_child(object_count - object_index - 1)
  141. spawn_parent.remove_child(node)
  142. node.queue_free()