You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: lua/docs/content/reference/object.yml
+97-53Lines changed: 97 additions & 53 deletions
Original file line number
Diff line number
Diff line change
@@ -36,7 +36,7 @@ properties:
36
36
description: |
37
37
Collision groups the [This] belongs to.
38
38
39
-
⚠️ It doesn't mean the [This] will collide with other [Object]s in these groups.
39
+
⚠️ It doesn't mean the [This] will collide with other [Object]s in these groups.
40
40
41
41
If the [This] belongs to group number `3` for example, it means all [Object]s that have group number `3` in their [Object].[CollidesWithGroups](#property-collideswithgroups) property will collide with it.
42
42
@@ -45,46 +45,79 @@ properties:
45
45
- [Player]s collide with the [Map] only
46
46
47
47
That can all be configured differently depending on your needs.
48
+
49
+
Collision groups are best used as buckets created for gameplay needs, for example,
50
+
- a group for "hittable" objects that can be damaged by the player's weapon
51
+
- a group for recyclable Objects that are disabled and thrown back into their pool when they reach a certain trigger collider
52
+
- a group for static scenery objects that moving objects will bump into
53
+
- a group for objects that can get hit by raycasts executed for some specific game mechanic
54
+
It may well be the case that one object belongs to several or all of these groups, depending on the gameplay associated with it.
55
+
56
+
In general, it is bad practice to assign or add all collision groups from one object to another (unless making exact copies), as it isn't future-proof if you later add more groups. Instead, you should assign individual groups depending on what this new object should contribute to in your world.
48
57
49
58
samples:
50
59
- code: |
51
-
local object1 = Object()
52
-
local object2 = Object()
53
-
object1.Physics = PhysicsMode.Dynamic
54
-
object2.Physics = PhysicsMode.Dynamic
55
-
56
-
-- making sure 2 objects collide with each other
57
-
-- NOTE: by default:
58
-
-- Map.CollisionGroups == {1},
59
-
-- Player.CollisionGroups == {2},
60
-
-- Object.CollisionGroups == {3}
61
-
object1.CollisionGroups = {5}
62
-
object2.CollisionGroups = {5}
63
-
object1.CollidesWithGroups = {1, 5} -- collides with Map + objects in group 5
64
-
object2.CollidesWithGroups = {1, 5} -- collides with Map + objects in group 5
65
-
66
-
-- would also work this way if you don't
67
-
-- remember Map's group (which can be changed too by the way)
-- let's say our world needs an extra group for a gameplay mechanic, for example, a group for objects that can be hit by player's weapon (which could perform a raycast in that group)
74
+
local GROUP_HITTABLE = 4
75
+
76
+
-- here, the object would collide with anything that cares about GROUP_OBJECT or GROUP_HITTABLE, in addition to itself wanting to collide with GROUP_MAP and GROUP_PLAYER
-- when adding new obstacle/scenery objects to our scene, you can simply re-use the GROUP_MAP as a way to say "this is part of the environment that is collidable"
81
+
-- here, maybe this object only acts as an obstacle and doesn't contribute to anything else
82
+
someBigRock.CollisionGroups = GROUP_MAP
83
+
someBigRock.CollidesWithGroups = nil
84
+
85
+
-- doing this effectively prevents all physics interaction on an object
86
+
o.CollisionGroups = nil
87
+
o.CollidesWithGroups = nil
88
+
89
+
-- note that there is redundancy with CollisionGroups and CollidesWithGroups, so you can organize your groups however seems more convenient for you
90
+
-- for example the following setups will all result in object1 and object2 colliding with each other
91
+
object1.CollisionGroups = GROUP_OBJECT
92
+
object1.CollidesWithGroups = nil
93
+
object2.CollisionGroups = GROUP_OBJECT
94
+
object2.CollidesWithGroups = GROUP_OBJECT
95
+
96
+
object1.CollisionGroups = GROUP_OBJECT
97
+
object1.CollidesWithGroups = GROUP_OBJECT
98
+
object2.CollisionGroups = GROUP_OBJECT
99
+
object2.CollidesWithGroups = nil
100
+
101
+
object1.CollisionGroups = GROUP_OBJECT
102
+
object1.CollidesWithGroups = GROUP_OBJECT
103
+
object2.CollisionGroups = GROUP_OBJECT
104
+
object2.CollidesWithGroups = GROUP_OBJECT
105
+
106
+
object1.CollisionGroups = GROUP_OBJECT
107
+
object1.CollidesWithGroups = nil
108
+
object2.CollisionGroups = nil
109
+
object2.CollidesWithGroups = GROUP_OBJECT
76
110
77
111
- name: "CollidesWithGroups"
78
112
type: "CollisionGroups"
79
113
description: |
80
-
Collision groups the [This] collides with.
114
+
Collision groups the [This] collides with. See [This].[CollisionGroups](#property-collisiongroups).
81
115
82
116
By default:
83
117
- [Object]s collide with the [Map] and other [Object]s
84
118
- [Player]s collide with the [Map] and the [Object]s
85
119
86
120
That can all be configured differently depending on your needs.
87
-
88
121
samples:
89
122
- code: |
90
123
local object = Object()
@@ -247,12 +280,15 @@ properties:
247
280
- name: "Tick"
248
281
type: "function"
249
282
description: |
250
-
Tick is a [function] executed ~30 times per second when set ([nil] by default). Provides the [This] and elapsed time in seconds as parameters.
283
+
Tick is a [function] executed each frame when set ([nil] by default). Provides the [This] and elapsed time in seconds as parameters.
284
+
285
+
For general purposes, you may consider using [Client.Tick](reference/client#functions-tick) instead. It is functionally the same, but is executed once for your world per frame, rather than once per frame per object.
286
+
287
+
The exact number of frames per second may fluctuate and depend on the device. It is typically around 60 frames per second.
251
288
samples:
252
289
- code: |
253
-
-- executed ~30 times per second on each user device
254
290
myObject.Tick = function(object, dt)
255
-
print("elapsed:", dt, "seconds")
291
+
print("elapsed:", dt, "seconds since last frame")
256
292
end
257
293
258
294
- name: "LocalRotation"
@@ -267,8 +303,7 @@ properties:
267
303
description: |
268
304
Velocity of the [This] in world coordinates per second.
269
305
270
-
⚠️ `Velocity` only affects [This] when [This].[Physics](#property-physics) is `PhysicsMode.Dynamic`.
271
-
Whenever [Physics](#property-physics) is set to `PhysicsMode.Disabled`, `Velocity` is set to `{0,0,0}`.
306
+
⚠️ `Velocity` only affects [This] when [This].[Physics](#property-physics) is `PhysicsMode.Dynamic`.
272
307
samples:
273
308
- code: |
274
309
-- makes myObject jump:
@@ -277,18 +312,11 @@ properties:
277
312
- name: "Motion"
278
313
type: "Number3"
279
314
description: |
280
-
Be aware, this `Motion` property is a hack regarding laws of physics. (sorry Isaac)
281
-
282
-
But it's very practical to move objects without worrying about forces at play.
283
-
284
-
This is what's being used by default when you're moving around with your avatar (see [Client.DirectionalPad](/reference/client#property-directionalpad)). It's the reason why you can stop moving horizontally while in the air.
315
+
`Motion` is an instantaneous displacement that contributes to moving [This] every frame, without changing [This].[Velocity](#property-velocity) directly, and without being affected by collision responses and other forces. It is expressed in world coordinates per second.
285
316
286
-
Basically, `Motion` is an instantaneous displacement that contributes to moving [This] every frame, without changing [This].[Velocity](#property-velocity) directly.
317
+
It's very useful to quickly implement character movement. This is what's being used by default when you're moving around with your avatar (see [Client.DirectionalPad](/reference/client#property-directionalpad)). It's the reason why you can stop moving horizontally while in the air.
287
318
288
-
`Motion` is expressed in world coordinates per second.
289
-
290
-
⚠️ `Motion` only affects [This] when [This].[Physics](#property-physics) is `PhysicsMode.Dynamic`.
291
-
Whenever [Physics](#property-physics) is set to `PhysicsMode.Disabled`, `Motion` is set to `{0,0,0}`.
319
+
⚠️ `Motion` only affects [This] when [This].[Physics](#property-physics) is `PhysicsMode.Dynamic`.
292
320
samples:
293
321
- code: |
294
322
local speed = 10
@@ -297,24 +325,35 @@ properties:
297
325
-- If the Camera rotates after this, it won't change where myObject is heading.
298
326
299
327
- name: "LocalScale"
300
-
type: "number"
328
+
type: "Number3"
301
329
description: |
302
-
Scale of the [Object], in its parent.
330
+
Scale of the [Object], in its parent local space. Can be set to a `number` for a uniform scale.
303
331
304
332
Nested [Object] local scales are combined to obtain the "world scale" ([Object.LossyScale](#property-lossyscale)), the [Object]'s final scale.
305
333
samples:
306
334
- code: |
307
-
myObject.LocalScale = 2 -- the Object is now 2 times bigger
335
+
-- make the object twice as big
336
+
myObject.LocalScale = 2
337
+
338
+
-- equivalent to
339
+
myObject.LocalScale = Number3(2, 2, 2)
340
+
myObject.LocalScale = { 2, 2, 2 }
308
341
- code: |
309
-
topLevelObject.LocalScale = 2
310
-
local o = Object()
311
-
o.LocalScale = 0.5
312
-
topLevelObject:AddChild(o) -- o becomes a child of topLevelObject
313
-
-- o ends up being displayed with a scale of 1
342
+
-- demonstrate how scales are combined in the hierarchy
343
+
local parentObject = Object()
344
+
parentObject:SetParent(World)
345
+
parentObject.LocalScale = 2
346
+
347
+
local childObject = Object()
348
+
childObject:SetParent(parentObject)
349
+
childObject.LocalScale = 0.5
350
+
351
+
-- here, the scales would cancel each other: 2 x 0.5 = 1
352
+
print(childObject.LossyScale) -- returns (1,1,1)
314
353
315
354
- name: "LossyScale"
316
355
read-only: true
317
-
type: "number"
356
+
type: "Number3"
318
357
description: |
319
358
Convenience property that attempts to match the actual world scale as much as it can. Note that [Object]s that have multiple levels of nested rotations and scales will return a skewed lossy scale.
320
359
@@ -425,6 +464,9 @@ functions:
425
464
426
465
The `keepWorld` optional parameter, `false` by default, dictates whether to maintain the child's world or local position and rotation. Keeping world will ensure the object doesn't move in the scene, adjusting its local position/rotation accordingly; keeping local will have the object move in the scene in order to maintain an equivalent local position/rotation relative to its new parent.
427
466
467
+
It's a good practice to set child/parent relationships before setting positions, if you do not want to use the `keepWorld` parameter.
468
+
469
+
Note that there is a cyclic hierarchy protection that will prevent you from creating parenting loops.
428
470
samples:
429
471
- code: |
430
472
local o = Object()
@@ -465,7 +507,7 @@ functions:
465
507
466
508
The `config` table accepts two boolean options:
467
509
- `deepFirst`: if `true`, traverses depth-first instead of root-first. Default `false`.
468
-
- `includeRoot`: if `true`, includes [This] in the recursion. Default `false`.
510
+
- `includeRoot`: if `true`, includes [This] in the recursion. Default `true`.
469
511
arguments:
470
512
- name: "callback"
471
513
type: "function"
@@ -567,7 +609,9 @@ functions:
567
609
568
610
The `keepWorld` optional parameter, `false` by default, dictates whether to maintain the child's world or local position and rotation. Keeping world will ensure the object doesn't move in the scene, adjusting its local position/rotation accordingly; keeping local will have the object move in the scene in order to maintain an equivalent local position/rotation relative to its new parent.
569
611
570
-
It's also a good practice to set child/parent relationships before setting positions.
612
+
It's a good practice to set child/parent relationships before setting positions, if you do not want to use the `keepWorld` parameter.
613
+
614
+
Note that there is a cyclic hierarchy protection that will prevent you from creating parenting loops.
0 commit comments