Search Unity

Trying to keep object aligned with surface, keeps detaching

Discussion in 'Physics' started by imaginaryhuman, Feb 25, 2015.

  1. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    Ok so I am making a simple 2D game with a curved/wavy surface. I have an object I want to align to the surface and move along it. It adjusts its rotation to match the normal of the surface. I'm using a simple edge collider.

    The way I've done it is simply to give the character a sphere collider, then another sphere collider (on a child object) is positioned on the opposite side of the surface, and they're joined by a `tight spring` which tries to balance out quickly. I also tried it with a fixed distance joint.

    When moving the character object, I set the player's rigidbody's velocity vector to move to `the right`, based on the surface normal.

    Obviously the surface is not perfectly spherical, it's made of flat-edged polygons. My physics settings are about default, with a frictionless physics material given to the sphere colliders.

    Problem is, I can have the character move at a certain speed and he'll stay locked to the surface. But after a certain point, if the speed is too high moving over a tighter curve, his movement `to the right` tends to be too strong and forces the colliders to pass through the surface, causing the player to detach from the surface and go flying off.

    One fix which does work, is to ramp up the physics timestep, e.g. instead of 60hz, change it to 100hz, or 120. When it's high enough, based on move speed and curvature, it becomes stable. Ramping up the number of position/velocity iterations does NOT fix it, even at 100. I understand why this is needed - because really the simulation needs to happen in much smaller increments to be accurate enough. This is even with continuous collision detection and interpolation/extrapolation on all objects. If the timestep is too coarse then the player loses the surface much more often. Problem is, hiking up the physics process just for the sake of the player means all other objects also hike up their processing, unnecessarily. I want to avoid this if possible.

    I've tried doing a raycast from the player to the surface and then using the surface normal to apply a negative force pushing the player against the surface, but this also does not solve it.

    Anyone got any tip or idea how I can get the object to move much faster over the surface without losing contact? My last ditch thought is that I will have to do many more raytasts in order to predict the surface curvature and adjust the velocity vector to match? The problem mainly happens on convex curves.
     
    Last edited: Feb 25, 2015
  2. Billy4184

    Billy4184

    Joined:
    Jul 7, 2014
    Posts:
    6,023
    If you're using an edge collider perhaps you could get the array of collider nodes using EdgeCollider2D.points and then find which two collider nodes you are between by comparing your character location to the node positions (maybe attach an empty gameobject to your character's feet to prevent errors from the character rotation). Then all you have to do is find the angle between the two nodes and set your character's rotation to the perpendicular of that.
     
  3. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    Seeing the rotation is not a problem. Firing a raycast down toward the surface gives a `normal` for the surface angle. That's easy. What's not easy is taking into account a convex surface... if I just move the character 90 degrees to the right by a given distance, on a curve like that he goes `into the air` away from the surface, whereas he should really have stayed anchored to it.

    What I've done temporarily is fire a second raycast from a location to the right of/ahead of the player, down toward the surface. I compare the distance of this ray from the surface, to the distance of the ray beneath the player. The ratio of the two then scales an amount of `extra angle` which is added to the 90degrees, to then project a new velocity position which is more `hugging` of the surface. I'd say it helps a bit... .seems to... but so far nothing helps as much as going to 100 or 120hz physics timing.
     
  4. Billy4184

    Billy4184

    Joined:
    Jul 7, 2014
    Posts:
    6,023
    Heh, I'm still not familiar with a lot of the built-in functionalities of Unity! :)

    Let me see if I'm getting this correctly - your character has too much momentum on convex surfaces and does a flying jump when the surface angle changes?

    First of all, in my limited experience with joints suggests that they are not stable when taken out of conservative settings...like high velocity collisions, joints tend to do funny things when wound too tight or jerked too hard, even if the settings are theoretically 'safe'. Add to this your colliders passing through eachother and it seems to me that trying to solve this using the physics engine is not the best way.

    The way I would do it, then, is to read the surface angle and apply direct scripted motion to the character through the rigidbody2D.velocity such that you are always hugging the surface. For example, you could set the character as a child of an empty gameobject which is just below the character's feet and then control this gameobject to navigate directly between nodes on the collider, applying rotation by reading the surface normal.

    By the way, is your rigidbody mass set to zero? That might reduce greatly your momentum. Other than that perhaps you could add a continuous dynamic 'gravity' force to the character depending on the surface angle, although a bit of friction might be in order to prevent small errors resulting in sideways movement.
     
    Last edited: Feb 25, 2015
  5. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    Yah i'll keep fiddling with it. If I can help it I dont want to have to tap into the collider data. Also I have many segments that are separate objects, and would have to changing between them.

    For now I've ramped up the physics timing to 0.008888 instead of 0.016666 (ie 120hz) and this mostly seems to fix everything. I don't think I'm going to have a really huge amount of physics going on so hopefully it stays manageable.

    I am though having to throw in some kind of `safety checks` because sometimes, just occasionally, something wacky happens and the player goes flying off.
     
  6. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    I added some workarounds/safety checks that seems to take care of the object leaving the surface... i fire a spread of raycasts around the player when he is too far from any surface, and find the nearest surface, then move the player toward the surface to put him back in place. Seems to work so far. I also had to add another workaround to stop the player sinking into the surface, which happens in more concave areas sometimes. Gotta do what you gotta do. Raycats, can't live without em.
     
  7. Billy4184

    Billy4184

    Joined:
    Jul 7, 2014
    Posts:
    6,023
    Maybe a good perspective on this problem would be to ask yourself what sort of world you are trying to make. For example if your terrain was a circular 2D planet it would make the most sense to create a gravitational force pulling toward the center. Doing it this way would help tie in the mechanics with the 'reality' you are trying to make. If you're keen to have things done by the physics engine, what other mechanics will have to fit in with the method you use (e.g. with the two colliders and spring, a jumping mechanic would be very difficult to integrate).

    I think the cleanest approach through physics would be to have a local force field pulling the character down the surface normal. This force might be adjusted to increase when the character is further away from the surface in order to get a tight effect without yanking the character down through the ground. Sort of like a 'lerp to surface' force with a high coefficient. If you made the force negative when the character went below the ground this would take care of your concave problem as well.
     
  8. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    Yes, good ideas, thanks. Its funny when you get bugs like this that it undermines confidence in knowing that things will continue to be stable in the long term. I have to rely on the physics engine and it obviously has some subtle quirks at times, and the thought that just one error at some point in the future might completely freeze the game is a bit scary... but putting as many checks and measures in place as possible to try to avoid that and deal with it as gracefully as possible.

    Regarding circular world... no, for some secret reasons ;-)