跨服务器同步拖放门[Unity - Mirror]

问题描述 投票:0回答:1

过去几个小时一直在解决这个问题。我制作了一扇像 Phasmofobia 中的门,你可以按住 MB1 并拖动来打开或关闭它。问题是我正在制作一款多人游戏,我需要在服务器上同步该门,当有人打开它时,它就会为那里的所有玩家打开。现在每个人都可以开门,但不同步。

我创建了下面的脚本,有什么建议吗?我知道我必须使用

[Command]
[ClientRpc]
但不知道如何在这里使用它们。我以前在动画中使用过它,它很简单,但在这种情况下它打败了我。我还将网络身份和网络转换附加到门上,没有更改任何设置,但无法使其工作。

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;
    }
}

编辑:我已经让它与

Command
ClientRpc
一起工作,门同步良好,但主机以外的其他玩家在尝试拉开门时,有时门只是移动了一点,有时是在主机再次移动它之前它根本不会移动。我还在
Command
中使用 RequireAuthority = false。大家有什么想法吗? :(

c# unity-game-engine mirror unity3d-mirror
1个回答
0
投票

我在下面添加了一些框架代码,可能会帮助您解决问题。

我将解释我的代码是如何工作的,以及为什么这样写。

首先要注意的是CMMDoveDoor函数中门是如何旋转的。这是因为 NetworkTransform 组件的工作方式。如果syncDirection变量(在检查器中找到)设置为服务器到客户端,这意味着对客户端门旋转的任何更改只会影响客户端设备上的门(同一门不会影响客户端设备上的门)。在服务器或其他客户端设备上轮换)。通过使用命令,客户端基本上会询问服务器:“嘿,你能为我移动那扇门吗?”,但实际上是服务器移动了门。然后,网络转换将看到服务器移动了门,并告诉所有客户端“嘿,门移动了”,客户端应自动更新其门位置以匹配服务器。

第二个需要注意的事情是我们如何将 (requiresAuthority = false) 放入 [Command] 代码中。这告诉服务器,“让任何客户端调用此函数,即使他们不拥有门”。通常,您必须拥有门才能调用此函数,但这允许任何连接的客户端调用此函数。出于安全原因,这可能很重要(例如,如果每个玩家都有一个脚本,使用 [SyncVar](该变量只能在服务器上更改,但可以被所有玩家读取)存储他们在服务器上收到的积分数量客户),您不希望其他客户能够更改其他玩家拥有的积分)

虽然这可能不是最好的解释,但我想我会尽力给你一条生命线,因为在回答问题方面更有经验的人不太可能过来并发布更好的东西。如果您需要更多信息,请告诉我,如果您希望我尝试为您修复它,请随时发布您的新的、更新的代码。

using System.Collections.Generic;
using UnityEngine;
using Mirror;


public class DoorController : NetworkBehaviour
{
    public void Update()
    {
        if (isClient)
        {
            //Check If The Player Wants To Move The Door

            //If So, Call CMDMoveDoor(), And Input The Degrees That Should Be Moved
            //Do NOT Move The Door Here. The Door Should Only Be Moved On The Server
        }   
    }

    //This Can Be Called By Any Client, But Ran On The Server
    [Command (requiresAuthority = false)] 
    void CMDMoveDoor(float degrees)
    {
        //Optionally, You Can First Check The Degrees Amount To Make Sure That It Is Reasonable.
        //For Example, If It Would Rotate Too Far Or Too Fast, You Can Clamp It Here

        //Now, Update The Position Of The Door Here By The Degrees Specifed. 
        //Make Sure Your Network Transform Is Added To The Object Or It's Parent, And That The Sync Rotation Bool Is Set To True In The Inspector
        //If The Server Owns The Door, The Door's Rotation Will Sync Across All Clients Automatically
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.