Need help Simulating magnetism with Area2d and RogidBody2d

Godot Version

4.4.1

Question

In a 2d scene, I have some area2ds with its gravity less powerful than overall gravity. I have a rigidbody2d, which is controlled by the player, the player drags the screen in one direction and it gets flinged in opposite direction. Just plain stuff.

The area2d works like magnets, some will attract the rigidbody some will repel it. The problem I am facing is sometimes the area2ds with attraction force, when the rigidbody enters the area2d’s collision area in an angle, it will orbit a little before finally getting attached to the area2d core, as gravity works universally, but my magnets are supposed to attract others like in a straight line

I tried ditching the gravity stuff with just code like this,

# The code is in area2d's physics process
# Char -> Rigidbody2d 
if Char.GetPolarity() == GetPolarity():
    # Repel
    var diff : Vector2 = global_position - Char.global_position
    Char.apply_central_force(-diff.normalized() * 500)
else:
    var diff : Vector2 = (global_position - Char.global_position).normalized()
    Char.apply_central_force(diff.normalized() * 1500)

But the code works very similarly to gravity.
Here’s how the fling thing works in the rigidbody:

# posStart is where the dragging started
# local_position = to_local(global_position)
# vt is -(posEnd - posStart).limit_length(flingMaxLen) when the dragging was finished

func fling() -> void:
    var flingVector : Vector2 = posStart - local_position + vt
    var powerFactor = vt.length() / flingMaxLen
    var impulseVector = flingVector.normalized() * FLING_POWER * powerFactor
    apply_impulse(impulseVector)

I’d be grateful if anybody could help me figure out this problem.
Thank You.

I’m just spitballing here because there’s no visual and that’s how I see your problem in my head from what I read, but is it possible that the object “gravitates” for a bit because of the multiple attractors around, until the “strongest” actually wins and then it attaches to it?

If the magnet is strong enough, attracted objects should be expected to start orbitin the magnet and eventually fall into it, just like with planets orbiting a sun with gravity. Not sure if I understand the goal. Do you want the magnet to just slightly change the objects trajectory, without actually winning it over?

Maybe carefully balance the strength of the magnet so that if works correctly. I would also suggest dividing the strength by the distance, so that the effect is weaker when far away and stronger when near:

var diff : Vector2 = (global_position - Char.global_position) # <- I removed .normalized()
var dist = diff.length()
var diff = diff.normalized() / (1.0 + dist) # Divide by distance. That 1.0 is for avoiding division by zero.
Char.apply_central_force(diff * 1500) # Removed the .normalized() from here too.

I didn’t test this, but I think it might work if you find a good strength value. Adjust the “1500”.

Each magnet area2d will be quite far away from each other. Only one magnet’s power will effect the character at a time.

I couldn’t actually find any reference if magnets make others orbit around them.

I want the magnet to pull the character rigidbody2d towards the center when it gets within its range.

I will try tweaking it and let you know.

They wouldn’t. But, if you have several in “close” proximity, they would each pull an object which could be seen as “levitating” until the one strongest would pull it closer until it stuck to it.

Well, maybe they wouldn’t. But a magnetic monopole with an evenly distributed force might. Like this magnet in the code :slight_smile: (sorry this is offtopic)

If you’re attracting another magnet, sure.

I was experimenting with many things, If I set Char.gravity_scale = 0 when the rigid body is inside the area2d. I get results like this.

1

Otherwise as usual here’s the problem of orbiting without the gravity_scale = 0 thing

Untitledvideo-MadewithClipchamp2-ezgif.com-crop

By doing so without Char.gravity_scale = 0 It kinda doesn’t work no matter how much I increase it from 1500. But If I set Char.gravity_scale = 0 I get this type of result

2

Sorry, I didn’t think things completely trough. Divide by distance is too much in 2d, but if you first divide the dist by the areas radius, you get a nice fallof for the effect:
var dist = diff.length() / 80.0
In my test I have an area with a 80.0 radius circle.

magnet

Does this look like what you’re after? I find it very difficult to make it orbit. Unless I use linear damping on the RigidBody2D, that makes it much more prone to orbiting and locking in to the magnet. But I can still balance the forces so that it only nudges the trajectory.

I’m still not sure what you mean by this. Maybe you need to explain better what you want?

Here’s a test with a real magnet and a ball bearing:

I think this proves that magnets do cause objects to orbit (kinda). That nudge in the trajectory basically is just that: an orbit. Just not a stable orbit, and the object will quickly either escape, or fall into the magnet. If I remove gravity (pencil) from my experiment, the magnet wins and this causes a very eccentric but small orbit around the magnet. It looks more like vibrating than orbiting. My code behaves just like this realworld experiment.

In your videos you have a pretty realistic behaviour. I think it would be a fun mechanic if you just balance the forces to make it feel good. But I understand that in games the desired behaviour is not always the most realistic one.

Ah, the videos make things more clear. I too think that the current mechanism will be cool in game, it will allow things like trick shots. I’ll keep it.

Thank you for giving me your precious time.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.