Networked Character Controller Issue (v2)

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
MCJOHNS117
Posts: 4
Joined: Tue Apr 28, 2020 8:51 pm

Networked Character Controller Issue (v2)

Post by MCJOHNS117 » Tue Apr 28, 2020 9:37 pm

I have taken a look at the thread regarding Character Controllers in v2, and it helped me tremendously in getting mine setup, so thank you Norbo and everyone else for that.

My issue is pretty unique, and I am not sure how to replicate it. I copied verbatim the code from the following demo files:
-CharacterController.cs
-CharacterNarrowphaseCallback.cs
-CharacterMotionConstraint.cs
-DemoPoseIntegrator.cs
-SimpleThreadDispatcher.cs

I am creating my character in the same order and with the same values as the demo:

Code: Select all

var shape = new Capsule(0.5f, 1);

((BEPUPhysics)player.Physics).ShapeIndex = CharacterControllers.Simulation.Shapes.Add(shape);
((BEPUPhysics)player.Physics).CharacterControllers = CharacterControllers;
int bodyHandle = ((BEPUPhysics)player.Physics).BodyHandle = CharacterControllers
	.Simulation.Bodies.Add
	(
		BodyDescription.CreateDynamic
		(
			new Vector3(obj.Position.X, obj.Position.Y, obj.Position.Z), 
			new BodyInertia { InverseMass = 1f / MASS },
			new CollidableDescription(((BEPUPhysics)player.Physics).ShapeIndex, SPECULATIVE_MARGIN),
			new BodyActivityDescription(shape.Radius * 0.02f)
		)
	);
ref var character = ref CharacterControllers.AllocateCharacter(bodyHandle);
character.LocalUp = new Vector3(0, 1, 0);
character.CosMaximumSlope = (float)Math.Cos(MAXIMUM_SLOPE);
character.JumpVelocity = JUMP_VELOCITY;
character.MaximumVerticalForce = MAXIMUM_VERTICAL_GLUE_FORCE;
character.MaximumHorizontalForce = MAXIMUM_HORIZONTAL_FORCE;
character.MinimumSupportDepth = shape.Radius * -0.01f;
character.MinimumSupportContinuationDepth = -SPECULATIVE_MARGIN;
The simulation is setup the same as the demos:

Code: Select all

BufferPool = new BufferPool();
ThreadDispatcher = new SimpleThreadDispatcher(Environment.ProcessorCount);
CharacterControllers = new CharacterControllers(BufferPool);
Simulation = Simulation.Create(BufferPool, new CharacterNarrowphaseCallbacks(CharacterControllers), new PoseIntegratorCallbacks(new Vector3(0.0f, -10f, 0.0f)));
The issue comes when running the server. It appears that the CharacterControllers.TryReportContacts ethod is not being called, as my character does not move (confirmed that messages to/from the server are being seen, with the correct values going in and no changes coming out.)

BUT where it get really weird is if I attach the visual studio debugger to my server process and put a breakpoint in the TryReportContacts method everything starts to work! My client can move, the breakpoint is being hit, everything seems to be running fine.

If I leave the server running, disconnect the client, remove the breakpoint, and login with the client again...nothing. No movement.

I have no idea where to begin with this one. Please help! :lol:

Norbo
Site Admin
Posts: 4884
Joined: Tue Jul 04, 2006 4:45 am

Re: Networked Character Controller Issue (v2)

Post by Norbo » Tue Apr 28, 2020 10:09 pm

Given that it works with the debugger attached, it's almost certainly not going to be physics-related misconfiguration. Hard to say what it is- standard recommendation would be to add more reporting and progressively simplify so you can narrow down where it might be coming from.

MCJOHNS117
Posts: 4
Joined: Tue Apr 28, 2020 8:51 pm

Re: Networked Character Controller Issue (v2)

Post by MCJOHNS117 » Fri May 01, 2020 1:38 am

A bit of an update on this.

It appears that when I swapped v1 for v2 somehow I didnt update the position being sent to the client. Once this was solved, everything worked as it should.

The issue with seeing my character move while debugging was interesting though. It turns out that when the breakpoint hit in the physics thread, the character was not being updated. So the client side movement was working as intended, without any updates from the server. If I had had more than one client logged in I may have noticed the issue.

Either way, everything is working perfectly now, and I am moving on to integrating my terrain generation to the server side. I am taking a queue from your deformed plane creator in the DemoMeshHelper class. On that note, is there any limitation to the size of those meshes? For instance, if I wanted a map of size 16km^2, broken into areas 128m^2, given enough memory, are there any other issues I might come across?

Norbo
Site Admin
Posts: 4884
Joined: Tue Jul 04, 2006 4:45 am

Re: Networked Character Controller Issue (v2)

Post by Norbo » Fri May 01, 2020 1:59 am

Should work fine, with two potential minor issues:
1) At the border between meshes, contacts will not be corrected to match the continuous surface. That can cause bumps for sliding or rolling objects when the normals point sideways. More information in this thread: viewtopic.php?f=4&t=2689
2) 32 bit floats can have insufficient precision for positions far from the origin. If your game was operating at scales of ~1 unit or so for most objects, then you can probably use anything within 5000-10000 units of the origin. 16km^2 laid out as a 4km x 4km square centered on the origin should be totally fine.

MCJOHNS117
Posts: 4
Joined: Tue Apr 28, 2020 8:51 pm

Re: Networked Character Controller Issue (v2)

Post by MCJOHNS117 » Fri May 01, 2020 5:35 am

Norbo wrote:
Fri May 01, 2020 1:59 am
1) At the border between meshes, contacts will not be corrected to match the continuous surface. That can cause bumps for sliding or rolling objects when the normals point sideways. More information in this thread: viewtopic.php?f=4&t=2689
I will take a look at this, I am sure it will apply.
Norbo wrote:
Fri May 01, 2020 1:59 am
2) 32 bit floats can have insufficient precision for positions far from the origin. If your game was operating at scales of ~1 unit or so for most objects, then you can probably use anything within 5000-10000 units of the origin. 16km^2 laid out as a 4km x 4km square centered on the origin should be totally fine.
This is one thing I am thinking about. I know in single player games they adjust the game world to always be centered on the player, but that doesnt really help a multiplayer situation. As they say, I will cross that bridge when I get to it. :lol:

I am using the RigidPose.Position to send back to the client, however I am having trouble determining when to access it. I tried calling it in the same lock as the Simulation.Timestep, but was getting access violation errors. I suppose this is due to the physics having internal threading. Is there a safe way to access the character controllers position?

Norbo
Site Admin
Posts: 4884
Joined: Tue Jul 04, 2006 4:45 am

Re: Networked Character Controller Issue (v2)

Post by Norbo » Fri May 01, 2020 4:45 pm

So long as the body data isn't being modified externally or an executing timestep, it's safe to access. No engine threads continue to run outside of the timestep.

You may be able to catch the problem earlier than an access violation if you run the library in debug configuration so that all the asserts are active.

MCJOHNS117
Posts: 4
Joined: Tue Apr 28, 2020 8:51 pm

Re: Networked Character Controller Issue (v2)

Post by MCJOHNS117 » Sat May 02, 2020 12:49 am

Code: Select all

2020-05-01 20:39:58,618 [11] ERROR Photon.SocketServer.ApplicationBase [(null)] - System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at BepuPhysics.Trees.Tree.RefitAndRefineMultithreadedContext.RefitAndRefine(Tree& tree, BufferPool pool, IThreadDispatcher threadDispatcher, Int32 frameIndex, Single refineAggressivenessScale, Single cacheOptimizeAggressivenessScale)
   at BepuPhysics.CollisionDetection.BroadPhase.Update(IThreadDispatcher threadDispatcher)
   at BepuPhysics.Simulation.CollisionDetection(Single dt, IThreadDispatcher threadDispatcher)
   at BepuPhysics.PositionLastTimestepper.Timestep(Simulation simulation, Single dt, IThreadDispatcher threadDispatcher)
   at BepuPhysics.Simulation.Timestep(Single dt, IThreadDispatcher threadDispatcher)
   at RegionServer.BackgroundThreads.PhysicsBackgroundThread.Update(TimeSpan elapsed) in PhysicsBackgroundThread.cs:line 286
   at RegionServer.BackgroundThreads.PhysicsBackgroundThread.Run(Object threadContext) in PhysicsBackgroundThread.cs:line 280
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
Line 286 of RegionServer.BackgroundThreads.PhysicsBackgroundThread.Update(TimeSpan elapsed) is:

Code: Select all

Simulation.Timestep(_physicsTimestep, ThreadDispatcher);
Immediately after that I am updating the physics position to send back to the client:

Code: Select all

Parallel.ForEach(Region.AllPlayers.Values.Where(instance => instance is CPlayerInstance).Cast<CPlayerInstance>(), (CPlayerInstance instance) => 
{
	((BEPUPhysics)instance.Physics).SetPosition(new BodyReference(((BEPUPhysics)instance.Physics).BodyHandle, 		 
        ((BEPUPhysics)instance.Physics).CharacterControllers.Simulation.Bodies).Pose.Position);
});
I am sure this is something on my end, but I fear I may be in over my head here. I appreciate the time you have already spent on this Norbo.

Norbo
Site Admin
Posts: 4884
Joined: Tue Jul 04, 2006 4:45 am

Re: Networked Character Controller Issue (v2)

Post by Norbo » Sat May 02, 2020 5:54 pm

Running with debug asserts active in the library would provide more information, but it looks like some state has gotten corrupted in the broad phase. Incorrectly timed asynchronous reads can get torn/trash data, possibly even an access violation at the time of the read if you get very unlucky, but a readonly operation by itself can't corrupt the internal state of the engine. Either something is writing to the engine's state when it shouldn't, or something about the simulation's configuration is busted. Hard to say what is happening in any more detail.

Grabbing the latest source off github and running in debug mode might reveal something.

Post Reply