1
\$\begingroup\$

I'm attempting to do a logic test regarding a client's camera in a multiplayer FPS in Unity and I'm a little uncertain of which way to implement the functionality.

The scenario:
- I have a host and a client playing together.
- I want to be able to tell if specific objects are visible from each player's camera, even on the edges of their screens.

For a local player this is simple, I just take the local camera reference, convert the target object's position to that camera's viewport space to see if it's within the bounds of the camera, and then raycast to test for blocking objects.

In a Host-Client setup, I've been attempting to ensure I do everything on the Host's machine, but the Client's camera does not exist in that context, only a third-person remote-player.

Possible solutions:

  • I could pass the object's position to the client, convert it to the client's viewport space on their machine, then send that converted position back to the Host every frame, but this seems like a lot of network traffic for this. Furthermore it would use a stale client's camera position on the Host's up-to-date object position.
  • Or I could do the full logic test on the client machine and only tell the host the result (e.g., success/fail). But from my understanding this is an ill-advised practice given how authority should be handled in a Host-Client setup...
  • Or I could keep a camera object on the remote-player and synchronise that with the client's camera position and then do the test solely on the Host's machine involving that synced camera and objects.

I'm not sure which approach to pursue and would appreciate any input!

\$\endgroup\$
1
\$\begingroup\$

You can pass the direction vector and position of the camera to the server, since it only takes up 24 bytes. Then just take the position of the object, subtract the position of the camera you just received, normalize the resulting vector and take the dot product of it and the direction vector from the client.

This gives you the cosine of the angle between the cameras viewing direction and the vector from the camera to the angle. If this is less than the cosine of the FOV, then you know the object is visible.

But, since this solution requires you to know the position and direction of the camera, unless you set it on the server side and the client has no control over it, you might as well just do the visibility check on the client side and send the results to the server. The client could just fake the vectors, so there's no point in doing a less-precise test to make it just a bit more secure.

\$\endgroup\$
  • \$\begingroup\$ Thanks for input, highlighting the importance of precision is something I hadn't thought about. Also thanks for the alternate method of detecting whether the object is visible or not, I'm definitely going to compare that with Camera.WorldToViewportPoint() to see which method is more performant! \$\endgroup\$ – Visulth May 15 at 0:28
  • 1
    \$\begingroup\$ Weighing a vector angle computation versus WorldToViewportPoint (which should be just a matrix multiply & vector division) is likely to be a micro-optimization that's not worth your time. Pick the version that gives you correct results - here, the shape of the screen is significant: you have a wider FoV horizontally than vertically, so the viewport check takes that into account but a single angle check neglects it, treating the screen as a disc. \$\endgroup\$ – DMGregory May 20 at 12:36

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.