Friction and Restitution swapped in 3D?

Hi, I wasted a couple hours yesterday trying to get a ball bouncy, until i figured out that friction sets the bounciness of the ball instead of restitution, so i figured i'll just give a heads up for others that encounter this in the future. Set friction to 1 to get perfect elastic bounce. Haven't tested if the opposite is true as well (restitution setting the value for friction), since it's harder to test.

Comments

  • blubwage
    blubwage
    edited July 2017
    Got some more testing done after implementing it in my game. It seems the Friction value sets both friction and restitution. So if you put friction to 1, balls bounce between walls at almost 90° angle take a long time to lose speed, while flatter angles slow down significantly with each bounce. The restitution value doesn't seem to do anything. Is there any way to adjust these manually? My game evolves all around drones bouncing around that the players have to dodge, so not being able to get an elastic bounce kinda kills the whole concept. Would need to set velocity manually all the time, which i kinda want to avoid.

    Edit: Seems like they also change angle on collision (entry angle is always greater than exit angle, so after a while they align to a 90° angle, which might actually be the reason for them changing speed all the time. Doesn't really seem all that usable for my situation, so i guess i won't get around writing my own bounce behaviour :/
  • Update: I've been trying to create my own bounce behaviour, but ran into problems with contacts[0].normal not returning the proper values at times. I surrounded the ball by 4 truesync cubes, made it's collider a trigger and attached a TrueSyncBehaviour with:
            public void OnSyncedTriggerEnter(TSCollision other)
            {
                if (other.gameObject.layer != 19 && other.gameObject.layer != 16)
                    return;
                var normal = other.contacts[0].normal * -1;
    
                if (TSMath.Abs(normal.x) > 0.1 && TSMath.Abs(normal.z) > 0.1)
                {
                    tsRigidBody.velocity *= -1;
                }
                else 
    {
                    tsRigidBody.velocity = -2 * TSVector.Dot(tsRigidBody.velocity, normal) * normal + tsRigidBody.velocity;
                }
            }
    I added the (TSMath.Abs(normal.x) > 0.1 && TSMath.Abs(normal.z) > 0.1) check to counteract corners, where it enters two colliders during one lockstep tick and would therefore would get sent outside the walls. So far that was working decently, but occasionally, hits with single walls will also return contact[0].normal vectors that trigger said condition. For example, a ball bouncing with the top wall (which usually returns contacts[0].normal = (0, 0, 1)) suddenly returns (0.9, 0, 0.4). I honestly am out of ideas as to why this happens and how to fix it. I tried adding f.e.
    if (TSMath.Abs(normal.x) > TSMath.Abs(normal.z)) 
    {
            normal.x = TSMath.Sign(normal.x);
            normal.z = 0; 
    }
    and vice versa to counteract derivations in the contact[0].normal vectors, but sometimes the derivation is so big that f.e. a trigger at the top wall will return a vector with Abs(normal.x) > Abs(normal.z), which would once again lead the ball outside of the walls due to the new normal vector being 90° to what it should be. I also checked whenever a ball was in 2 colliders at once when these things happened by adding the TSCollision to a list on trigger enter and removing it from the list on trigger exit, but the problems don't seem to have anything to do with that, drones passed by when they were in only 1 collider, while they didn't pass by when they were in 2 and the other way around.

    I really want to use TrueSync, since it seems to be by far the best fit for our game (many neutral enemies at once, players only controlling their character with click to move to dodge things), but no matter what i try, I can't figure out a way to get a normal elastic bounce with entry angle = exit angle on the TrueSync engine, which is the basis of the entire game. I'd really appreciate any ideas how that would be achievable.
  • blubwage
    blubwage
    edited July 2017
    2nd Update: Uploaded a sample project: https://drive.google.com/open?id=0B9OuKnRGElPyQ3YtVWtrOURYNTQ
    Test1 scene shows how balls (friction set to 1 to make them bounce) try to allign themselves to the normal vector on bounce and lose velocity based on how much the bounce vector deviates from the normal vector.
    Test2 scene shows my attempt at writing a bounce script utilizing contacts[0].normal. Every time a normal vector deviates from what it should be and every time the trigger is in contact with 2 colliders it prints it to the console. If you let it run long enough, you'll notice balls slipping out (might want to increase ball count to reduce wait time).
  • blubwage
    blubwage
    edited July 2017
    Update 3: Somewhat reliable workaround for now: Surround your colliders with a backup collider (my wall colliders are 1 units thick and the backup colliders are moved 0.5 units towards the outside, so drones have 0.5 units to bounce properly, otherwise backup triggers). Should the drone pass through the normal colliders and hit the backup colliders, reverse their velocity to send them right back in. My bounce script:
            public void OnSyncedTriggerEnter(TSCollision other)
            {
                if (other.gameObject.layer != 19 && other.gameObject.layer != 16)
                    return;
    
                var normal = other.contacts[0].normal * -1;
    
                if (other.gameObject.name == "Backup")
                {
                    Debug.Log("needed backup");
                    tsRigidBody.velocity *= -1;
                }
                else
                {
                    if (TSMath.Abs(normal.x) > 0.1 && TSMath.Abs(normal.z) > 0.1)
                    {
                        if (TSMath.Abs(normal.x) > TSMath.Abs(normal.z))
                        {
                            normal.z = 0;
                            normal.x = TSMath.Sign(normal.x);
                        }
                        else
                        {
                            normal.x = 0;
                            normal.z = TSMath.Sign(normal.z);
                        }
                    }
    
                    tsRigidBody.velocity = -2 * TSVector.Dot(tsRigidBody.velocity, normal) * normal +
                                               tsRigidBody.velocity;
                }
            }
    
    Feels ugly, but couldn't come up with anything better. At least it's working consistently in my tests.
  • Hi @blubwage, as you noticed we don't have a reliable 3D physics, we are Jitter for that, it works good for most scenarios but several specific needs for a game generally shows up an issue with the engine :/. We will note down this issue, thanks for sharing code and sample projects.
  • It's a typo in the TSCollider script, line 159
    if (tsMaterial != null) {
        newBody.TSFriction = tsMaterial.friction;
        newBody.TSRestitution = tsMaterial.friction;
    }
  • Yep, we have fixed it in the current repo, thanks @MerlijnGamedia.