Been battling around this problem for the past hours. I've made a door like the one in Phasmofobia, you can hold MB1 and drag to open it or close it. The problem is that I am making a multiplayer game and I need that door to be synchronized across the server, when somebody opens it, it will open for all the players there. Right now, everyone can open the door but it's not synchronized.
I've created the script below, any suggestions? I know I have to use [Command] and [ClientRpc] but do not know how to use them here. I've used it before with animations and it's easy but it beats me in this case. I've also attached Network Identity and Network Transform to the door and did not change any settings but can't make it work.
public class DoorOpenScript : NetworkBehaviour
{
private Transform playerCamera;
[SerializeField] Transform distCheck;
[SerializeField] Transform hinge;
[SerializeField] private float maxDistance = 3f;
[SerializeField] float moveSpeed;
[SerializeField] Vector2 rotationConstraints;
bool movingDoor;
float rotation;
Vector3 targetPosition;
void Start()
{
targetPosition = distCheck.position;
// Find the player's camera at runtime
playerCamera = Camera.main.transform; // Assuming your camera is tagged as "MainCamera" or is the main camera in the scene
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = playerCamera.GetComponent<Camera>().ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
int layerMask = ~LayerMask.GetMask("IgnoreRaycast");
if (Physics.Raycast(ray, out hit, maxDistance, layerMask))
{
if (hit.collider.gameObject.CompareTag("Door") && hit.collider.gameObject == this.gameObject)
{
movingDoor = true;
}
}
}
if (movingDoor)
{
if (Input.GetMouseButtonUp(0))
{
movingDoor = false;
}
targetPosition = playerCamera.position + playerCamera.forward * 2f;
}
rotation += Mathf.Clamp(-GetRotation() * 5000 * Time.deltaTime, -moveSpeed, moveSpeed);
rotation = Mathf.Clamp(rotation, rotationConstraints.x, rotationConstraints.y);
hinge.localRotation = Quaternion.Euler(0, rotation, 0);
}
float GetRotation()
{
float firstDistance = (distCheck.position - targetPosition).sqrMagnitude;
hinge.Rotate(Vector3.up);
float secondDistance = (distCheck.position - targetPosition).sqrMagnitude;
hinge.Rotate(-Vector3.up);
return secondDistance - firstDistance;
}
}
EDIT: I've kinda made it work with Command and ClientRpc, the door syncs good but other players than the host when they are trying to pull to open the door, sometimes the door just moves a little and sometimes is does not move at all until the host is moving it again. I'm also using RequireAuthority = false inside the Command. Any idea guys? :(
I put in some skeleton code below to possibly help you out with your problem.
I will explain how my code works, and why it is written this way.
The first part that should be noted is how the door is only rotated in the CMDMoveDoor function. This is because of how the NetworkTransform component works. If the syncDirection varible (found in the inspector) is set to server to clients, that means that any changes to the rotation of the door on the client side will only affect the door on the clients device (the same door will not be rotated on the server or on other clients devices). By using a command, the client basically asks the server, "hey, could you move that door for me?", but the server is the one actually moving the door. The Network Transform will then see that the server moved the door, and will tell all the clients "hey, the door moved", and the clients should automatically update their door position to match the server.
The secound thing to notice is how we put (requiresAuthority = false) inside the [Command] code. This tells the server, "let any client call this function, even if they do not own the door". Normally, you would have to own the door to call this function, but this allows any connected client to call this function. This can be important for security reasons (For example, if each player had a script that stored the amount of points they received on the server using a [SyncVar] (a variable that can only be changed on the server but can be read by all clients), you would not want other clients to be able to change the amount of points that other players have)
While this is probably not the best explanation possible, I figured I would try to throw you a lifeline since it would be unlikely for someone more experienced at answering questions to come by and post something better. Please let me know if you need additional information, and feel free to post your new, updated code if you would like me to try to fix it for you.