Vật lý và khớp nối
KHIM mô phỏng part trên game server (và trong Play của KHIM Engine). Một unit bằng một stud; trọng lực 196,2 unit/s², như Roblox.
Neo hay thả
- Part neo (anchored) đứng yên tuyệt đối. Sàn, tường, nhà cửa.
- Part thả (
anchored = false) rơi, lăn, bị đẩy và va đập. Thùng gỗ, bóng, mảnh vỡ.
local crate = world.Crate
crate.anchored = false
crate:applyImpulse(vec3(0, 500, -300)) -- một cú đẩy, chia cho khối lượng của nó
crate.velocity = vec3(0, 50, 0) -- hoặc đặt vận tốcVật liệu và khối lượng
Part nặng bằng thể tích nhân mật độ vật liệu, và vật liệu quyết định độ bám và độ nảy:
| Vật liệu | Mật độ | Ma sát | Độ nảy |
|---|---|---|---|
| Plastic, Neon | 0.7 | 0.5 | 0.1 |
| Smooth | 0.7 | 0.3 | 0.1 |
| Wood | 0.35 | 0.6 | 0.05 |
| Glass | 2.4 | 0.25 | 0.2 |
| Metal | 7.8 | 0.4 | 0.05 |
| Grass | 0.9 | 0.65 | 0.05 |
| Brick | 1.9 | 0.75 | 0.05 |
| Concrete | 2.4 | 0.7 | 0.03 |
| Sand | 1.6 | 0.85 | 0 |
| Rock | 2.7 | 0.65 | 0.05 |
| Water | 1.0 | 0.1 | 0 |
| Leaves | 0.3 | 0.6 | 0.02 |
Vì vậy cùng một cú đẩy làm một part Metal lớn nhúc nhích ít hơn nhiều so với một part Wood nhỏ.
Nhóm va chạm
Mỗi part thuộc một nhóm va chạm (part.group, ban đầu là "Default"). Các nhóm quyết định thứ gì đi xuyên qua thứ gì:
local door = world.VipDoor
door.group = "VipDoor"
physics.collide("VipDoor", "Players", false) -- người chơi đi xuyên qua; thùng gỗ vẫn đụng vào
print(physics.collides("VipDoor", "Players")) -- false- Có sẵn: Default, Players (mọi nhân vật) và Ragdoll. Một world đặt thêm được 13 nhóm của riêng nó (mỗi tên tối đa 23 ký tự).
physics.collide(a, b, false)vớia == blàm các part trong cùng nhóm đi xuyên nhau.touchedvẫn chạy với các part không va chạm, nên cửa VIP vẫn biết ai đã đi qua.
Trong KHIM Engine bạn đặt bảng này không cần code: Inspector của part > Behavior > CollisionGroup > Which groups collide... (hoặc Insert > Collision groups) - một bảng ô tick.
Hàn (weld)
Weld giữ hai part dính làm một. KHIM Engine giữ weld giữa các part dựng cùng nhau, và clone() của một Model giữ chúng. Các part đã hàn không va chạm với nhau.
Khớp nối (joint)
Khớp nối đặt trong part chuyển động và trỏ tới part nó nối vào (part1):
| Khớp | Làm gì | Ví dụ |
|---|---|---|
| Hinge | Xoay quanh một trục | Cửa, bánh xe, cần gạt |
| Slider | Trượt dọc một trục | Thang máy, ngăn kéo, piston |
| BallJoint | Xoay mọi hướng quanh một điểm | Đèn treo trên xích |
| Spring | Kéo về một độ dài nghỉ | Giảm xóc xe, bạt nhún |
| Rope | Giữ khoảng cách không quá một độ dài | Xích đu, móc cần cẩu |
Trong KHIM Engine: chọn part sẽ được nối vào, Ctrl-bấm part chuyển động, rồi chèn khớp (Insert Object > Joints). Inspector đặt part kia, điểm neo, trục, giới hạn và motor.
Thành viên
| Thành viên | |
|---|---|
part1 | Part được nối vào |
anchor, axis | vec3 trong không gian part của chính nó |
enabled | Bật hay tắt |
limited, lower, upper | Hinge: độ; Slider: unit |
motor, speed, force | Tự quay/trượt: độ hoặc unit mỗi giây, với lực tối đa force |
angle (Hinge), offset (Slider) | Đã xoay / trượt bao nhiêu (chỉ đọc) |
length, stiffness, damping | Spring và Rope (length cho cả hai) |
-- Bệ xoay trên trụ (bệ không neo: khớp nối chỉ di chuyển part thả)
local spinner = new("Hinge", world.Platform)
spinner.part1 = world.Post
spinner.motor = true
spinner.speed = 45 -- độ mỗi giây
spinner.force = 100000
-- Cổng dựng trong KHIM Engine: giới hạn 0 tới 90, mở bằng một nút bấm
local gate = world.Gate.Hinge
world.Button.Clickable.clicked:connect(function()
gate.motor = true
gate.speed = 60 -- mở tới chốt 90 độ và giữ ở đó
end)Khớp nối hoạt động trên server. ClientScript đọc được nhưng không làm gì di chuyển bằng chúng.
Lực đẩy (mover)
Đặt vào một part thả để đẩy nó:
| Mover | Làm gì | Thành viên |
|---|---|---|
| Mover | Đẩy nó đi với một vận tốc, giữ nó chống lại trọng lực: bệ di động, drone | velocity, strength, relative |
| Spinner | Làm nó quay: quạt, bánh xe lăn | spin (radian mỗi giây quanh mỗi trục), strength, relative |
| Thruster | Đẩy bằng một lực đều: tên lửa, gió | force, relative |
local drone = new("Mover", world.Drone)
drone.velocity = vec3(0, 0, -10) -- bay ngang 10 unit mỗi giâyrelative = true làm véc-tơ xoay theo part (mặc định của Thruster: tên lửa đẩy theo hướng mũi nó).
Di chuyển part không cần vật lý
Với bệ và cửa cần đi đúng một đường, Motion (không cần code) hoặc tween đơn giản hơn vật lý:
world.Lift:tween({position = world.Lift.position + vec3(0, 20, 0)}, {time = 4, reverses = true, repeats = -1})Nhân vật đứng trên part đang di chuyển - tween, khớp nối, đang xoay - được chở theo.
Raycast
local hit = world:raycast(origin, direction) -- part đầu tiên dọc đường thẳng, hoặc nil
if hit then print(hit.part, hit.position, hit.normal, hit.distance) endĐộ dài của direction là khoảng cách nó dò.