#Networked physics

36 messages · Page 1 of 1 (latest)

fierce wharf
#

I'm trying to make a physics driven game but am encountering an issue that I can't seem to wrap my head around.
To boil down the issue to the simplest version:
I have a big ball that can be pushed. Currently when a player tries to push it, it does not move. Only the owner of said object is able to push it.
One solution could be granting authority to the player that is touching it, but then another playing that simultaneously wants to push it will also not be able to push it.

How would I be able to make this work?

sleek cosmos
# fierce wharf I'm trying to make a physics driven game but am encountering an issue that I can...

All physics / collisions has to be on server, with server updating clients via NetworkTransform with Sync Direction set to Server To Client. Multiple Additive Scenes example has tumblers that players can push around. To make that look decent, I make the colliders on players a little bigger to cover the lag of players moving on clients because clients can only move things they own and switching ownership isn't fast enough and will mess up the physics anyway.

fierce wharf
#

I there no way to have some state/solution that attempts to assign authority based on user proximity?

#

I recall somehow being able to play with a rigidbody on all clients untill someone picked it up (and thus claimed auth)

sleek cosmos
fierce wharf
#

I tried an example where i throw the object into the proximity of the other player, and I still see a jitter when it transfers. The use case is VR in this case, so we're not talking 100s of units per second

sleek cosmos
#

@kindred hill Has worked on VR stuff, so I'll let him chime in.

fierce wharf
#

Thanks for the help so far in any case!

sleek cosmos
# fierce wharf I tried an example where i throw the object into the proximity of the other play...

Short version...on the object:

public Rigidbody rb;

protected override void OnValidate()
{
    if (Application.isPlaying) return;
    base.OnValidate();
    rb = GetComponent<Rigidbody>();

    // initialize for all cases
    rb.isKinematic = true;
}

[ServerCallback]
void OnTriggerEnter(Collider other)
{
    if (!other.CompareTag("Player") return;
    // if someone already owns this thing, abort
    if (connectionToClient != null) return;
    if (!other.TryGetComponent(out NetworkIdentity ni) return;

    // order matters here for host client
    rb.isKinematic = true;
    netIdentity.AssignClientAuthority(ni.connectionToClient);
}

[ServerCallback]
void OnTriggerExit(Collider other)
{
    if (!other.CompareTag("Player") return;
    if (!other.TryGetComponent(out NetworkIdentity ni) return;
    // if 'other' isn't the current owner of this thing, abort
    if (connectionToClient != ni.connectionToClient ) return;

    // order matters here for host client
    ni.RemoveClientAuthority();
    rb.isKinematic = false;
}

// Enable / Disable owner ability to push this thing
public override void OnStartAuthority() { rb.isKinematic = false; }

public override void OnStopAuthority() { rb.isKinematic = true; }
fierce wharf
#

Okay, this seems to flip kinematic when a player wants to claim authority, but is there a way to preserve angular-/velocity aswell?

sleek cosmos
fierce wharf
#

The unreliable network transform

#

I read the rigidbody sync and noticed it only really sets kinematic, so i did that myself on the scripts that are on every synched RB anyways

sleek cosmos
# fierce wharf The unreliable network transform

You can try something like this:

public class CustomNT : NetworkTransformUnreliable
{
    public Rigidbody rb;

    protected override void OnValidate()
    {
        if (Application.isPlaying) return;
        base.OnValidate();
        rb = target.GetComponent<Rigidbody>();
    }

    protected override void Apply(TransformSnapshot interpolated, TransformSnapshot endGoal)
    {
        if (!isOwned)
        {
            rb.velocity = (transform.position - interpolated.position) / Time.deltaTime;
            rb.angVelocity = (transform.rotation.eulerAngles - interpolated.rotation.eulerAngles) / Time.deltaTime;
        }

        base.Appy(interpolated, endGoal);
    }
}
fierce wharf
#

Would an alternative also to reference the attached rigidbody? Or do you reckon this will cover it? The rigidbodies do havve differing masses

sleek cosmos
#

This would reference the rb on the same object as the customNT. This is untested, just a guess for something to try.

sleek cosmos
fierce wharf
#

Thanks for the help! I'll give it a try as soon as I can!

#

I'll keep you posted on the results

fierce wharf
#

Okay, I might be getting close to a desirable result, I'm just hitting one last issue it seems. (see attached gif) https://gyazo.com/b725f7a4e7b51b826fb982cee4044f6c
The wire box is green when local has authority and is running the sim. Red is when a remote is the owner and local listens to the unreliable transform.

When recieving the authority there appears to be none to minimal stutter, but when losing authority and granting the other user authority, there is some rubberbanding.

The amount of rubber banding is also not really consistent each time control is transfered.

To note: this same behaviour happends when a non-server+client instance is running this.

I suspect it is the interpolation that happens in the unreliable network transform.
Do you have any insights to share on the issue that could help me past this?
@sleek cosmos

#

The authority assigning happens in a seperate script that monitors the players and their positions. When the ball exceeds a given treshold, ownership is transfered to the closest player

sleek cosmos
fierce wharf
#

I am calling ResetState on the NT's on OnStartAuth and OnStopAuth

kindred hill
fierce wharf
#

It is intended for a pickup system, but i'm making it entirely physics driven. I'm trying to avoid any clinet-to-server delays that might result from that. It's a VR application, so anything that doesn't feel immersive I'm trying to avoid

fierce wharf
#

Is there perhaps a way to force a position into the interpolation of the network transforms?

#

The yellow line is the position that is passed through by the old authority holder, and the blue position is where the position gets set. What I'm thinking is to maybe force the NT to the yellow line position

#

Would such a thing be possible?

#

That would honestly fix this to a near-seamless state

#

For reference: The jitter happens when the authority is passed from local to another client. This is indicated by the green and red box around the ball

sleek cosmos
# fierce wharf https://gyazo.com/7239d311cda1afafb213012096e91e62

Please create a tiny Unity package (excluding Mirror) of your example and create a ticket here so we can take a look at it. We're working on a new NT component and we can add that to the test cases.

To create the package:

  • Put all relevant code, scene, prefabs, and art in a folder by itself at project root...keep it as stripped down simple as possible.
    • Do not send us your entire project - that will be discarded for sure.
  • Right-click the folder and choose Export Package
  • **DESELECT **the checkbox for including dependancies...we don't need Mirror or anything else from your project.
  • After the package has been saved, put it in a zip file and drop it directly into the ticket so it's attached
    • Do not put it somewhere else with a link to it like onedrive or dropbox or whatever - it will disappear.
fierce wharf
#

I'm approaching something that seems to at least be semi-stable for now. I am calling the teleportRPC on auth gained. Sometimes it seems to race with an Update call that is done by the rest of the component, but I think i can work around it for now.
Our player code is sort of wrapped into a lot of the rest of the project, so isolating it is not an easy job.
The core issue that is happening here is that I want (semi-)true seamless networked physics. I think a lot of this could be solved in a networked physics sync script that also tracks velocity/angular velocity, or some utility inside that script that on auth transfer communicates anything it needs to seamlessly transfer control and simulation. Maybe a nedID.YieldAuthority(netID other). Currently you have to remove auth, then grant auth again, but a netID that yields itself to another would ensure anything I need to have communicated on transfer is there in the call with it

#

But that's just me spitballing. I'm trying something Mirror is not built for (just yet). I'm loving the backend and it's functionalities for other, actually meant for, implementations

#

Thanks for all the help!