I wish to hear your thoughts on a CanTouch property for RigidBodies that may be added in the future if a majority agrees. This feature is quite useful but has some drawbacks.
View the issue linked below for more information.
I wish to hear your thoughts on a CanTouch property for RigidBodies that may be added in the future if a majority agrees. This feature is quite useful but has some drawbacks.
View the issue linked below for more information.
May I ask, how do we add plugins to that module?
If you’re creating a plugin for yourself/locally then follow whatever coding pattern you wish to use.
If you’re wanting to add a plugin to the original library, which is for something that would take a lot of effort to make from scratch, but is easier to do with the help of your plugin. Then, fork the github repository, create the new plugin file under src/Plugins
and follow the given code structure:
return function (...)
-- plugin code
end
After you’ve completed coding the plugin module, go to src/Plugins/init.lua
and add your plugin to the dictionary that is returned.
Something like:
Hexagon = require(script.Hexagon) -- src/Plugins/Hexagon.lua
After you’ve made the required changes, open a pull request in the main repository. It’ll be merged and added to the library. You can take a look at other plugin modules for reference as well.
That’s fantastic; what else are you working on?
At present I’ve been working on supporting methods like :Clone(), :SetSize(), :SetPosition(), :Rotate() etc for Custom RigidBodies. Looking into creating more types of constraints. And also some other fixes, improvements and features!
I’ll surely look it over when you’re finished. I’m looking forward to seeing what you come up with.
KeepInCanvas
property not working for RigidBodies when using Engine:Create()
Engine:GetDebugInfo()
Engine:GetCurrentCanvas()
- Deprecation Warning.Engine.Updated
Engine.Updated:Connect(function()
-- do something
end)
Dark theme is now the default theme for the site.
Added a new installation method to the Installation category.
Better content readability.
Improved and updated change log.
Listed out properties for constraint, point and RigidBody API.
Listed notes and warnings in the API
Changed code block tab spacing to 4.
Categorized types, functions, fetch methods, events and properties. Visible in the sidebar of pages under API.
Tutorials for almost every concept!
I am in love, despite not even testing it out yet, haha!
Just curious, and forgive me if it is already a thing, but do you plan to add shape initiation? So you can define 4 points, and have a shape drawn between them, not sure if it is possible but maybe even make it so that you can define anywhere from 3 to however much and it would auto-generate a shape.
Also, any plans for texturing, so we can easily add textures?
A recent update made this possible! Not only 3 or 4, but any amount of points at different positions can be specified to form RigidBodies!
You can turn ImageLabels, ImageButtons and even ViewportFrames to 2D Rigid Bodies to do this!
I’ve been working on some major optimizations in the library and hope to get it done soon! These would include optimizations to collision detection, updating and rendering points and constraints, querying of rigid bodies during collision detection, collision related events of the Engine and RigidBodies, object creation and more.
The reason these optimizations are necessary is because of how the collisions between rigid bodies are not “rigid” enough, or in simple words - the rigid bodies are not really “rigid”. They act more like soft bodies. And, the cause of this is because of the extremely low amount of iterations performed each for calculating and rendering physics. You may notice, rigid bodies start clipping into each other when their numbers are increased, since there is an exponential spike in the calculations that take place causing frame drops.
Why do more iterations matter? Currently, physics calculations and updates to physics objects are performed just once every RenderStepped. During low frame rates or even high frame rates, collisions tend to happen in between 2 rendered frames, commonly at low frame rates since the delta time is higher. This means, less collision checks and responses are performed and the physics objects are updated and rendered at low frequency causing them to clip into each other.
Doing the same task multiple times helps in this case. For example, performing the physics calculations and updating the physics objects 6 times each frame means that there are 6 iterations being made. This maintains the “rigidness” of these physics objects and keeps them stable even at low frame rates.
A comparison between just 1 iteration and multiple iterations of physics calculations. From a matter.js demo.
1 Iteration | Multiple Iterations |
---|---|
Rigid bodies clip into each other very often. | The rigid bodies don’t clip into each other very often. |
Hopefully these optimizations will help me add more iterations to the physics calculations to make the rigid bodies actually rigid. At present, this is not possible. More iterations equals more lag.
You can track the changes and progress here:
These small optimizations will make it easier for me to add multiple iterations to the physics calculations! I’ll make more changes if needed.
You appear to be doing an excellent job! Best wishes!
Here’s some benchmarks (via boatbomber’s Benchmarker plugin) comparing the unoptimized version (v0.5.6) and the current optimized version (v0.5.7). I’ve edited Engine:Start()
locally to not connect a RenderStepped event before hand. So if you’re going to benchmark it, be sure to remove the RenderStepped connection and set dt as 1/60.
Also note, that in the benchmarks Engine:Start() has been made a non-yielding function. It is called multiple times by the plugin and not once every frame.
Each benchmark is ran for 2 seconds hence the number of function calls vary for different cases. Each benchmark has 100 data points.
Common Information:
return {
ParameterGenerator = function()
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Unoptimized = require(ReplicatedStorage.Original.Nature2D)
local Optimized = require(ReplicatedStorage.Nature2D)
local World = Instance.new("ScreenGui")
local Canvas = Instance.new("Frame")
Canvas.Name = "Canvas"
Canvas.Size = UDim2.fromScale(1, 1)
Canvas.Parent = World
local function MakeRigidBodies(Engine, num: number)
local collidable = true
for i = 1, num do
local frame = Instance.new("Frame")
frame.AnchorPoint = Vector2.new(.5, .5)
frame.Size = UDim2.fromOffset(50, 50)
frame.Position = UDim2.fromScale(.5, .5)
frame.Parent = World.Canvas
Engine:Create("RigidBody", {
Mass = 1,
Object = frame,
Collidable = collidable,
Anchored = false
})
collidable = not collidable
end
end
local Engine1 = Unoptimized.init(World)
Engine1:UseQuadtrees(false)
MakeRigidBodies(Engine1, 50)
local Engine2 = Optimized.init(World)
Engine2:UseQuadtrees(false)
MakeRigidBodies(Engine2, 50)
return Engine1, Engine2
end;
Functions = {
["Unoptimized"] = function(Profiler, Engine1, Engine2)
Engine1:Start()
end;
["Optimized"] = function(Profiler, Engine1, Engine2)
Engine2:Start()
end;
};
}
Unoptimized - 106.9603ms
Optimized - 33.5569ms
Common Information:
return {
ParameterGenerator = function()
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Unoptimized = require(ReplicatedStorage.Original.Nature2D)
local Optimized = require(ReplicatedStorage.Nature2D)
local World = Instance.new("ScreenGui")
local Canvas = Instance.new("Frame")
Canvas.Name = "Canvas"
Canvas.Size = UDim2.fromScale(1, 1)
Canvas.Parent = World
local function MakeRigidBodies(Engine, num: number)
local collidable = true
for i = 1, num do
local frame = Instance.new("Frame")
frame.AnchorPoint = Vector2.new(.5, .5)
frame.Size = UDim2.fromOffset(50, 50)
frame.Position = UDim2.fromScale(.5, .5)
frame.Parent = World.Canvas
Engine:Create("RigidBody", {
Mass = 1,
Object = frame,
Collidable = collidable,
Anchored = false
})
collidable = not collidable
end
end
local Engine1 = Unoptimized.init(World)
Engine1:UseQuadtrees(true)
MakeRigidBodies(Engine1, 50)
local Engine2 = Optimized.init(World)
Engine2:UseQuadtrees(true)
MakeRigidBodies(Engine2, 50)
return Engine1, Engine2
end;
Functions = {
["Unoptimized"] = function(Profiler, Engine1, Engine2)
Engine1:Start()
end;
["Optimized"] = function(Profiler, Engine1, Engine2)
Engine2:Start()
end;
};
}
Unoptimized - 70.2497ms
Optimized - 39.1559ms
How did you do the collision detection, this is epic!
Does this support cylinders and triangles and stuff like that tho
That’s a huge optimization! Nc.
It’s very complicated to make a very simple one, you need to compare the size added to the 2nd frame and compare the position added to the 2nd frame, therefore do the process again but instead of adding it, subtract it instead.
Read the actual post and some of the replies made by the OP because it shows triangles and circles:
Collision detection is handled by the Separating axis theorem. I wrote about it a few months ago here.
My library supports all convex shapes for rigidbodies. It supports concave shapes too but they’ll have a convex hitbox.