【发布时间】:2021-10-17 04:01:05
【问题描述】:
我遇到了以下奇怪的情况,每当玩家生成时,以前的玩家可以从服务器接收到生成事件并能够生成新玩家,但他们无法更新新玩家位置。
奇怪的是,新玩家可以追踪老玩家的位置,而老玩家却无法追踪新玩家的更新位置。
我一直在调试,我注意到我在旧播放器客户端中保存“serverObjects”(播放器)的
这是 NetworkClient.cs(统一)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SocketIO;
using System;
public class NetworkClient : SocketIOComponent
{
[Header("Network Client")]
[SerializeField]
private Transform networkContainer;
[SerializeField]
private GameObject playerPrefab;
[SerializeField]
private Dictionary<string, NetworkIdentity> serverObjects;
public static string ClientID {get; private set;}
public override void Start() {
base.Start();
initialize();
SetupEvents();
}
private void initialize(){
serverObjects = new Dictionary<string, NetworkIdentity>();
}
public override void Update() {
base.Update();
On("close", (e) => {
Debug.Log("Se ha desconectado del servidor");
});
}
private Vector3 decryptPos(string pos){
var positions = new string[3];
positions = pos.Split(':');
//Debug.Log("Soy el possss");
Debug.Log(pos);
float x = float.Parse(positions[0]) ;
float y = float.Parse(positions[1]) ;
float z = float.Parse(positions[2]) ;
Vector3 pos3d = new Vector3(x,y,z);
return pos3d;
}
private void SetupEvents() {
On("open", (e) => {
Debug.Log("Conexión realizada con el servidor");
});
On("register", (e) => {
ClientID = e.data["id"].ToString();
//Debug.LogFormat("Nuestro Cliente tiene ID ({0})", ClientID);
});
On("spawn", (e) => {
string id = e.data["id"].ToString();
GameObject go = Instantiate(playerPrefab, networkContainer);
NetworkIdentity ni = go.GetComponent<NetworkIdentity>();
if(ClientID != id){
//En el caso de que está recibiendo el spawn de otro player
var debug = string.Format("Otro Player ({0})", id);
//Debug.Log(debug);
// Debug.Log(e);
//Debug.Log("Está spawneando otro player!!");
go.name = string.Format("Other Player ({0})", id);
//Getting and setting the position of the other player
string pos = e.data["encodedPosition"].str;
Vector3 position = decryptPos(pos);
go.transform.position = position;
ni.SetControllerID(id);
ni.SetSocketReference(this);
serverObjects.Add(id,ni);
} else {
//Debug.Log("Estoy espawneando :OO");
go.name = string.Format("Player ({0})", id);
ni.SetControllerID(id);
ni.SetSocketReference(this);
serverObjects.Add(id, ni);
}
ni = null;
});
On("updatePosition", (e) => {
string id = e.data["id"].ToString();
Debug.Log("SOY EL DATA QUE VIENE DEL SERVER");
//Debug.Log(e.data["encodedPosition"]);
var pos = e.data["encodedPosition"].str;
var positions = new string[3];
positions = pos.Split(':');
///Debug.Log("Soy el possss");
//Debug.Log(positions[0] +"|||"+positions[1]+"|||"+positions[2]);
float x = float.Parse(positions[0]) ;
float y = float.Parse(positions[1]) ;
float z = float.Parse(positions[2]) ;
//Debug.Log("Soy el possss22222");
//Debug.Log(x +"|-|-|"+y+"|-|-|"+z);
foreach (var item in serverObjects)
{
Debug.Log(item);
}
if(!serverObjects[id]){
} else {
NetworkIdentity ni = serverObjects[id];
}
Debug.LogFormat("Server Object: {0}", serverObjects[id]);
Vector3 posi = new Vector3(x,y,z);
ni.transform.position = posi;
Debug.Log("Soy el ultimate position...");
Debug.Log(posi);
});
On("disconnected", (e) => {
string id = e.data["id"].ToString();
GameObject go = serverObjects[id].gameObject;
Destroy(go); //Removiendo al jugador de la partida
serverObjects.Remove(id); // Removiendolo de memoria
});
}
}
这是 NetworkIdentity.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SocketIO;
public class NetworkIdentity : MonoBehaviour
{
[Header("Helpful Values")]
[SerializeField]
[GreyOut]
private string id;
[SerializeField]
[GreyOut]
private bool isControlling;
private SocketIOComponent socket;
void Awake()
{
isControlling = false;
}
public void SetControllerID (string ID){
id = ID;
isControlling = (NetworkClient.ClientID == ID) ? true: false; //Verifica si la id que viene pertenece al player o es de otro (para definir quien controla el personaje)
}
public void SetSocketReference(SocketIOComponent Socket){
socket = Socket;
}
public string GetID(){
return id;
}
public bool IsControlling(){
return isControlling;
}
public SocketIOComponent GetSocket(){
return socket;
}
}
这是 NetworkTransform.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
[RequireComponent(typeof(NetworkIdentity))]
public class NetworkTransform : MonoBehaviour
{
[SerializeField]
[GreyOut]
private Vector3 oldPosition;
private NetworkIdentity networkIdentity;
private Player player;
private float stillCounter = 0f;
void Start()
{
networkIdentity = GetComponent<NetworkIdentity>();
oldPosition = transform.position;
player = new Player();
player.position = new Position();
player.position.x = 0;
player.position.y = 0;
player.position.z = 0;
player.id = networkIdentity.GetID().Trim( new Char[] { '"' } );
if(!networkIdentity.IsControlling()){
//enabled = false; //Turn off the script if not own player
}
}
void Update()
{
if(networkIdentity.IsControlling()){
if(oldPosition != transform.position){
oldPosition = transform.position;
stillCounter = 0f;
sendData();
} else {
stillCounter += Time.deltaTime;
if(stillCounter >= 1f){
stillCounter = 0f;
sendData();
}
}
}
}
private void sendData(){
//Actualiza la información del player y la manda al server
player.position.x = (float)Math.Round(transform.position.x,3);
player.position.y = (float)Math.Round(transform.position.y,3);
player.position.z = (float)Math.Round(transform.position.z,3);
player.encodePosition();
var encodedJSONPos = player.toJSON();
//Debug.Log("Soy la posicion del playersino: ");
//Debug.Log(encodedJSONPos);
networkIdentity.GetSocket().Emit("updatePosition", encodedJSONPos );
}
}
这是 Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
[Serializable]
public class Player
{
public string username;
public string id;
public Position position;
public EncodedPlayerMovement encodedPlayerMovement = null;
public void encodePosition (){
this.encodedPlayerMovement = new EncodedPlayerMovement();
//Saving the id
this.encodedPlayerMovement.id = this.id;
//Saving the encoded position
//var debug = string.Format("Soy la posicion antes de ser codificada: x: ({0}) y: ({1}) z: ({2}) ", position.x, position.y, position.z);
//Debug.Log(debug);
var encodedPos = position.x+":"+position.y+":"+position.z;
encodedPos = encodedPos.Replace(",",".");
this.encodedPlayerMovement.encodedPosition = encodedPos;
//Debug.Log("Soy la posicion despues de ser codificada");
//Debug.Log(encodedPos);
}
public JSONObject toJSON() {
var jsonPlayer = this;
//return new JSONObject(JsonUtility.ToJson(this));
return new JSONObject(JsonUtility.ToJson(this.encodedPlayerMovement));
}
}
[Serializable]
public class EncodedPlayerMovement {
public string id;
public string encodedPosition;
}
这是 PlayerManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerManager : MonoBehaviour
{
[Header("Data")]
[SerializeField]
private float speed = 4f;
[Header("Class Reerences")]
[SerializeField]
private NetworkIdentity networkIdentity;
void Update()
{
if(networkIdentity.IsControlling()){
checkMovement();
}
}
private void checkMovement(){
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
transform.position += new Vector3(horizontal, 0f, vertical) * speed * Time.deltaTime;
}
}
这是nodejs中服务器代码的index.js
var io = require('socket.io')(process.env.PORT || 52300);
//Custom classes
var Player = require('./classes/Player');
console.log('Server has started');
var players = [];
var sockets = [];
io.on('connection', (socket) => {
console.log('Conexión realizada!');
var player = new Player();
var thisPlayerID = player.id;
players[thisPlayerID] = player;
sockets[thisPlayerID] = socket;
socket.emit('register', {id: thisPlayerID}); //Avisarle al cliente cual es su id en el servidor mediante un objeto json (no es necesario json.stringify pues se hace automatico)
socket.emit('spawn', player) //Avisa al player actual que ha spawneado
socket.broadcast.emit('spawn', player) //Avisa a los demas que el player actual ha spawneado (avisa a todos menos al player actual)
//Avisar al player actual sobre todos los demas players conectados en el servidor (no se avisa sobre si mismo)
for(var playerID in players) {
if(playerID !== thisPlayerID){
socket.emit('spawn', players[playerID]);
}
}
//Evento de positional data from player
socket.on('updatePosition', (data) => {
console.log("soy el data");
console.log(data);
var deserializePos = data.encodedPosition;//.encodedPosition;
var position = deserializePos.split(':');
console.log("ANTES DE TODO: Estoy recibiendo los cambios de posición del player... El player debe emitirse a los demas jugadores...");
console.log(position)
var x = parseFloat(position[0]);
var y = parseFloat(position[1]);
var z = parseFloat(position[2]);
console.log("ANTES DE ENCODE: Estoy recibiendo los cambios de posición del player... El player debe emitirse a los demas jugadores...");
console.log(x,y,z)
player.position.x = x;
player.position.y = y;
player.position.z = z;
player.EncodePosition();
console.log("DESPUES DE ENCODE: Estoy recibiendo los cambios de posición del player... El player debe emitirse a los demas jugadores...");
console.log(player)
//Avisarle a los demas que el player actual ha cambiado su posicion (se envia objeto player con la data)
socket.broadcast.emit('updatePosition', player);
});
socket.on('disconnect', () => {
console.log("Un jugador se ha desconectado...");
delete players[thisPlayerID];
delete sockets[thisPlayerID];
socket.broadcast.emit('disconnected', player);
});
});
最后是我的场景的图像...... Scene
我应该怎么做才能防止这个错误?
【问题讨论】:
-
我认为这需要minimal reproducible example。
-
也许与该项目的回购可以工作?
-
不,我认为您应该阅读链接。问题是这是一个庞大的代码量,而且鉴于这里的人免费帮助您,如果您努力将问题缩小到更易于消化的代码大小,您将更有可能获得答案.很少有人会投入精力来阅读和解决这么多代码,因为这需要大量时间。 StackOverflow 的目的不是为您的问题找到帮助,而是为未来的读者构建一个具有持久价值的问题库。这个问题没有那样做。
-
谢谢 J... 我会尽力按照链接说明缩小问题范围,感谢您的指导!
标签: c# node.js unity3d networking socket.io