Unity Moving Player腿多人游戏

时间:2018-12-14 18:14:30

标签: c# unity3d game-engine

我目前正在开发游戏,并且遇到以下情况:

我有一个附带有脚本的Player预制游戏对象(请参见下文)。我已经设置了网络管理器,并在“服务”下设置了一个帐户,以便能够使用多人游戏方面。

我已经进行了基本设置,以便播放器可以生成并可以进行多人游戏。玩家可以移动,每次构建会话时我都能看到其他玩家的移动。

我有一段代码,当播放器“行走”时(如果按了A,W,S或D键,则称为“ CmdWalk()”。)

基本上CmdWalk()使它改变了播放器的腿部旋转,使它看起来好像在走路。 (我不喜欢动画,所以这是我唯一的方法。)

问题在于,只有本地玩家才能看到他们的玩家“行走”,而其他在线玩家则看不到移动。  我不确定自己做错了什么,请有人帮忙。

以下是我为播放器准备的整个脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class PlayerController : NetworkBehaviour
{
    public float speedH = 2.0f;
    private float yaw = 0.0f;

    public float WalkingTime; //timer for walking animation
    public GameObject PlayerLeftLeg;
    public GameObject PlayerRightLeg;

    private float PlayerStatMenuTimer;
    public GameObject PlayerStatsMenu;

    // Update is called once per frame
    void Update () 
    {

        if (!isLocalPlayer)
        {
            return;
        }

        //keep track of time for player stat menu
        //if not here than menua will show and hide like a thousand times when pressed once due to update reading code per frame
        PlayerStatMenuTimer = PlayerStatMenuTimer + 1 * Time.deltaTime;

        //moving player left right forward backward
        var x = Input.GetAxis ("Horizontal") * Time.deltaTime * 50.0f;
        var z = Input.GetAxis ("Vertical") * Time.deltaTime * 50.0f;
        transform.Translate (x, 0, z);

        //rotating player or "Looking"
        yaw += speedH * Input.GetAxis ("Mouse X");
        transform.eulerAngles = new Vector3 (0.0f, yaw, 0.0f);

        //if player is using WASD to move then do leg moving animation
        //if not moving then set legs to be still and reset in standing position
        //FYI:  "transform.TransformVector(1,0,0)" was used instead of "Vector3.forward" was because
        //   vector3.forward is local space, so when i rotate player the sense of "forward" also changes, thus i needed
        //  a code that uses the world space, thus i used "transform.TransformVector(1,0,0)"
        if (Input.GetKey (KeyCode.W) || Input.GetKey (KeyCode.S) || Input.GetKey (KeyCode.A) || Input.GetKey (KeyCode.D))
        {
            CmdWalk ();
        }
        else
        {
            //if player not walking then reset
            PlayerRightLeg.transform.rotation = Quaternion.AngleAxis (0, Vector3.forward);
            PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis (0, Vector3.forward);
            WalkingTime = 0;
        }

        //get hidden mouse pointer back and unlock
        if (Input.GetKey (KeyCode.Escape))
        {
            Cursor.lockState = CursorLockMode.None;
        }

        //opens and closes stat menu
        if (Input.GetKey (KeyCode.Return) && (PlayerStatMenuTimer >= 1) && (PlayerStatsMenu.activeSelf == false)) 
        {
            Cursor.lockState = CursorLockMode.None;
            PlayerStatsMenu.SetActive (true);
            PlayerStatMenuTimer = 0;

            //call the script "GetplayerStats" and call function "retrieceplayerstats"
            var GetStats = GetComponent<GetPlayerStats> ();
            GetStats.RetrievePlayerStats ();

        }
        else if (Input.GetKey (KeyCode.Return) && PlayerStatMenuTimer >= 1 && PlayerStatsMenu == true) 
        {
            Cursor.lockState = CursorLockMode.Locked;
            PlayerStatsMenu.SetActive (false);
            PlayerStatMenuTimer = 0;
        }
    }

    private void Awake ()
    {
        //this code locks mouse onto center of window
        //Screen.lockCursor = true;
        Cursor.lockState = CursorLockMode.Locked;
    }

    [Command]
    void CmdWalk ()
    {
        //timer
        WalkingTime += Time.deltaTime;

        //right leg stepping forward
        if (WalkingTime > 0 && WalkingTime < .4)
        {
            PlayerRightLeg.transform.rotation = Quaternion.AngleAxis (PlayerRightLeg.transform.rotation.x - (60 * WalkingTime), transform.TransformVector (1, 0, 0));
            PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis (PlayerLeftLeg.transform.rotation.x + (60 * WalkingTime), transform.TransformVector (1, 0, 0));
        }

        //left leg stepping forward
        if (WalkingTime >.4 && WalkingTime < 1.2)
        {
            PlayerRightLeg.transform.rotation = Quaternion.AngleAxis (PlayerRightLeg.transform.rotation.x + (60 * (WalkingTime - .8f)), transform.TransformVector (1, 0, 0));
            PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis (PlayerLeftLeg.transform.rotation.x - (60 * (WalkingTime - .8f)), transform.TransformVector (1, 0, 0));
        }

        //right leg stepping forward
        if (WalkingTime > 1.2 && WalkingTime < 1.59)
        {
            PlayerRightLeg.transform.rotation = Quaternion.AngleAxis (PlayerRightLeg.transform.rotation.x - (60 * (WalkingTime - 1.6f)), transform.TransformVector (1, 0, 0));
            PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis (PlayerLeftLeg.transform.rotation.x + (60 * (WalkingTime - 1.6f)), transform.TransformVector (1, 0, 0));
        }

        //resetting
        if (WalkingTime > 1.6)
        {
            PlayerRightLeg.transform.rotation = Quaternion.AngleAxis (0, Vector3.forward);
            PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis (0, Vector3.forward);
            WalkingTime = 0;
        }
    }
}

对不起,代码量很多,但是唯一需要看的部分是键“ A”,“ W”,“ S”,“ D”和“ Void CmdWalk()”的“ IF语句”

谢谢。

1 个答案:

答案 0 :(得分:4)

import requests r = requests.get('https://intranet.jsondata.com/xy.json', auth=('user', 'pass')) json_content = r.json() 看到了动静,这让我感到惊讶。我只能说local Player可以看到它,因为

Host / Server Player

仅在服务器上执行。因此,实际上,主持人也应该已经可以看到其他客户端的动向。

无论如何将呼叫转接回所有客户,您都应该添加[Command] void CmdWalk() { //timer WalkingTime += Time.deltaTime; //right leg stepping forward if (WalkingTime > 0 && WalkingTime < .4) { PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x - (60 * WalkingTime), transform.TransformVector(1, 0, 0)); PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x + (60 * WalkingTime), transform.TransformVector(1, 0, 0)); } //left leg stepping forward if (WalkingTime > .4 && WalkingTime < 1.2) { PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x + (60 * (WalkingTime - .8f)), transform.TransformVector(1, 0, 0)); PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x - (60 * (WalkingTime - .8f)), transform.TransformVector(1, 0, 0)); } //right leg stepping forward if (WalkingTime > 1.2 && WalkingTime < 1.59) { PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x - (60 * (WalkingTime - 1.6f)), transform.TransformVector(1, 0, 0)); PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x + (60 * (WalkingTime - 1.6f)), transform.TransformVector(1, 0, 0)); } //resetting if (WalkingTime > 1.6) { PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(0, Vector3.forward); PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(0, Vector3.forward); WalkingTime = 0; } }

ClientRpc

更新

通常,这种方法的问题仍然是网络滞后。用户(如果不是主机的话)在呼叫被发送到服务器并返回给自己之前,不会看到自己的移动结果。因此,我还要在本地播放器上进行移动,并为他跳过Rpc调用:

[Command]
void CmdWalk()
{
    RpcWalk();
}

[ClientRpc]
void RpcWalk()
{
    //timer
    WalkingTime += Time.deltaTime;

    // also it is slightly more efficient to use if-else 
    // to avoid unneccesary checks since 
    // only one of those conditions can be true at a time

    //right leg stepping forward
    if (WalkingTime > 0 && WalkingTime < .4)
    {
        PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x - (60 * WalkingTime), transform.TransformVector(1, 0, 0));
        PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x + (60 * WalkingTime), transform.TransformVector(1, 0, 0));
    }

    //left leg stepping forward
    else if (WalkingTime > .4 && WalkingTime < 1.2)
    {
        PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x + (60 * (WalkingTime - .8f)), transform.TransformVector(1, 0, 0));
        PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x - (60 * (WalkingTime - .8f)), transform.TransformVector(1, 0, 0));
    }

    //right leg stepping forward
    else if (WalkingTime > 1.2 && WalkingTime < 1.59)
    {
        PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x - (60 * (WalkingTime - 1.6f)), transform.TransformVector(1, 0, 0));
        PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x + (60 * (WalkingTime - 1.6f)), transform.TransformVector(1, 0, 0));
    }

    //resetting
    else if (WalkingTime > 1.6)
    {
        PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(0, Vector3.forward);
        PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(0, Vector3.forward);
        WalkingTime = 0;
    }
}

并在void Walk() { //timer WalkingTime += Time.deltaTime; //right leg stepping forward if (WalkingTime > 0 && WalkingTime < .4) { PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x - (60 * WalkingTime), transform.TransformVector(1, 0, 0)); PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x + (60 * WalkingTime), transform.TransformVector(1, 0, 0)); } //left leg stepping forward else if (WalkingTime > .4 && WalkingTime < 1.2) { PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x + (60 * (WalkingTime - .8f)), transform.TransformVector(1, 0, 0)); PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x - (60 * (WalkingTime - .8f)), transform.TransformVector(1, 0, 0)); } //right leg stepping forward else if (WalkingTime > 1.2 && WalkingTime < 1.59) { PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x - (60 * (WalkingTime - 1.6f)), transform.TransformVector(1, 0, 0)); PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x + (60 * (WalkingTime - 1.6f)), transform.TransformVector(1, 0, 0)); } //resetting else if (WalkingTime > 1.6) { PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(0, Vector3.forward); PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(0, Vector3.forward); WalkingTime = 0; } if(!isLocalPlayer) return; // if executed by the local Player invoke the call on the server CmdWalk(gameObject); } // passing the GameObject reference over network works // since the player GameObject has a unique identity on all instances // namely the NetworkIdentity [Command] void CmdWalk(GameObject caller) { Walk(); RpcWalk(caller); } [ClientRpc] void RpcWalk(GameObject caller) { // skip if server since already done it in CmdWalk if(isServer) return; // skip if this is caller since already done locally if(caller == gameObject) return; Walk(); } 中使用

Update

代替