I'm developing a client/server multiplayer game. in server side i need prevent players cross map objects like walls also i need prevent player go inside each others, instead want to slide them along each other (players are circle shape).
i tried few solution (own code and mathematical) i didn't achieve needs so i decide to use a 2d physic engine. as server code is c# language i select Aether.Physics2D (c# port of box2d). (i don't know if i made the right decision because my needs are a little part of a physic engine just character movement part so sounds good if some one lead me in true direction)
by the way in physic engine, map objects are static bodies and players are dynamic bodies. the static bodies part work fine so players can't cross wall, instead they slide along walls but dynamic bodies part.
the problem is when 2 dynamic body collide each other they push (force) each other that i don't want. if i change mask or filter collision groups, they go inside each other, is there any other solution?
what i need (expect) is : i need prevent players (dynamic bodies) go inside each other and prevent they push each other. once a player collide with another player must stop moving and slide (slip-over) like what happen in static walls.
i search it on google there were 2 solutions,first was combine a dynamic body with Kinematic as shield (code below) and second change player collision group. both not work as expected.
** C# test code with unity engine as visual **
public GameObject player1_sprite;
public GameObject player2_sprite;
public GameObject player1k_sprite;
public GameObject player2k_sprite;
public GameObject ground_sprite;
// Start is called before the first frame update
World world;
Body player1;
Body player2;
Body player1_shadow;
Body player2_shadow;
Body ground;
void Start()
{
//Create a world
world = new World();
world.Gravity = tainicom.Aether.Physics2D.Common.Vector2.Zero;
//-------------------------- player 1
player1 = world.CreateBody(new tainicom.Aether.Physics2D.Common.Vector2(50, 80), 10, BodyType.Dynamic);
var player1_fixure = player1.CreateCircle(5, 10f);
player1.Mass = 10;
player1_fixure.Friction = 1;
player1_fixure.Restitution = 0;
player1_fixure.CollisionCategories = Category.Cat1;
player1_fixure.CollidesWith = Category.Cat2;
//-------------------------- player 1 shadow
player1_shadow = world.CreateBody(new tainicom.Aether.Physics2D.Common.Vector2(50, 80), 0, BodyType.Kinematic);
var player1_shadow_fixure = player1_shadow.CreateCircle(5, 10f);
player1_shadow_fixure .Restitution = 0;
player1_shadow_fixure.CollisionCategories = Category.Cat2;
world.Add(new tainicom.Aether.Physics2D.Dynamics.Joints.WeldJoint(player1, player1_shadow,
tainicom.Aether.Physics2D.Common.Vector2.Zero, tainicom.Aether.Physics2D.Common.Vector2.Zero)
{ CollideConnected = false });
//-------------------------- player 2
player2 = world.CreateBody(new tainicom.Aether.Physics2D.Common.Vector2(50, 50), 10, BodyType.Dynamic);
var player2_fixure = player2.CreateCircle(5, 10f);
player2.Mass = 10;
player2_fixure.Restitution = 0;
player2_fixure.Friction = 1;
player2_fixure.CollisionCategories = Category.Cat1;
player2_fixure.CollidesWith = Category.Cat2;
//-------------------------- player 2 shadow
player2_shadow = world.CreateBody(new tainicom.Aether.Physics2D.Common.Vector2(50, 50), 0, BodyType.Kinematic);
var player2_shadow_fixure = player2_shadow.CreateCircle(5, 10f);
player2_shadow_fixure .Restitution = 0;
player2_shadow_fixure.CollisionCategories = Category.Cat2;
world.Add(new tainicom.Aether.Physics2D.Dynamics.Joints.WeldJoint(player2, player2_shadow,
tainicom.Aether.Physics2D.Common.Vector2.Zero, tainicom.Aether.Physics2D.Common.Vector2.Zero)
{ CollideConnected = false });
//-------------------------- static ground
ground = world.CreateBody(new tainicom.Aether.Physics2D.Common.Vector2(50, 5), 0, BodyType.Static);
var gfixture = ground.CreateRectangle(100, 10, 1f, tainicom.Aether.Physics2D.Common.Vector2.Zero);
gfixture.Restitution = 0f;
gfixture.Friction = 1f;
gfixture.CollisionCategories = Category.Cat2;
}
// Update is called once per frame
void Update()
{
tainicom.Aether.Physics2D.Common.Vector2 vel = new tainicom.Aether.Physics2D.Common.Vector2(0, 0);
if (Input.GetKeyDown(KeyCode.UpArrow))
{
vel += new tainicom.Aether.Physics2D.Common.Vector2(0, 1);
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
vel += new tainicom.Aether.Physics2D.Common.Vector2(0, -1);
}
if (Input.GetKeyDown(KeyCode.RightArrow))
{
vel += new tainicom.Aether.Physics2D.Common.Vector2(1, 0);
}
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
vel += new tainicom.Aether.Physics2D.Common.Vector2(-1, 0);
}
if (Input.GetKeyDown(KeyCode.Space))
{
player1.Position = new tainicom.Aether.Physics2D.Common.Vector2(30, 90);
}
player1.ApplyLinearImpulse (vel * 200);
//force and linear velocity checked too
world.Step(Time.deltaTime);
player1_sprite.transform.position = new UnityEngine.Vector3(player1.Position.X, 0, player1.Position.Y);
player2_sprite.transform.position = new UnityEngine.Vector3(player2.Position.X, 0, player2.Position.Y);
player1k_sprite.transform.position = new UnityEngine.Vector3(player1_shadow .Position.X, 0, player1_shadow.Position.Y);
player2k_sprite.transform.position = new UnityEngine.Vector3(player2_shadow .Position.X, 0, player2_shadow.Position.Y);
ground_sprite.transform.position = new UnityEngine.Vector3(ground.Position.X, 0, ground.Position.Y);
}
if i delete weld joint and correct update code so set shadow body position equal to it's parent, again not success they push each other because before shadow follow the parent we call step function and dynamic collide each other but they are in mask group so nothing happen but in next step shadow bodies move then they push dynamics.
player1.LinearVelocity= (vel * 200);
world.Step(Time.deltaTime);
player1_shadow.Position = player1.Position;
player2_shadow.Position = player2.Position;
b2ShapeCast
function since 2.4.0, and its output includes the collision point and normal. But of course, for circles it's easy enough to compute this analytically. A collision between a swept circle and a stationary one (or equivalently, two swept circles, as viewed in the inertial frame of one of them) is equivalent to a ray intersection with a circle having the sum of their radii. So you might find it easier to just write your own swept check \$\endgroup\$