如何通过统一运动在c#控制台上进行玩家移动计算

时间:2017-11-15 12:18:55

标签: c# unity3d client-server

问题:我如何在c#控制台上进行操作,以确定玩家应该根据玩家输入统一来进行操作。

为了进一步说明,客户端是统一运行的,服务器是c#控制台应用程序。当玩家按下移动键ex。 (w,女巫根据本地位置向前移动玩家,以便始终让玩家向前移动)它向玩家发送该玩家按下w的服务器,然后服务器响应并告诉客户端按下w,改变玩家w按bool为true。然后角色移动。

本质上,我试图弄清楚如何制作一个方程式,它将完成统一所做的事情,但没有变换,甚至变换的工作原理,以便我可以将它应用到服务器端。

以下是客户端代码:

 private void Update()
{
    SendKeysToServer();
    PlayerController();
    PlayerPositionUpdateChecker();
}

public void PlayerController()
{
    if (gameObject.name == ntwmng.Playername)
    {
        MovementControllerPlayer();
        JumpControllerPlayer();
        RotationControllerPlayer();
        MovementFinalizer(); 
    }
    else
    {
        MovementControllerClones();
        JumpControllerClones();
        RotationControllerClones();
        MovementFinalizerClones();
    }
}

public void MovementControllerPlayer()
{
    if (CharContr.isGrounded)
    {
        moveDirection = new Vector3(0, 0, 0);

        if (wKeyDownPlayer)
        {
            moveDirection = moveDirection + new Vector3(0, 0, speed * Time.deltaTime);
        }
        if (sKeyDownPlayer)
        {
            moveDirection = moveDirection + new Vector3(0, 0, -speed * Time.deltaTime);
        }
        if (qKeyDownPlayer)
        {
            moveDirection = moveDirection + new Vector3(-speed * Time.deltaTime, 0, 0);
        }
        if (eKeyDownPlayer)
        {
            moveDirection = moveDirection + new Vector3(speed * Time.deltaTime, 0, 0);
        }

        moveDirection = transform.TransformDirection(moveDirection);
        //moveDirection *= speed; 
    }

}

public void RotationControllerPlayer()
{
    if (dKeyDownPlayer)
    {
        transform.Rotate(0, RotationSpeed * Time.deltaTime, 0);
    }
    if(aKeyDownPlayer)
    {
        transform.Rotate(0, -RotationSpeed * Time.deltaTime, 0);
    }
}

public void JumpControllerPlayer()
{
    if (CharContr.isGrounded)
    {

        if (SpaceKeyDownPlayer)
        {
            moveDirection.y = jumpSpeed * Time.deltaTime;
        } 
    }
}

public void MovementFinalizer()
{
    moveDirection.y -= gravity * Time.deltaTime;
    CharContr.Move(moveDirection);
}

public void CameraAndListenerController()
{
    if (gameObject.name == ntwmng.Playername)
    {
        if (playercam.enabled == false)
        {
            playercam.enabled = true;
        }
        if (AudioListener.enabled == false)
        {
            AudioListener.enabled = true;
        }
    }
    else
    {
        if (playercam.enabled == true)
        {
            playercam.enabled = false;
        }
        if (AudioListener.enabled == true)
        {
            AudioListener.enabled = false;
        }
    }
}

public void SendKeysToServer()
{
    NetworkStream NtwrkStrm = ServerConnection.GetStream();
    IFormatter Formatter = new BinaryFormatter();

    foreach (KeyCode kcode in Enum.GetValues(typeof(KeyCode)))
    {
        if(Input.GetKeyDown(kcode))
        {
            string type = "Movement Update Key Down";
            string kycode = Convert.ToString(kcode);
            //Debug.Log(kycode);
            Formatter.Serialize(NtwrkStrm, type);
            NtwrkStrm.Flush();
            Formatter.Serialize(NtwrkStrm, ntwmng.Playername);
            NtwrkStrm.Flush();
            Formatter.Serialize(NtwrkStrm, kycode);
            NtwrkStrm.Flush();
        }else
        if(Input.GetKeyUp(kcode))
        {
            string type = "Movement Update Key Up";
            string kycode = Convert.ToString(kcode);
            //Debug.Log(kycode);
            Formatter.Serialize(NtwrkStrm, type);
            NtwrkStrm.Flush();
            Formatter.Serialize(NtwrkStrm, ntwmng.Playername);
            NtwrkStrm.Flush();
            Formatter.Serialize(NtwrkStrm, kycode);
            NtwrkStrm.Flush();
        }
    }
}

public void MovementControllerClones()
{
    if (CharContr.isGrounded)
    {
        moveDirection = new Vector3(0, 0, 0);

        if (wKeyDownClone)
        {
            moveDirection = moveDirection + new Vector3(0, 0, speed * Time.deltaTime);
        }
        if (sKeyDownClone)
        {
            moveDirection = moveDirection + new Vector3(0, 0, -speed * Time.deltaTime);
        }
        if (qKeyDownClone)
        {
            moveDirection = moveDirection + new Vector3(-speed * Time.deltaTime, 0, 0);
        }
        if (eKeyDownClone)
        {
            moveDirection = moveDirection + new Vector3(speed * Time.deltaTime, 0, 0);
        }

        moveDirection = transform.TransformDirection(moveDirection);
        //moveDirection *= speed;
    }

}

public void RotationControllerClones()
{
    if (dKeyDownClone)
    {
        transform.Rotate(0, RotationSpeed * Time.deltaTime, 0);
    }
    if (aKeyDownClone)
    {
        transform.Rotate(0, -RotationSpeed * Time.deltaTime, 0);
    }
}

public void JumpControllerClones()
{
    if (CharContr.isGrounded)
    {

        if (SpaceKeyDownClone)
        {
            moveDirection.y = jumpSpeed* Time.deltaTime;
        }
    }
}

public void MovementFinalizerClones()
{
    moveDirection.y -= gravity * Time.deltaTime;
    CharContr.Move(moveDirection);
}

public void CloneKeyUpdater(string type,string kcode)
{
    //Debug.Log("Key " + kcode + " Clone Updating");
    if (type == "Movement Update Key Down")
    {
        if (kcode == "W")
        {
            wKeyDownClone = true;
        }
        if (kcode == "A")
        {
            aKeyDownClone = true;
        }
        if (kcode == "D")
        {
            dKeyDownClone = true;
        }
        if (kcode == "S")
        {
            sKeyDownClone = true;
        }
        if (kcode == "Q")
        {
            qKeyDownClone = true;
        }
        if (kcode == "E")
        {
            eKeyDownClone = true;
        }
        if (kcode == "Space")
        {
            SpaceKeyDownClone = true;
        }
    }
    else if (type == "Movement Update Key Up")
    {
        if (kcode == "W")
        {
            wKeyDownClone = false;
        }
        if (kcode == "A")
        {
            aKeyDownClone = false;
        }
        if (kcode == "D")
        {
            dKeyDownClone = false;
        }
        if (kcode == "S")
        {
            sKeyDownClone = false;
        }
        if (kcode == "Q")
        {
            qKeyDownClone = false;
        }
        if (kcode == "E")
        {
            eKeyDownClone = false;
        }
        if (kcode == "Space")
        {
            SpaceKeyDownClone = false;
        }
    }
}

public void PlayerKeyUpdater(string type, string kcode)
{
    //Debug.Log("Key down " + kcode + " Updating");
    if (type == "Movement Update Key Down")
    {
        if (kcode == "W")
        {
            wKeyDownPlayer = true;
        }
        if (kcode == "A")
        {
            aKeyDownPlayer = true;
        }
        if (kcode == "D")
        {
            dKeyDownPlayer = true;
        }
        if (kcode == "S")
        {
            sKeyDownPlayer = true;
        }
        if (kcode == "Q")
        {
            qKeyDownPlayer = true;
        }
        if (kcode == "E")
        {
            eKeyDownPlayer = true;
        }
        if (kcode == "Space")
        {
            SpaceKeyDownPlayer = true;
        }
    }
    else if (type == "Movement Update Key Up")
    {
        if (kcode == "W")
        {
            wKeyDownPlayer = false;
        }
        if (kcode == "A")
        {
            aKeyDownPlayer = false;
        }
        if (kcode == "D")
        {
            dKeyDownPlayer = false;
        }
        if (kcode == "S")
        {
            sKeyDownPlayer = false;
        }
        if (kcode == "Q")
        {
            qKeyDownPlayer = false;
        }
        if (kcode == "E")
        {
            eKeyDownPlayer = false;
        }
        if (kcode == "Space")
        {
            SpaceKeyDownPlayer = false;
        }
    }
}

任何帮助都将非常感谢。 :)

编辑: 所以我想出了一个方程式,我正在尝试模仿玩家的动作,现在它只能在0到90度之间工作,只是告诉我得到它的确切。这个等式非常接近,但只是一点点。有什么建议?此外,这是在客户端运行,没有服务器影响,所以我可以得到精确的数学。数学出来的速度比玩家目前的位置慢了大约每秒1个单位。基本上在按下w并持续1秒后,速度= 20时,数学计算结果为19,实际位置为20。

这是代码

    if (CharContr.velocity != Vector3.zero)//checks if the player is moving
    {
        if (rotation < 90f && rotation > 0f) // makes sure the rotation is 0-90
        {
            percent = (100 / (90 / rotation)) / 100; // gets the percent
            x = x + (percent * speed * Time.deltaTime); //adds to current position multiplied by speed and delta time
            invertPercent = 1 - percent; //gets the percent for z
            z = z + (invertPercent * speed * Time.deltaTime); // adds and stuff again
        }

3 个答案:

答案 0 :(得分:1)

如果你想自己实现它而不是使用Unity的内置NetworkTransform,这真的很复杂。阅读此"Client-Side Prediction and Server Reconciliation"文章。该文章有很多部分,但它向您展示了发生了什么以及如何完成。

虽然如果您通过提供新功能(Physics.Simulate)使用Rigidbody,Unity会简化其中的一部分。您使用Physics.Simulate函数模拟服务器上的所有Rigidbody,序列化每个Rigidbody的转换并发送给所有客户端。

在客户端上,接收数据,对它们进行反序列化,然后从当前变换到接收到的变换。您可以找到一个示例,了解如何使用Physics.Simulate确定刚体在x秒here内的位置。

答案 1 :(得分:0)

将键码发送到服务器并基于bool同步位置不是最佳做法。

好的做法是,将x,y和z位置的3浮点值发送到服务器,然后将其广播给其他玩家。 所以其他玩家的确切位置没有近似值

很抱歉,如果我在错误的地方回答,因为我没有足够的代表发表评论。

答案 2 :(得分:0)

所以我做了一些搜索,并提出了一个解决方案,这仅适用于玩家向前移动且玩家方向介于0和90之间的情况。基本上我必须使用transform.translate而不是使用角色控制器。我这样做的原因是当玩家按下它时它会将它发送到服务器并且服务器可以同时运行它,然后使用该信息来告诉玩家应该是什么。

if (rotation < 90f && rotation > 0f)
        {
            moveDirection = new Vector3(0, 0, 0);
            percent = (100 / (90 / rotation)) / 100;
            invertPercent = 1 - percent;

            x = percent * speed;
            z = invertPercent * speed;
            transform.Translate(x * Time.deltaTime, 0, z * Time.deltaTime, Space.World);
            newposition = newposition + new Vector3(x * Time.deltaTime, 0, z * Time.deltaTime);
        }