[SOLVED] Port to Unity3D - Some Issues and Questions

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
BrightBit
Posts: 21
Joined: Fri Jul 08, 2016 12:11 pm

[SOLVED] Port to Unity3D - Some Issues and Questions

Post by BrightBit »

I've compiled BEPUphysics v1.4.0 with Visual Studio Community 2015 for a use in Unity 3D 5.3.5f1. Therefor I changed the build settings of the projects BEPUphysics and BEPUutilities to use the target framework "Unity 3.5 .net Subset Base Class Libraries" and removed the conditional compilation symbol "WINDOWS" from the BEPUutilities project. Finally I changed the code in ParallelLoopWorker.cs (line 84) from "getToWork.Dispose();" to "getToWork.Close();".

I now even managed to create a small demo scene with two boxes, a rotating fan blade on a cylinder as in one of BEPU Physics' original demos and a working character controller. This made me feel euphoric. I really love the idea of having a dynamic character controller in Unity. :)

However, I noticed several things during my way of integrating BEPU Physics:
  1. The camera smoothing code in CharacterCameraControlScheme doesn't seem to work in Unity. The line "Character.Body.BufferedStates.InterpolatedStates.Position;" always returns the same position although the controller body is moving and BufferedStates.Enabled of my only space instance is set to TRUE. Am I doing something wrong?
  2. In contrast to PhysX the creation of a static mesh in BEPU Physics doesn't require normals or uv coordinates. How can I still retrieve them if I'm in need of those information during raycasts or collisions?
  3. Did someone test the character controller on curly stairs? That's something most other controllers (e.g. UFPS) that I've tested in Unity failed to solve properly. My first tests with BEPU Physics' controller on curly stairs seem promising but are still not good enough (some jitters but it might get better with camera smoothing).
Now, I just want to add that I really like this physics library so far! :) Did you (@Norbo) write this engine all by yourself?


Kind regards
BrightBit

Edit: Are there some statistics about how fast BEPU Physics is in creating and updating its collision data in comparison to other libraries? PhysX for example seems to be slow when it comes to procedurally generated meshes.
Last edited by BrightBit on Tue Jul 19, 2016 4:56 pm, edited 1 time in total.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Port to Unity3D - Some Issues and Questions

Post by Norbo »

The camera smoothing code in CharacterCameraControlScheme doesn't seem to work in Unity. The line "Character.Body.BufferedStates.InterpolatedStates.Position;" always returns the same position although the controller body is moving and BufferedStates.Enabled of my only space instance is set to TRUE. Am I doing something wrong?
Interpolated states are one step beyond buffered states. They require that both the Space.BufferedStates.Enabled = true and Space.InterpolatedStates.Enabled = true. (Also, I don't remember the last time I actually tested the CharacterCameraControlScheme under variable update rates since it's just a little demo feature. It's possible there's a goof in there somewhere.)

(Future compatibility note: BEPUphysics v2.0 won't have buffered or interpolated state stuff built into the engine itself. Fixed time stepping and these buffering systems aren't doing anything special or 'physicsy', so it's easy to do all of it externally. I might still have an external layer or demo showing how to do it (it is pretty easy after all), but it's something to keep in mind.)
In contrast to PhysX the creation of a static mesh in BEPU Physics doesn't require normals or uv coordinates. How can I still retrieve them if I'm in need of those information during raycasts or collisions?
Authored normals and UVs require a lookup. The Space.RayCast returns the object associated with an impact. If you happen to have an object where you can look up this extra metadata by, say, position, that would be sufficient.

If you want something like the impacted triangle index, you'll probably want to bypass the Space.RayCast. Use the Space.BroadPhase.QueryAccelerator.RayCast to collect the BroadPhaseEntry objects with AABBs intersected by your ray. This function won't attempt to do any kind of detailed per object test beyond the AABB test, so it lets you deal with individual objects in a customizable way.

If a BroadPhaseEntry is a StaticMesh, you could use the StaticMesh.Mesh.Tree.GetOverlaps function to collect potential triangle impacts by triangle index. You can test individual triangle indices using the Toolbox.FindRayTriangleIntersection, or do whatever other tests you want. An example of this kind of function is the TriangleMesh.RayCast (though it only concerns itself with the geometric hit data).

You could also redo the ray cast on the specific BroadPhaseEntry returned by a Space.RayCast to collect detailed information to avoid dealing with the broad phase query directly, but that would do a little redundant work. That redundant work may or may not matter.

(Future compatibility note: BEPUphysics v2.0 will be changing a lot of this massively. It should actually get easier to directly access this kind of information, but... it definitely won't be the same.)
Did someone test the character controller on curly stairs? That's something most other controllers (e.g. UFPS) that I've tested in Unity failed to solve properly. My first tests with BEPU Physics' controller on curly stairs seem promising but are still not good enough (some jitters but it might get better with camera smoothing).
I tested it on a whole lot of horribly annoying cases and don't know of any outright failures under optimal configuration, but there is a great deal of complexity involved so it's hard to say. Innocent seeming configuration choices can wreak havoc with stability. If you can reproduce the behavior in a modified BEPUphysicsDemos demo I could take a closer look.

The systems most likely to choke would probably be upstepping or downstepping. Note that some games don't actually need stepping and can get away with a character with a rounded bottom that can ride over reasonably sized obstacles and stairs. The teleportation-based stepping is really mainly useful for Quake/TF2-type games where people fly up and down huge stairs at 40 miles an hour.
Now, I just want to add that I really like this physics library so far! :) Did you (@Norbo) write this engine all by yourself?
Yup, glad you like it :)
Edit: Are there some statistics about how fast BEPU Physics is in creating and updating its collision data in comparison to other libraries? PhysX for example seems to be slow when it comes to procedurally generated meshes.
I don't know of any benchmarks out there about that specifically. BEPUphysics v1.4 and before have certainly been used in dynamic mesh cases (minecraftish games come to mind), though it does require some effort. For example, you definitely will want to use some kind of non-blocking approach for creating and modifying any large mesh acceleration structures. Even with a hypothetical perfect system, updating the structure of 100,000 triangle mesh is probably going to take long enough to avoid stalling your main thread with it. I'm also not happy with how hard it is to avoid allocations when redoing hierarchies in v1.4.

That said, the first bits of v2.0 already have some pretty big advantages in this regard. The new tree that will replace both the current broad phase and the other per-object hierarchies is already working, and it's a lot faster in every way: http://www.bepuphysics.com/blog/2015/9/ ... trees.html

(Now I just need to finish the rest of it!)
BrightBit
Posts: 21
Joined: Fri Jul 08, 2016 12:11 pm

Re: Port to Unity3D - Some Issues and Questions

Post by BrightBit »

Thank you for your fast answers! :)

Now, I wrote in my code space.BufferedStates.Enabled = true and space.BufferedStates.InterpolatedStates.Enabled = true but it still didn't work. So maybe there really is a small problem although I have to be honest: I don't even know yet what these buffered states are actually doing.
Norbo wrote: If you want something like the impacted triangle index, you'll probably want to bypass the Space.RayCast. Use the Space.BroadPhase.QueryAccelerator.RayCast to collect the BroadPhaseEntry objects with AABBs intersected by your ray. This function won't attempt to do any kind of detailed per object test beyond the AABB test, so it lets you deal with individual objects in a customizable way.

If a BroadPhaseEntry is a StaticMesh, you could use the StaticMesh.Mesh.Tree.GetOverlaps function to collect potential triangle impacts by triangle index. You can test individual triangle indices using the Toolbox.FindRayTriangleIntersection, or do whatever other tests you want. An example of this kind of function is the TriangleMesh.RayCast (though it only concerns itself with the geometric hit data).
Those options would fit my need, I guess, but I'm not sure if I shouldn't just wait for BEPUphysics v2.0 then. But what do you mean by "It should actually get easier to directly access this kind of information, but... it definitely won't be the same." I will be able to get these information but the overall API of BEPUphysics will change dramatically (in comparison to v1.0)?
Norbo wrote: If you can reproduce the behavior in a modified BEPUphysicsDemos demo I could take a closer look.
I really would like to use this offer. However, I already tried something like this but I had troubles exporting my model to the xnb file format. Could you also try to reproduce the behaviour when I supply to you the model file (in OBJ?) in conjunction with the parameters I've used for the Character Controller?
Norbo wrote: The systems most likely to choke would probably be upstepping or downstepping. Note that some games don't actually need stepping and can get away with a character with a rounded bottom that can ride over reasonably sized obstacles and stairs. The teleportation-based stepping is really mainly useful for Quake/TF2-type games where people fly up and down huge stairs at 40 miles an hour.
Okay, I might look into what happens when I disable the teleportation-based stepping.
Norbo wrote: Even with a hypothetical perfect system, updating the structure of 100,000 triangle mesh is probably going to take long enough to avoid stalling your main thread with it.
Don't you mean "take long enough to stall your main thread"? By the way, no pressure intended but is there an estimate for when you might be able to release v2.0? :)

PS: Somewhere I read that you use BEPUphysics in a game that you are currently working on. Can you supply some links to it? I'm curious to see it. :)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Port to Unity3D - Some Issues and Questions

Post by Norbo »

Now, I wrote in my code space.BufferedStates.Enabled = true and space.BufferedStates.InterpolatedStates.Enabled = true but it still didn't work. So maybe there really is a small problem although I have to be honest: I don't even know yet what these buffered states are actually doing.
Assuming there's not a bug in the CharacterCameraControlScheme itself, the interpolated states also require that the Space is being updated with the Space.Update(dt) overload. Passing in an elapsed time makes the engine take a variable number of fixed-length simulation steps to keep up with the accumulated time. Since the simulation takes fixed-length steps, there will be left over time. That left over time is used to interpolate between the last two computed states for dynamic objects, and that's what InterpolatedStates handles.
But what do you mean by "It should actually get easier to directly access this kind of information, but... it definitely won't be the same." I will be able to get these information but the overall API of BEPUphysics will change dramatically (in comparison to v1.0)?
The difference between v1.4.0 and v2.0.0 can be thought of as roughly as big as the difference between v1.4.0 and... a different rigid body physics engine. Mainly because it is pretty much a ground-up rewrite. That might not be as bad as it sounds, though- rigid body physics engines are pretty similar. It's not hard to write an abstraction layer that mostly hides the details once you know the common bits.

As for how it will be different, expect a lot less API-level 'automation' (e.g. probably no more automatic ShapeChanged events propagating through a complicated and fragile web of handlers), a flatter and minimalist API, and direct access whenever useful and possible. Minimizing overhead and maximizing performance are the main reasons for the rewrite.
Could you also try to reproduce the behaviour when I supply to you the model file (in OBJ?) in conjunction with the parameters I've used for the Character Controller?
Sometimes these issues are very tricky to reproduce, but I can give it a shot. OBJ or FBX should work.
Okay, I might look into what happens when I disable the teleportation-based stepping.
For reference, to do this, comment out this block in the CharacterController:

Code: Select all

                if (StepManager.TryToStepDown(out newPosition) ||
                    StepManager.TryToStepUp(out newPosition))
                {
                    supportData = TeleportToPosition(newPosition, dt);
                }
Don't you mean "take long enough to stall your main thread"?
It would take long enough to noticeably stall the thread, yes- a clearer original wording would have been "take long enough to justify avoiding the stall on your main thread"
I'm not sure if I shouldn't just wait for BEPUphysics v2.0 then. [...] By the way, no pressure intended but is there an estimate for when you might be able to release v2.0?
I'm not going to be working full time on v2.0 until 2-3 months from now. And regarding when v2.0 will be completed, I have proven terrifically bad at predicting BEPUphysics timelines. I don't want it to take longer than about 4-6 months from starting to get the core bits down, but a desired timeline is a long way from an actual timeline.

For reference, that tree I mentioned earlier took about 2 months to complete. Notably, one of the earliest predictions I made about its timeline was 12 days. I did later increase that estimate before beginning... to 1 month.
PS: Somewhere I read that you use BEPUphysics in a game that you are currently working on. Can you supply some links to it? I'm curious to see it.
No public info yet since it's still mostly-stealthmode, but I am slowly collecting a mass of potential dev blog material for when it reaches a point where I'm comfortable with talking about it in more depth. (Topics perhaps including "WHY DID THE SKY DISAPPEAR I DIDNT CHANGE ANYTHING: One of many adventures in early D3D12 development")

I will say that, unsurprisingly, it's pretty darn heavy on physics. BEPUphysics v2 is almost entirely driven by the many-faceted inadequacy of v1.4.0 for the game's use case.
BrightBit
Posts: 21
Joined: Fri Jul 08, 2016 12:11 pm

Re: Port to Unity3D - Some Issues and Questions

Post by BrightBit »

I found the mistake that lead to the missing interpolation. It was code from the original unity fork of BEPU that tricked me into believing that Space.Update(dt) was used where instead Space.Update() was called all the time. Sorry. :oops: While searching for this "bug" I at least finally understood the interpolated states and the buffered states.

To come back to the curly stairs climbing issue: I've attached an Stairs.txt file to this post (I had to rename it since *.obj isn't allowed). The file combines two stairs in one model. The important one has modeled steps whereas the other one is more like a slide. These are the parameters that I've used for the CharacterController:

Code: Select all

StandingCameraOffset  = 0.7f;
CrouchingCameraOffset = 0.4f;
ProneCameraOffset     = 0.1f;

new CharacterController(somePosition,
        1.7f, // height
        1.7f * .7f,  // crouchingHeight
        1.7f * 0.3f, // proneHeight
        0.3f, // radius
        0.1f, // margin
        10f, // mass
        0.8f, // maximumTractionSlope
        1.3f, // maximumSupportSlope
        1f, // standingSpeed
        3f, // crouchingSpeed
        1.5f, // proneSpeed
        1000, // tractionForce
        6, // slidingSpeed
        50, // slidingForce
        1, // airSpeed
        250, // airForce
        4.5f, // jumpSpeed
        3, // slidingJumpSpeed
        5000); // maximumGlueForce
As far as I can remember, the radius and the standingSpeed should be the only parameters that differ from the default ones but I listed them all to be sure.

A question along the way: I read some of your blog entries and in one of them you wrote "Expect older platforms like Xbox360 and WP7 to be abandoned.". Now I'm curious if BEPU Physics v2.0 will even work with Unity. Will the compilation of BEPU Physics v2.0 be supported as the compilation of the current version is supported now? As described here: viewtopic.php?f=9&t=2322

Last but not least, I like to say that I tried to measure the performance of PhysX and BEPU Physics for creating and updating collision data. Therefor I created a small test scenario for each library where every three seconds the y-coordinates of each vertex in a static mesh, a grid with 256x256 vertices, was randomly changed. I ran 100 samples for each library and calculated the slowest time it took, the fastest time and the average time. Here are the results for a computer with an Intel Core i5 CPU M450 @2.40 GHz, 4 GB Ram and Windows 7 64 Bit:

BEPU:
  • Slowest : 1.1829581 seconds
    Fastest : 1.0335033 seconds
    Average : 1.0832482 seconds
PhysX:
  • Slowest : 1.0499889 seconds
    Fastest : 0.9903418 seconds
    Average : 1.0118106 seconds
Here are some code excerpts in case you or someone else is interested in the details:

Test case for BEPU Physics:

Code: Select all

void Start()
{
    List<BEPUutilities.Vector3> vertices = new List<BEPUutilities.Vector3>();

    for (int y = 0; y < gridSize; ++y)
        for (int x = 0; x < gridSize; ++x)
            vertices.Add(new BEPUutilities.Vector3(2 * x, 0, 2 * y));

    List<int> triangles = new List<int>();

    for (int y = 0; y < gridSize - 1; ++y)
        for (int x = 0; x < gridSize - 1; ++x)
        {
            triangles.Add(gridSize * (y)     + (x));
            triangles.Add(gridSize * (y)     + (x + 1));
            triangles.Add(gridSize * (y + 1) + (x + 1));

            triangles.Add(gridSize * (y)     + (x));
            triangles.Add(gridSize * (y + 1) + (x + 1));
            triangles.Add(gridSize * (y + 1) + (x));
        }

    physicsMesh = new BEPUphysics.BroadPhaseEntries.StaticMesh(vertices.ToArray(), triangles.ToArray(), this.transform.ToBEPU());
    physicsMesh.Sidedness = BEPUutilities.TriangleSidedness.DoubleSided;

    PhysicsSpaceManager.Space.Add(physicsMesh);
}

void Update()
{
    test += Time.deltaTime;

    if (test > 3.0f && counter < 100)
    {
        test = 0.0f;
        counter += 1;

        for (int i = 0; i < physicsMesh.Mesh.Data.Vertices.Length; ++i)  physicsMesh.Mesh.Data.Vertices[i].Y = Random.Range(0.0f, 2.0f);

        Stopwatch sw = new Stopwatch();
        sw.Start();

        physicsMesh.Mesh.Tree.Reconstruct();
        physicsMesh.UpdateBoundingBox();

        sw.Stop();
        System.TimeSpan current = sw.Elapsed;

        if (current < lowest)  lowest = current;
        if (current > highest) highest = current;

        values.Add(current);
    }
    else if (!done && counter == 100)
    {
        done = true;

        UnityEngine.Debug.Log(highest);
        UnityEngine.Debug.Log(lowest);
        UnityEngine.Debug.Log(GetAverage());
    }
}
Test case for PhysX:

Code: Select all

void Start()
{
    mesh = new Mesh();

    List<Vector3> vertices = new List<Vector3>();

    for (int y = 0; y < gridSize; ++y)
        for (int x = 0; x < gridSize; ++x)
            vertices.Add(new Vector3(2 * x, 0, 2 * y));

    List<int> triangles = new List<int>();

    for (int y = 0; y < gridSize - 1; ++y)
        for (int x = 0; x < gridSize - 1; ++x)
        {
            triangles.Add(gridSize * (y)     + (x));
            triangles.Add(gridSize * (y)     + (x + 1));
            triangles.Add(gridSize * (y + 1) + (x + 1));

            triangles.Add(gridSize * (y)     + (x));
            triangles.Add(gridSize * (y + 1) + (x + 1));
            triangles.Add(gridSize * (y + 1) + (x));
        }

    UpdateMesh(vertices.ToArray(), triangles.ToArray());

    meshCollider.sharedMesh = mesh;
}

void UpdateMesh(Vector3[] vertices, int[] triangles)
{
    mesh.MarkDynamic();
    mesh.Clear();
    mesh.name      = "Test";
    mesh.vertices  = vertices;
    mesh.triangles = triangles;
}

void Update()
{
    test += Time.deltaTime;

    if (test > 3.0f && counter < 100)
    {
        test = 0.0f;
        counter += 1;

        Vector3[] vertices = mesh.vertices;
        int[] triangles    = mesh.triangles;

        for (int i = 0; i < vertices.Length; ++i) vertices[i] = new Vector3(vertices[i].x, Random.Range(0.0f, 2.0f), vertices[i].z);

        UpdateMesh(vertices, triangles);

        Stopwatch sw = new Stopwatch();
        sw.Start();

        meshCollider.sharedMesh = null;
        meshCollider.sharedMesh = mesh;
        
        sw.Stop();
        System.TimeSpan current = sw.Elapsed;

        if (current < lowest)  lowest = current;
        if (current > highest) highest = current;

        values.Add(current);
    }
    else if (!done && counter == 100)
    {
        done = true;

        UnityEngine.Debug.Log(highest);
        UnityEngine.Debug.Log(lowest);
        UnityEngine.Debug.Log(GetAverage());
    }
}
Thanks in heaps for your patience and for helping me evaluate your engine.

PS: I experimentally removed the teleportation code but then I wasn't even able to take the first step of the stair.
Attachments
Stairs.txt
The file contains two stairs that are combined as one mesh. One stair has modeled steps whereas the other one is more like a slide. Note: You might need to change the filename extension back to *.obj!
(39.86 KiB) Downloaded 290 times
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Port to Unity3D - Some Issues and Questions

Post by Norbo »

A question along the way: I read some of your blog entries and in one of them you wrote "Expect older platforms like Xbox360 and WP7 to be abandoned.". Now I'm curious if BEPU Physics v2.0 will even work with Unity. Will the compilation of BEPU Physics v2.0 be supported as the compilation of the current version is supported now? As described here: viewtopic.php?f=9&t=2322
It's hard to say exactly.

The rule of thumb would be: if it can handle .NET Core, unsafe code, and the latest version of C#, it should handle v2.0. For reference, I'll probably be targeting the C# 7 preview (ref locals and returns are really nice to have). Unfortunately, it will be far more difficult to 'turn off' some of the incompatible features.

The bad news is older versions of Unity will probably have a lot of problems with it. I don't think webplayer stuff using 2.0 will be feasible due to unsafe code. Note that I'm not very familiar with where Unity stands, so this is partly speculation.

The good news is that Unity has been putting forward effort to escape the legacy issues surrounding the old mono runtimes and platform. I'm pretty hopeful for the future because:
1) .NET Core and the associated technology stack is FOSS,
2) Microsoft bought Xamarin and already had a pretty good relationship with Unity,
3) Unity was already working on IL2CPP as a means of addressing some of the platform problems, and
4) Unity joined the .NET foundation:
Yes we plan to support .NET 4.6 and continue improving support as .NET evolves in the future.
I would be very surprised if Unity has any problem with BEPUphysics v2.0 in the mid-long term. It's just a question of time.
Last but not least, I like to say that I tried to measure the performance of PhysX and BEPU Physics for creating and updating collision data.
By the way, for modifications to a mesh that do not involve topology changes (that is, no added or removed elements, and no element movements such that the form of the tree becomes terrible), you can use Refit instead of Reconstruct. It's way faster. On my computer (3770K@4.5ghz):

Code: Select all

v1.4.0 Reconstruct:
Average: 0.177805882915706
Fastest: 0.156391210178821
Slowest: 0.204268637878478

v1.4.0 Refit:
Average: 0.0266572225445356
Fastest: 0.0260292644907152
Slowest: 0.0273815176657454
Out of curiosity I went ahead and compared this case to the v2.0 tree. (I needed to get away from the mess of driver bugs on the graphics engine for a while anyway!)

Code: Select all

v2 Reconstruct Incremental:
Average: 0.108381626208785
Fastest: 0.105335314609513
Slowest: 0.120236430730378
Cost Metric: 42.10615

v2 Reconstruct Sweep:
Average: 0.258328756093843
Fastest: 0.252644895449062
Slowest: 0.285086683758538
Cost Metric: 25.12667

v2 Refit And Refine:
Average: 0.00335068266550107
Fastest: 0.00323025255419911
Slowest: 0.00376038729092665
Cost Metric: 25.12862

v2 Refit:
Average: 0.000971802507841576
Fastest: 0.000873025416332772
Slowest: 0.00129461711369722
Cost Metric: 25.12862
The first chunk, "Reconstruct Incremental", is doing a construction process very similar to what v1.4.0's Reconstruct did. It just inserts triangles one at a time. You'll also notice a "Cost Metric", which is a rough measure of how expensive a query is. Lower is better. v1.4.0's Reconstruct should have a similar or slightly higher cost- I just didn't bother going back and adding in a measurement for it.

"Reconstruct Sweep" is one of the new tree's features. It is a heavyweight, high quality builder designed mainly for offline or load-time use. It's here as a reference- and to note that it isn't much slower than v1.4.0's much, much lower quality Reconstruct.

"Refit and Refine" is by far the most interesting of the new features. Despite taking only about 3 milliseconds, it gradually improves the tree, both in terms of its Cost Metric (up to a limit- it's based on local sweep rebuilds, so it can't do better than a global sweep build) and in terms of the cache efficiency of its layout in memory. So while the above refinement started from a high quality sweep build, it can also take low quality builds and make them much better over time. This is extremely important for the broad phase use case and in any other dynamic hierarchy where you expect lots of topological changes over time. This system can handle adds and removes of leaves without any problem. Notably, this test was run on one thread, but there's a multithreaded overload that gives near linear speedups (as shown in the blog post).

"Refit" is just the same as v1.4.0's refit, except... >27x faster. Less than a millisecond for all 130,050 triangles. The cost metric turns out pretty good here just because it was initialized with the high quality sweep build and randomizing the y position a little doesn't change much.

I added the benchmark to the scratchpad repo: https://github.com/RossNordby/scratchpa ... nceTest.cs
PS: I experimentally removed the teleportation code but then I wasn't even able to take the first step of the stair.
The ability for the cylindrical character to walk up steps depends strongly on how 'round' it is. You can think about the character as a 'core' cylinder expanded by a sphere of margin radius across its entire surface, so that edges aren't perfectly sharp. For example:
cylindercore.jpg
cylindercore.jpg (10.71 KiB) Viewed 8964 times
Using 0.1 as the margin means it can only climb stair-like obstacles less than 0.1 units tall, assuming a maximum traction slope of pi/2. With a maximum traction slope of 0.8, it would be closer to a maximum of 0.05 units. If units are meters, that's only about 2 inches. The standard height of a stair in the US is 7 inches, so without increasing the allowed slope of about 0.8, it would require a margin of around 0.35 to 0.4.

Note that the margin can't be bigger than the radius, though- the margin is internal. So the character radius would need to be increased to equal or exceed the margin. If the margin equals the radius, the 'cylinder' is really a capsule.

If the environment is highly realistic with reasonably sized stairs, this can work out okay. Another common option is to design the environment with this kind of character in mind- so 'stairs' would be a detailed graphical model over a physical ramp. Ramps will tend to be faster too- less triangles to collide with.

For my own game, I turn off the stepping queries for performance and networking reasons (stepping is not super slow, but when there are many thousands of characters on a single server, every bit helps). I use a big margin to let them climb stuff as above, but I also increase the maximum traction slope to increase the stair-climbing power even more. This has the effect of also letting characters walk up very steep hills, but I made it slower while climbing steep slopes, and kept the threshold slope required to go from notraction->traction low- so if the character briefly slips on a cliff, they're going to fall. And of course, where I have control over the content, the physics representation tends to be simpler and more ramp-like.

I haven't quite gotten around to testing out the model- I'll probably get to that tomorrow.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Port to Unity3D - Some Issues and Questions

Post by Norbo »

I couldn't reproduce any unexpected behavior with stepping on that model with that character configuration. The default CharacterController.StepManager.MaximumStepHeight of 1 is probably way higher than is appropriate for this model, so sometimes it climbs multiple steps or the central pole itself, and then subtle movements can make it fall back down because it didn't have a very solid foothold... but that's pretty much what is supposed to happen given the configuration and model.

Reducing the maximum step height to 0.3 feels better overall since it doesn't try to climb the walls quite so much. It does have some trouble with climbing very close to the pole because teleportation based stepping involves teleporting the character both up and forward along the detected step direction. If the system can't find a valid location with traction, maybe because it's blocked by other geometry, it won't step up. The 'forward' component of the teleportation is proportional to the character's margin, so technically you could reduce the margin to get finer grained stepping, but you will sacrifice a degree of collision robustness if you go too low. The default for most shapes at the default scale is 0.04. (I would recommend keeping the margin large if possible, and modifying the geometry to give it more room to find a foothold.)

Also, if you weren't already, use the single sided Clockwise or Counterclockwise sidednesses as opposed to DoubleSided whenever possible. DoubleSided can make things more difficult, since it has to deal with the 'inner' side of all of the stairs too. And of course, make sure the appropriate winding order is used- clockwise on a counterclockwise-designed mesh will cause nasty issues.

At a higher level, I would recommend trying to design physics geometry to be kinder to the engine. Near the central support, it's just about the worst case for teleportation stepping- small movements can trigger huge vertical movement over extremely short timespans, and the multiple facets of collidable geometry in a small place make all calculations slower and more difficult. A slightly larger central support to reduce the extreme curvature exposed at the center would be helpful- a person would have trouble climbing that in real life. In addition, try to get rid of much unnecessary geometry as possible. If the central support was expanded to include the internal side of the stairs, no triangles would be needed there.

Incidentally, I tried disabling stepping and setting the margin to 0.3 with 1.555 traction slope, and it works pretty well at slow paces. Faster paces would tend to require a larger margin so that not so much momentum is lost when bumping into the stairs.
BrightBit
Posts: 21
Joined: Fri Jul 08, 2016 12:11 pm

Re: Port to Unity3D - Some Issues and Questions

Post by BrightBit »

Norbo wrote:1) .NET Core and the associated technology stack is FOSS,
2) Microsoft bought Xamarin and already had a pretty good relationship with Unity,
3) Unity was already working on IL2CPP as a means of addressing some of the platform problems, and
4) Unity joined the .NET foundation:
I would be very surprised if Unity has any problem with BEPUphysics v2.0 in the mid-long term. It's just a question of time.
You have some really good arguments there. :)
Norbo wrote:By the way, for modifications to a mesh that do not involve topology changes [...] you can use Refit instead of Reconstruct.
Good to know but for my current project I probably won't be able to use it. Whenever the geometry in my application changes, there will be topology changes, too.
Norbo wrote:"Refit and Refine" is by far the most interesting of the new features. Despite taking only about 3 milliseconds, it gradually improves the tree, both in terms of its Cost Metric (up to a limit- it's based on local sweep rebuilds, so it can't do better than a global sweep build) and in terms of the cache efficiency of its layout in memory. So while the above refinement started from a high quality sweep build, it can also take low quality builds and make them much better over time. This is extremely important for the broad phase use case and in any other dynamic hierarchy where you expect lots of topological changes over time. This system can handle adds and removes of leaves without any problem. Notably, this test was run on one thread, but there's a multithreaded overload that gives near linear speedups (as shown in the blog post).
That definitely sounds interesting! I would like to repeat that in my own words, just to check if I got the details right. Instead of calling Reconstruct() as I am doing now, I would be able to call something like RefitAndRefine(). This call would trigger some kind of reconstruction over time? So it spreads its work over several frames and can be used even for topology changes? Sorry, if I misunderstood that. My knowledge about physics engines and their data structures is really basic.
Norbo wrote:The ability for the cylindrical character to walk up steps depends strongly on how 'round' it is.
I noticed before (on the stairs) that although the CharacterController uses a Cylinder for its body, it's behaving as if it is a capsule. Now, I finally understand why.

I also experimented a bit with some of your suggestions (e.g. changing the margin, increasing maximumTractionSlope, using a smaller MaximumStepHeight) and it seems to work out, especially when I combine that with ramps as the physical representation for the stairs. I am also using the Clockwise sidedness already. After your last post I disabled stepping again and you're right it seems much better now.

Are you even aware of how good the basic mechanisms of your character controller are? I tried Unity's internal CharacterController class which is a kinematic one, UFPS (about 80€) which is good but also kinematic and has some minor walking/stair issues and Realistic FPS Prefab (about 30€) which claims to be a dynamic character controller but it's a bad one. Your controller might not be that feature rich but IMHO the foundation is much more solid!

Last but not least, is there some kind of manual for BEPU Physics? I just want to be sure that I didn't miss it if there's one.


Cheers and I can't thank you enough for answering that fast, often and detailed!
BrightBit
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Port to Unity3D - Some Issues and Questions

Post by Norbo »

That definitely sounds interesting! I would like to repeat that in my own words, just to check if I got the details right. Instead of calling Reconstruct() as I am doing now, I would be able to call something like RefitAndRefine(). This call would trigger some kind of reconstruction over time? So it spreads its work over several frames and can be used even for topology changes?
Yup!
Are you even aware of how good the basic mechanisms of your character controller are? I tried Unity's internal CharacterController class which is a kinematic one, UFPS (about 80€) which is good but also kinematic and has some minor walking/stair issues and Realistic FPS Prefab (about 30€) which claims to be a dynamic character controller but it's a bad one. Your controller might not be that feature rich but IMHO the foundation is much more solid!
I have seen a lot of issues reported by users of other systems out there, but I sympathize with the developers. Making a solid general-purpose character for 3d, especially one with support for stepping, is one of the more difficult things in game development. It's got a trifecta of raw computational geometry complexity, an extreme focus on the tiniest aspects of behavior (the player WILL notice a 5 millimeter bump), and an execution budget measured in microseconds.

I used the Source engine's character controller as a benchmark, since it's my favorite one out there. I spent a lot of time in the Hammer editor messing around making stress tests; that character is ridiculously solid. I'm pretty happy that I've been able to get as close as I have to its behavior :)
Last but not least, is there some kind of manual for BEPU Physics? I just want to be sure that I didn't miss it if there's one.
Sort of- the documentation page has a good bit of information, including introductory samples: https://bepuphysics.codeplex.com/documentation

There's no single monolithic reference though. I basically rely on people coming to the forum and gradually creating a searchable index of topics. Well, google searchable anyway; the built-in forum search is not very helpful.
BrightBit
Posts: 21
Joined: Fri Jul 08, 2016 12:11 pm

Re: Port to Unity3D - Some Issues and Questions

Post by BrightBit »

Norbo wrote:Yup!
Awesome! I'm really looking forward to version 2.0 and I definitely will use your engine instead of PhysX, now. :) I just have to investigate those uv and normal lookup suggestions - like bypassing the Space.RayCast and so on - a bit more.
Norbo wrote:[...] but I sympathize with the developers. Making a solid general-purpose character for 3d [...] is one of the more difficult things in game development.
I agree because I already tried to develop one myself.
Norbo wrote:I used the Source engine's character controller as a benchmark.
When I was using the OGRE engine some long time ago, people in the OGRE forums also admired the Character Controller of the Source engine (based on HAVOK).

By the way, thanks for the link to the documentation pieces and thanks again in general. :)
Post Reply