1
\$\begingroup\$

I'm making a shooter in Unity with UNET, and of course I handle projectile (like arrows) collision on the server.

The arrows are Networked rigidbodies with NetworkBehaviours, and I would like to spawn a Non-networked, eye candy like client side prefab at the collision point.

Current solution:

protected override void OnServerFixedUpdate()
{
    var distanceSincePreviousFrame = Vector3.Distance(positionAtPreviousFrame, rb.position);
    Collider collider;
    Vector3 impactPoint;
    if(CheckForImpactInNextFrame(distanceSincePreviousFrame, out collider, out impactPoint))
    {
        transform.position = impactPoint;
        DoImpactEffect(collider);
        GetComponent<Rigidbody>().isKinematic = true;
        NetworkServer.Destroy(gameObject);
    }
    positionAtPreviousFrame = rb.position;
}
void OnDestroy()
{
    var go = Instantiate(ClientSidePrefab, transform.position, transform.rotation);
}
  • The rigidbody flies on the server (rigidbody synced), and CheckForImpactNextFrame checks collision by raycasting. (needed so projectiles won't go through things due to simulation errors).

  • If it collides, then it does its impact effect, then destroys itself on the network.

  • Clients instantiate a client side, non networked prefab for visuals when the networked projectile is destroyed.

At the server side this works well, "client side arrow" is instantiated at the impact position,

but at clients, it's instantiated at its previous position, because the transform.position = impactPoint; in the if isn't synced before it is destroyed on the clients.

How could I make those client side visuals appear at the correct position?

Could I call a "force sync" before destroying?

I can't call an RpcCreateVisuals(position) method, because the entity may be destroyed on the client when the Rpc message arrives. (because the destroy message was faster.)

I could call an "always alive" object's Rpc, like a ProjectileManager's method, and I think that it will always arrive, because destroying the projectile has no effect on it. But it feels hacky, non OOP. Doesn't it?

How should I solve this solution? What is the common approach for this problem?

The same problem described by someone else: https://answers.unity.com/questions/1636182/client-objects-not-traveling-same-distance-as-on-s.html

Maybe I could disable them, and subscribe them to a "GarbageCollector" system, which destroys them only after a delay? Is this a well designed solution?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.