繁体   English   中英

使用 SocketIO 和 Unity Quest 2 vr 作为客户端和 Node.JS 作为服务器

[英]Using SocketIO with Unity Quest 2 vr as client and Node.JS as server

我和我的团队正在使用 C# 编写的 Unity 为 Quest 2 构建 VR 游戏。

我们有一个程序是用 JavaScript (Node.JS) 编写的服务器,它们的通信方式是通过 SocketIO。 在 Unity 编辑器中,两个应用程序都可以相互通信,但是当我尝试将应用程序构建为 APK 并将其加载到 Quest 2 时,服务器似乎无法与 VR 游戏通信。

关于我可以做些什么让他们互相交谈的任何建议? 这是我一直在使用的 NetworkManager 文件。

注意:文件中带有 SocketIO 的任何内容下方总是有一条红线,并显示“找不到类型或命名空间名称 'SocketIOCommunicator'(您是否缺少 using 指令或程序集引用?) [Assembly-CSharp]csharp(CS0246 )"

我不知道这意味着什么以及该怎么做。

using System;
using System.Collections;
using Firesplash.UnityAssets.SocketIO;
using Newtonsoft.Json;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using static PlayerManager;
using Classes.Managers;

namespace Network
{
    public class JoinRoom
    { 
        public string clinician;
    }
    public class StartGame
    {
        public string game;
    }

    public static class Pausing 
    {
        public static Boolean isPaused = false;
    }

    public class Position
    {
        public float xPos;
        public float zPos;
        public float yPos;
    }

    [RequireComponent(typeof(SocketIOCommunicator))]
    public class NetworkManager : MonoBehaviour
    {
        private SocketIOCommunicator _communicator;
        private SocketIOInstance _socket;
    
        [SerializeField] private TMP_InputField patientNameInput;
        [SerializeField] private TextMeshProUGUI patientName;
        [SerializeField] private TextMeshProUGUI clinicianName;
        [SerializeField] private GameObject setName;
        [SerializeField] private TextMeshProUGUI connText;
        private void Awake()
        { 
            DontDestroyOnLoad(this);
            _communicator = GetComponent<SocketIOCommunicator>();
            _socket = _communicator.Instance;
        }

        private void Start()
        {
            _socket.Connect();
            HandleServerEvents();
            StartCoroutine(PatientConnect());
        }

        private IEnumerator PatientConnect()
        {
            yield return new WaitUntil(() => _socket.IsConnected());
            FetchName();
        }


        private void FetchName()
        {
            if (PlayerPrefs.HasKey("PatientName"))
            {
                PlayerPrefs.SetString("PatientName", "Test Subject FetchName()");
                var name = PlayerPrefs.GetString("PatientName");
                Debug.Log("Has Name: " + name);
                _socket.Emit("unityConnect", name);
                patientName.SetText(name);
                SwitchToViewName();
            }
            else
            {
                SwitchToSetName();
            }
        }
        
        private void HandleServerEvents()
        {
             _socket.On("userJoined", (string payload) =>
            {
                Debug.Log("Joined Room!");
                var obj = JsonConvert.DeserializeObject<JoinRoom>(payload);
                Debug.Log(obj.clinician);
                clinicianName.SetText(obj.clinician);
                connText.gameObject.SetActive(true);
            });
             _socket.On("startGame", (string payload) =>
             {
                 Debug.Log("Started Game");
                 var obj = JsonConvert.DeserializeObject<StartGame>(payload);
                 Debug.Log(obj.game);
                 // connText.SetText("Started Planes");
                 switch(obj.game) {
                    case "3":
                        SceneManager.LoadScene("Planes");
                        break;
                    case "2":
                        SceneManager.LoadScene("Balloons");
                        break;
                    case "1":
                        SceneManager.LoadScene("Blocks");
                        break;
                    default:
                        SceneManager.LoadScene("Init");
                        break;
                 }
             });
             _socket.On("pauseGame", (string payload) => {
                GameplayManager.getManager().ResumeGame();
                Debug.Log("Unpaused");             
            });
             _socket.On("resumeGame", (string payload) => {
                GameplayManager.getManager().PauseGame();
                Debug.Log("Paused");
             });
             _socket.On("updateClientPosition", (string payload) => {
                 Debug.Log(payload);
                 var obj = JsonConvert.DeserializeObject<Position>(payload);
                 float y = obj.yPos;
                 float x = obj.xPos;
                 float z = obj.zPos;
                 movePlayerX(x);
                 movePlayerY(y);
                 movePlayerZ(z);
             });

            _socket.On("kickPatient", (string payload) => {
                Debug.Log(payload);
                SceneManager.LoadScene("Init");
            });

             _socket.On("handMirror", (string payload) => {
                Debug.Log(payload);
                switch (payload) {
                    case "LEFT":
                        CalibrationManager.getManager().SetCalibrationType(2);
                        CalibrationManager.getManager().SetUnaffectedController(OVRInput.Controller.LTouch);
                        break;
                    case "RIGHT":
                        CalibrationManager.getManager().SetCalibrationType(2);
                        CalibrationManager.getManager().SetUnaffectedController(OVRInput.Controller.RTouch);
                        break;
                    default:
                        CalibrationManager.getManager().SetCalibrationType(0);
                        break;
                }                
             });
        }
        
        private void OnDestroy()
        {
            _socket.Close();
        }

        public void SetPatientName()
        {
            
            PlayerPrefs.SetString("PatientName", patientNameInput.text);
            FetchName();
        }

        public void SwitchToSetName()
        {
            setName.SetActive(true);
            patientName.gameObject.SetActive(false);
        }

        private void SwitchToViewName()
        {
            setName.SetActive(false);
            patientName.gameObject.SetActive(true);
        }

    }
}

这是JS服务器文件

import express, { json } from "express";

const app = express();
import cors from "cors";

import http from "http";

const httpServer = http.createServer(app);

import { Server, Socket } from "socket.io";

import "./database";
import {
  addPatient,
  checkUserWithPassword,
  clearToken,
  deleteSession,
  getAllSessions,
  getSessionsByUsername,
  insertSession,
  removePatientFromSession,
} from "./database";
import { ISession } from "./ Models/ISession";
import { logout, validateToken } from "./auth";
import { generateUniqueId } from "./utils";
import { IUser } from "./ Models/IUser";

const port = 5000;

interface IStartGame {
  sessionKey: string;
  game: string;
}
const io = new Server(httpServer, {
  cors: {
    origin: "http://localhost:3000",
    methods: ["GET", "POST"],
  },
});

io.use(async (socket, next) => {
  const token = socket.handshake.headers.authorization;
  // const session = socket.handshake.headers.session;
  /*if (verifyToken(token)) {
        setTimeout(next, 1000);
    }*/
  next();
});

app.use(cors());
app.use(express.json());
app.use((req, res, next) => setTimeout(next, 1000));

app.post("/login", async (req, res) => {
  const params = req.body as IUser;

  checkUserWithPassword(params.username, params.shaPassword).then((token) => {
    if (token) {
      res.send({ success: true, token });
    } else {
      res.send({ success: false });
    }
  });
});

app.post("/logout", async (req, res) => {
  const token = req.headers.authorization;
  logout(token, () => {
    res.sendStatus(200);
  });
});

app.post("/loginWithToken", (req, res) => {
  const token = req.headers.authorization;
  validateToken(token, (success: boolean, user: IUser) => {
    if (success) {
      res.send({
        success: true,
        user,
      });
    } else {
      res.send({ success: false });
    }
  });
});

app.get("/sessions", (req, res) => {
  const cred = req.body.user as IUser;
  const token = req.headers.authorization;
  validateToken(token, (success: boolean, user: IUser) => {
    if (success) {
      getAllSessions()
        .then((sessions) => {
          res.send({ sessions });
        })
        .catch(() => {
          res.sendStatus(500);
        });
    } else {
      res.sendStatus(403);
    }
  });
});

app.post("/session", (req, res) => {
  const params = req.body as ISession;
  const token = req.headers.authorization;
  validateToken(token, (success: boolean, user: IUser) => {
    if (success) {
      getAllSessions().then((sessions: ISession[]) => {
        const id = generateUniqueId(
          5,
          sessions.map((s) => s.sessionKey)
        );
        insertSession({
          sessionName: params.sessionName,
          sessionKey: id,
          createdBy: user.username,
          patients: [],
        }).then((suc) => {
          if (suc) {
            res.send({ success: true });
          } else {
            res.sendStatus(500);
          }
        });
      });
    } else {
      res.sendStatus(403);
    }
  });
});
app.delete("/sessionDelete", (req, res) => {
  const params = req.body;
  const token = req.headers.authorization;
  validateToken(token, (success: boolean) => {
    if (success) {
      deleteSession(params.sessionKey);
      console.log(`Clinicain deleted session ${params.sessionKey}`);
      res.sendStatus(200);
    } else {
      res.sendStatus(403);
    }
  });
});



const unitySockets = {};
interface IUnitySocket {
  name: string;
  socket: Socket;
}

const addUnitySocket = (name: string, socket: Socket) => {
  unitySockets[socket.id] = {
    name,
    socket,
  };
};

io.on("connection", (socket) => {
  console.log(`Client ${socket.id} has connected`);
  socket.on("disconnect", () => {
    if (unitySockets[socket.id]) {
      unitySockets[socket.id].socket.disconnect();
      delete unitySockets[socket.id];
    }
    console.log(`Client ${socket.id} has disconnected`);
  });

  socket.on("unityConnect", (name: string) => {
    console.log(name + " joined unity");
    socket.join("waiting");
    addUnitySocket(name, socket);
  });
  socket.on("unityChangeName", (name: string) => {
    if (unitySockets[socket.id]) {
      unitySockets[socket.id].name = name;
    } else {
      addUnitySocket(name, socket);
    }
  });
  app.post("/startGame", (req, res) => {
    const params = req.body as IStartGame;
    console.log(params.sessionKey);
    console.log(params.game);
    socket.to(params.sessionKey).emit("startGame", { game: params.game });
    res.sendStatus(200);
  });
  app.patch("/pause", (req, res) => {
    const params = req.body;
    console.log("Clicked pause");
    if (params.isPaused) {
      socket.to(params.sessionKey).emit("resumeGame");
    } else {
      socket.to(params.sessionKey).emit("pauseGame");
    }
    res.sendStatus(200);
  });

  app.post("/updateClientPosition", (req, res) => {
    const params = req.body;
    console.log(params);
    socket.to(params.sessionKey).emit("updateClientPosition", params.value);
    res.sendStatus(200);
  });

  app.post("/handMirror", (req, res) => {
    const params = req.body;
    socket.to(params.sessionKey).emit("handMirror", params.hand);
    res.sendStatus(200);
  });

  app.delete("/removePatientFromSession", (req, res) => {
    const params = req.body;
    const token = req.headers.authorization;
    validateToken(token, (success: boolean) => {
      if (success) {
        removePatientFromSession(params.sessionKey, params.patientId);
        console.log(`Clinician kicked user ${params.patientId}`);
        socket.to(params.sessionKey).emit("kickPatient", params.patientId);
        res.sendStatus(200);
      } else {
        res.sendStatus(403);
      }
    });
  });

  app.post("/leaveAllRooms", (req, res) => {
    const rooms = io.sockets.adapter.sids[socket.id];
    console.log(rooms);
    // tslint:disable-next-line:forin
    for (const r in rooms) {
      socket.leave(r);
      console.log("left room " + r);
    }
    res.sendStatus(200);
  });
  app.post("/join", (req, res) => {
    const params = req.body as ISession;
    socket.join(params.sessionKey);
    console.log(`joined room ${params.sessionKey}`);
    socket.to(params.sessionKey).emit("userJoined");
    socket.emit("userJoined");
    res.send({ success: true });
  });
  app.get("/getWaitingClients", (req, res) => {
    const waitingSet = io.sockets.adapter.rooms.get("waiting");

    const retList = [];
    console.log(waitingSet);
    if (!waitingSet) {
      res.send({ waitingList: [] });
    } else {
      const waiting = Array.from(waitingSet);
      waiting.forEach((val) => {
        const unitySocket: IUnitySocket = unitySockets[val];
        if (unitySocket) {
          retList.push({
            name: unitySocket.name,
            socketId: val,
          });
        }
      });
      res.send({ waitingList: retList });
    }
  });
  app.get("/getPatientsInSession", (req, res) => {
    const roomKey = req.query.roomKey.toString();
    console.log("Get room " + roomKey);
    const roomSet = io.sockets.adapter.rooms.get(roomKey);
    if (roomSet) {
      const patients = Array.from(roomSet);
      const retList = [];
      patients.forEach((id) => {
        if (unitySockets[id]) {
          retList.push({
            name: unitySockets[id].name,
            socketId: id,
          });
        }
      });
      res.send({ patientList: retList });
    } else {
      res.send({ patientList: [] });
    }
  });
  app.post("/addClientsToSession", (req, res) => {
    const clientList = req.body.clientList;
    const roomKey = req.body.roomKey;
    const clinicianName = req.body.clinician;
    console.log("Add to room " + roomKey);
    clientList.forEach((id) => {
      if (unitySockets[id].socket) {
        unitySockets[id].socket.leave("waiting");
        unitySockets[id].socket.join(roomKey);
        unitySockets[id].socket.emit("userJoined", {
          clinician: clinicianName,
        });
      }
    });
    addPatient(clientList, roomKey);
    res.sendStatus(200);
  });
  app.post("/leave", (req, res) => {
    const params = req.body as ISession;
    socket.leave(params.sessionKey);
    console.log(`left room ${params.sessionKey}`);
    socket.to(params.sessionKey).emit("userLeft");
    socket.emit("userLeft");
    res.send({ success: true });
  });
});

httpServer.listen(port, () => {
  console.log(`server is listening on ${port}`);
});

Unity场景界面: Unity Scence

我找到了方法,我使用 heroku 来托管我的 node.js 服务器应用程序,然后不得不更改前端电子连接到 heroku 网站的方式。 统一任务游戏也是如此。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM