unit_interaction.rst 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. ======================
  2. Interacting with Units
  3. ======================
  4. At some point you will probably need to reference units from the Lua scripts to
  5. manipulate their properties, be notified of particular events and make them do
  6. something interesting.
  7. Getting Unit handles
  8. --------------------
  9. The simplest way of getting a handle to a unit is to spawn it directly from a
  10. script:
  11. .. code:: lua
  12. player = World.spawn_unit(world, "units/player/player")
  13. In most cases, however, units are not spawned directly but rather as a
  14. consequence of loading levels in a world. You can get a table with all units
  15. spawned in a world this way:
  16. .. code:: lua
  17. local units = World.units(world)
  18. for _, u in ipairs(units) do
  19. -- Do something with Unit u.
  20. end
  21. To obtain a specific Unit by name (its name as set in the Level Editor, *not*
  22. the unit name itself):
  23. .. code:: lua
  24. door = World.unit_by_name(world, "main_door")
  25. The Script component
  26. --------------------
  27. Obtaining unit handles is useful but might not be enough. With a unit handle
  28. alone you can modify properties but you cannot receive events.
  29. Creating a Unit script
  30. ----------------------
  31. Unit scripts are a particular type of scripts that can be attached to units via
  32. a Script Component. To create a Unit script, right click on the Project Browser
  33. and choose ``New (Unit) script``.
  34. Crown will create a new Unit script similar to the following:
  35. .. code:: lua
  36. MyScript = MyScript or {
  37. data = {}
  38. }
  39. local data = MyScript.data
  40. -- Called after units are spawned into a world.
  41. function MyScript.spawned(world, units)
  42. if data[world] == nil then
  43. data[world] = {}
  44. end
  45. local world_data = data[world]
  46. for _, unit in pairs(units) do
  47. -- Store instance-specific data.
  48. if world_data[unit] == nil then
  49. world_data[unit] = {}
  50. end
  51. end
  52. end
  53. -- Called once per frame.
  54. function MyScript.update(world, dt)
  55. local world_data = data[world]
  56. for unit, unit_data in pairs(world_data) do
  57. -- Update unit.
  58. end
  59. end
  60. -- Called before units are unspawned from a world.
  61. function MyScript.unspawned(world, units)
  62. local world_data = data[world]
  63. -- Cleanup.
  64. for _, unit in pairs(units) do
  65. if world_data[unit] then
  66. world_data[unit] = nil
  67. end
  68. end
  69. end
  70. return MyScript
  71. Unit scripts work differently than similar solutions in other engines. Instead
  72. of getting many individual update() calls for each individual Unit, you will
  73. receive a single update() for *every* unit that has that particular script
  74. attached to it.
  75. This allows for efficient bulk updates, state sharing and it also make profiling
  76. code easier.
  77. Receiving collision events
  78. --------------------------
  79. To get physics collision notification events, implement any of the following
  80. callbacks in your script component:
  81. .. code:: lua
  82. function MyScript.collision_begin(world, unit, other_unit, actor, other_actor, position, normal, distance)
  83. -- Called when unit and other_unit begin touching.
  84. end
  85. function MyScript.collision_end(world, unit, other_unit)
  86. -- Called when unit and other_unit end touching.
  87. end
  88. function MyScript.collision_stay(world, unit, other_unit, actor, other_actor, position, normal, distance)
  89. -- Called between collision_begin() and collision_end() while the units remain touching.
  90. end
  91. Triggers
  92. --------
  93. Units whose actor is configured as a trigger (actor class 'trigger') will not
  94. receive regular collision events, instead, they will receive trigger events:
  95. .. code:: lua
  96. function MyScript.trigger_enter(world, trigger_unit, other_unit)
  97. -- Called when other_unit begins touching trigger_unit.
  98. end
  99. function MyScript.trigger_leave(world, trigger_unit, other_unit)
  100. -- Called when other_unit ends touching trigger_unit.
  101. end