Nature2D - 2D Physics Engine for UI Elements

When I used it, it was… PERFECT, it’s better than my GUI collision system which is just 3 lines of code lol.

1 Like

This is amazing! I was thinking of people playground right when I saw the demos. I am def going to make a people playground type sandbox game now.

1 Like

Created some new tutorials for the API that had not be covered in the documentation. New tutorials cover Collision Filtering for RigidBodies, Handling events for both Engine and RigidBodies as well as State Management/Custom Attribute management!

You can find them over at the documentation website under the tutorials category.

Handling Events
Collision Filtering
RigidBody State Management

I have been developing a new feature lately, which is the support of custom rigidbodies like triangles, irregular quadrilaterals and other polygons. This requires you to provide a structure of Rod Constraints and Points to construct a RigidBody on your own.

I have been puzzled about the creation of custom RigidBodies for some time now. Which creation method would be practical and user friendly?

I lay out some methods here:

Let me know what you think! If you have any other ideas, do share.

v0.5 - Custom RigidBody Support!

Major Release.

  • Fixed Engine:CreateCanvas() - Canvas’ can now be re-initialized.
  • Fixed Constraint:Render() - Prevent support constraints from rendering
  • Added support for custom RigidBodies
  • Added new Valid Property for RigidBodies - Structure: table
  • Updated Collision Detection and Response to work with custom RigidBodies
  • Updated Engine:Create()
  • Restrict certain methods from being used for custom RigidBodies

You can now create more than just rectangles and squares. You can now define your own point-constraint structures like triangles, irregular quadrilaterals and n-sided polygons and then turn them into RigidBodies! Here’s how Custom RigidBodies work and how you can create your own!

In the above image, the green dots are the arbitrary points we chose for our RigidBody, if we pass in a UI element, the 4 dots are automatically placed at its corners, also keeping in mind its rotation. There are 6 lines connecting the points all together. The lines in black are the edges of the RigidBody and the lines in red are “support constraints” which are meant to hold the RigidBody’s structure in place and it prevent it from collapsing into nothingness. It is worth noting that support constraints are not used in collision detection. All constraints are rods.

In order to create custom RigidBodies, you don’t need to specify a UI element/Object when using Engine:Create(). You would pass in a property called “Structure”. This contains a table of constraint data. Here’s how a structure looks like for a rectangle:

-- { Point1: Vector2, Point2: Vector2, Support: boolean }

local struct = {
    { Vector2.new(0, 0), Vector2.new(0, 10) },
    { Vector2.new(0, 10), Vector2.new(10, 10) },
    { Vector2.new(10, 10), Vector2.new(10, 0) },
    { Vector2.new(10, 0), Vector2.new(0, 0) },
    { Vector2.new(0, 0), Vector2.new(10, 10), true },
    { Vector2.new(10, 0), Vector2.new(0, 10), true }
}

You just need to provide the positions of the points of the edges and specify if they are support constraints or not! Note that in order to create custom rigidbodies, you must specify a frame for the Engine’s Canvas. You can then use Engine:Create() to turn this structure into a RigidBody. A simple example of a triangle:

local viewport = workspace.CurrentCamera.ViewportSize

local function MakeTriangle(a: Vector2, b: Vector2, c: Vector2)
	return {
		{ a, b, false }, 
        { a, c, false }, 
        { b, c, false }
	}
end

local triangle = Engine:Create("RigidBody", {
	Structure = MakeTriangle(viewport/2, viewport/2 + Vector2.new(-40, 80), viewport/2 + Vector2.new(40, 80)),
	Collidable = true,
	Anchored = false
})

Custom RigidBodies also support Quadtree collision detection! It is worth noting that not all methods will work for custom RigidBodies since the idea is fairly new. I will add the ability to use them in the future! If you try to use these methods, an error will pop up in the output window.


Updated Roblox Asset & Github

Updated Documentation

Updated Wally Package - 0.4.5 → 0.5.0


cc: @uhi_o

3 Likes

A little demonstration of the same. Custom RigidBodies will remain hollow and I don’t intend to make them have color inside. You are free to script triangulation to fill them :slight_smile:

4 Likes

Is it possible for soft bodies to be added?

With the recent addition of Custom RigidBodies, soft bodies are already possible to make! It requires a bit more work on your hand though. You can do that by combining different RigidBodies structures together to form a softbody. Even connecting multiple RigidBodies with Spring/Rod constraints will do it for you. Glad you brought this up, I’ll try to use my methods to make a softbody tomorrow and share the results with you!

And it’s done! I made a point-constraint structure in a grid like manner and here we have a Softbody!

It may collapse on low frame rates though. And collision detection isn’t the best with this sort of structure :(. Thus, try making softbodies that are smaller in size!

5 Likes

Thats really cool! Thanks! Im gonna try this out

1 Like

I’ve tried implementing character movement and I think I did it kind of? I got a frame that moves based on the user’s input by using ApplyForce not sure if this is the intended purpose of it though. I also couldn’t figure out how to keep the rigid body still it was very bouncy and kept turning around not sure if this is possible to fix though.

1 Like

ApplyForce will make the RigidBody accelerate, so if you want limit forces applied you could use the following method:

local maxForce = 0.5
body:ApplyForce(someForce)
body.forces = Vector2.new(math.clamp(body.forces.X, -maxForce, maxForce), body.forces.Y)

You can increase the Friction and AirFriction, fidget with the gravity and set the collision multiplier to something like 0.1! You can do that by Engine:SetPhysicalProperty()

v0.5.1 Support for different Masses of RigidBodies

You can now set any mass value you like for different RigidBodies to see changes in Collision Response and how forces are applied to each RigidBody. This paves the way for more accurate physical simulations with guis!

  • Added the ability to set a mass value other than 1 for different RigidBodies
  • Added new methods to RigidBodies
    • RigidBody:SetMass(mass: number)
  • Updated Point:ApplyForce() and RigidBody:ApplyForce(). Divides the force by the RigidBody’s mass to calculate acceleration.
  • Updated Collision detection and response to have effects according to the masses of each RigidBody. Now calculates accurate ratios for the force applied to each body after collision.
  • Cleaned some code, replaced bad practices with good ones, used Vector2:Dot() which is slightly faster than calculating the dot product of two vectors from scratch.

A little demonstration of the same. You can see the smaller box is having a hard time pushing the larger box because one has a mass of 100 and the smaller one has a mass of 1. A force of -0.35, 0 is being applied for 5 seconds on the smaller box.

1 Like

v0.5.2 - Introducing Nature2D Plugins!

  • Added new methods to Points
    • Point:SetMaxForce(maxForce: number)
  • Added new methods to RigidBodies
    • RigidBody:SetMaxForce(maxForce: number)
  • Added Plugins
    • Quad
    • Triangle
    • MouseConstraint

So what are these “Plugins” all about? Don’t get confused, these plugins are not Roblox Studio plugins. These plugins are essentially utility modules that many people may find useful! I decided to create some of them for practices which are prominent, like creating custom RigidBody structures and being able to drag and move RigidBodies here and there using the mouse button.

There are 3 Plugins available as of now

  • Quad - To create a 4 sided custom RigidBody structure given 4 points.
  • Triangle - To create a triangular custom RigidBody structure given 3 points.
  • MouseConstraint - A tool for dragging and moving RigidBodies using the mouse cursor.

In order to use plugins, you may require them in your script like this:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Plugins = require(ReplicatedStorage.Nature2D.Plugins) 

Example of the Triangle Plugin:

--[[
    Plugins.Triangle(a: Vector2, b: Vector2, c: Vector2)
]]

local TriangleBody = Engine:Create("RigidBody", {
    Mass = 5,
    Structure = Plugins.Triangle(Vector2.new(10, 10), Vector2.new(10, 20), Vector2.new(0, 20)),
    Collidable = true,
    Anchored = false
})

Example of the Quad Plugin:

--[[
    Plugins.Quad(a: Vector2, b: Vector2, c: Vector2, d: Vector2)
]]

local QuadBody = Engine:Create("RigidBody", {
    Mass = 5,
    Structure = Plugins.Quad(Vector2.new(0, 0), Vector2.new(20, 20), Vector2.new(0, 20), Vector2.new(20, 0)),
    Collidable = true,
    Anchored = false
})

Example of MouseConstraint:

--[[
    Plugins.MouseConstraint(engine: Engine, range: number)
]]

Plugins.MouseConstraint(Engine, 10) -- RigidBodies that are closest to the mouse and under a radius of 10 pixels can be dragged around by holding and moving the mouse.

image

If you wish to see more plugins be added, do share some feedback with me. If you wish to have your plugins be added to Nature2D, open a pull request at the Github Repository!


Updated Roblox Asset & Github

Updated Documentation

Updated Wally Package - 0.5.1 → 0.5.2



Documentation up to the latest version will be updated soo !

2 Likes

Was messing around with this, and accidentaly created a killing-low-end-pcs machine lol. other than fps, this is pretty cool!

Ah well, having so many RigidBodies spawned is going to make any PC lag. There can be a lot of optimizations in the code though. I’ll look into that and hopefully make this library faster than it is right now, sometime in the future.

Thanks! Glad you liked it.

2 Likes

This is pretty cool and interesting! Only one thing: this link is not working https://jaipack17.github.io/Nature2D/api/Engine
image

Thanks for letting me know! Fixed it!

2 Likes

Hey, I noticed that anchored RigidBodies with anchor points other than (0, 0) don’t mix well with the engine (but unanchored ones work fine).

Script:

local Nature2D = require(game:GetService("ReplicatedStorage").Nature2D)
local GuiBase = script:FindFirstAncestorOfClass("ScreenGui")
local MainFrame = GuiBase.Canvas

local Engine = Nature2D.init(GuiBase)

Engine:Create("RigidBody",{
	Object = MainFrame.Floor;
	Collidable = true;
	Anchored = true;
})

for i,v in pairs(MainFrame.Physics:GetChildren()) do
	Engine:Create("RigidBody",{
		Object = v;
		Collidable = true;
		Anchored = false;
	})
end

Engine:SetPhysicalProperty("Friction",math.huge)
Engine:Start()

Explorer:
Screen Shot 2021-12-20 at 2.41.57 PM
Anchor point of (0, 0):


Anchor point of (0.5, 0.5):
(I readjusted the frame to the middle)

Are there plans to fix this, or is it intended?

4 Likes