Fast collisions with Photon Rigidbodys (Golf game)

I am working on a networked golf game and trying to add collision between the balls. Each player has a ball prefab with Photon components like so: https://imgur.com/VrP10Jc

As it is right now, the balls often don't register a collision when they are moving too fast, although they register fine for slower collisions. Is there any other setting that can help me register fast collisions?

An alternative is to have the master client own all the balls and simulate all the movement. However, that's not very smooth from the player's perspective because every time they hit their ball, they might have to wait 100-200 ms to see it actually move.

Any ideas welcome!

Comments

  • I could increase the send rate but that might be a bad idea.
  • And if the answer is "You just have to do it on a master client"... I would appreciate some basic tips on that.
  • S_Oliver
    S_Oliver ✭✭✭
    Each player has its own Golfball? So the balls are just syncd over the network,means u only sync position , the collision detection should hapen on the owner side.
    What you are locking for is https://docs.unity3d.com/ScriptReference/Rigidbody-collisionDetectionMode.html
  • Hi S_Oliver,

    The balls are all set to Continuous Dynamic. The physics itself works, it's definitely a network problem. When the balls move too quickly, the Photon Rigidbody View doesn't register a collision.
  • S_Oliver
    S_Oliver ✭✭✭
    edited August 2018
    The Rigidbody View itself only Sync the Velocity, it dont detect Collision.

    Try the same Offline, use only the Rigidbody and see what happen.

    http://doc-api.photonengine.com/en/PUN/current/class_photon_rigidbody_view.html#details
  • Thanks for the reply.

    So I did try the collision offline, and the collision itself works locally, even with very fast movement.

    Now I see that the Rigidbody View only syncs velocity. If I wanted to detect a collision over the network, how should I do so?
  • Bumping my thread. Any suggestions for collision detection over the network, as the Rigidbody Views aren't really for that purpose? Should I go for a model with an authoritative master client or not? Open to any ideas!
  • Still open to any ideas!
  • Still open to any ideas!
  • STILL open to any ideas! Not sure why I've been trolled... Great customer support
  • sah1234
    sah1234
    edited August 2019
    For the annals of history, collision detection is done through a custom rpc setup. Not perfect but definitely fine for this use case.

    void OnCollisionEnter(Collision collision)
    {
    if (!photonView.IsMine)
    return;

    Collider other = collision.collider;

    if (other.tag != "PlayerBallNetwork")
    return;

    Vector3 otherVelocity = other.attachedRigidbody.velocity;

    //Set other velocity
    PhotonView otherPhotonView = other.transform.root.GetComponent();
    Player otherPlayer = otherPhotonView.Owner;
    otherPhotonView.RPC("SetVelocity", otherPlayer, otherVelocity);
    }

    [PunRPC]
    void SetVelocity(Vector3 velocity)
    {
    rb.WakeUp();
    rb.velocity = Vector3.zero;
    rb.AddForce(100 * velocity); //Change this for more forceful collisions
    }
  • Minitte
    Minitte
    edited August 2019
    I had a sort of a similar problem that I'm fixing. I think the reason why collisions are not consistent is that the objects are actually teleporting to their new locations and the colliders will actually teleport inside each other.

    Maybe if the physics is done on the master client's side and everyone else would sleep the rigidbody every frame.
  • [SOLVED]

    I may be a bit late, at least for your game, but for future people with the same issue, I have solved it, by changing the Ownership of the Photonview you have collided with, to be the same owner as the object with the heighest speed in the collision. And once the collision has finished, the owners are reset back to how they were to start with.


    using System.Collections;

    using System.Collections.Generic;

    using UnityEngine;

    using Photon.Pun;

    using Photon.Realtime;


    public class GolfBall : MonoBehaviourPun

    {


      PhotonView view;

      Rigidbody rb;


      private void Start()

      {

        rb = GetComponent<Rigidbody>();

        view = GetComponent<PhotonView>();

      }


      private void OnCollisionEnter(Collision collision)

      {

        if (view != null)

        {

          if (view.IsMine)

          {

            if (collision.gameObject.name == "GolfBall(Clone)" && collision.gameObject != this.gameObject)

            {

              if (!collision.transform.GetComponent<PhotonView>().IsMine)

              {

                print("SIIUUUUUUUSUISUISUI");

                Vector3 rb2 = collision.transform.GetComponent<Rigidbody>().velocity;

                if (Mathf.Sqrt((rb.velocity.x * rb.velocity.x) + (rb.velocity.y * rb.velocity.y) + (rb.velocity.z * rb.velocity.z)) > Mathf.Sqrt((rb2.x * rb2.x) + (rb2.y * rb2.y) + (rb2.z * rb2.z)))

                {

                  collision.transform.GetComponent<GolfBall>().TransferOwnership();

                  collision.transform.GetComponent<Rigidbody>().velocity += rb.velocity * 100f;

                }

              }

            }

          }

        }

      }


      public void TransferOwnership()

      {

        base.photonView.RequestOwnership();

      }

    }




    IMPORTANT: This is attatched to the Golf Ball, and only handles the turning of the other body in the collision into your own owner, however, it is equally important to set the owner back to its original owner. This can be done for example, by checking the velocity of the ball, and once it is equal to Vector3.zero, you check if it is not your photon view, and if it was your original view (this can be done by setting a boolean on the start method as such):


    using System.Collections;

    using System.Collections.Generic;

    using UnityEngine;

    using Photon.Pun;


    public class GolfBallExternalController : MonoBehaviourPun, IPunObservable

    {

    public Rigidbody Ball;

      public PhotonView view;

      bool StartMine;


    private void Start()

      {


        if (view.IsMine)

        {

          StartMine = true;

        }

      }

    }


    and if all of the conditions match, you can set back the player to be your view, as such:

    private void Update()

    {

          if(ball.velocity == Vector3.zero && StartMine && !view.IsMine)

          {

            ball.GetComponent<GolfBall>().TransferOwnership();

          }

    }




    I hope this answer was helpful to someone, and any doubts, just ask.

  • Hey SDev, interesting approach there! I still think it's simpler to just apply a velocity modifier by RPC because ownership changing could come with side effects. But maybe your use case is more complex.

    Not to be too off topic but Photon Fusion has a cool demo for golf. https://doc.photonengine.com/en-us/fusion/current/game-samples/fusion-golf