所以,我正在开发一个Unity项目,我需要在其中实现客户端/服务器功能。
客户端有自己的“场景”,服务器也有自己的场景。服务器代码和networkView将附加到其场景中的主摄像头。代码如下:
using UnityEngine;
using System.Collections;
using System.Net;
using System.Collections.Generic;
public class NetworkManagerCS : MonoBehaviour {
public int loadlevel;
public int connectPort = 25000;
public string hostname;
public string GameName = "Historical Grounds";
private bool refreshing;
private HostData[] hostData;
private Dictionary<string, string> playerList = new Dictionary<string, string>();
string textToEdit = "Type text here";
// This is for debuggin purposes only!! Will be deprecated
public void OnGUI() {
if (Network.peerType == NetworkPeerType.Disconnected) {
GUILayout.Label("Connection status: Disconnected");
GUILayout.BeginVertical();
if (GUILayout.Button("Connect as client"))
{
ConnectToServer();
}
if (GUILayout.Button("Start Server"))
{
Network.InitializeServer(4, connectPort, true);
MasterServer.RegisterHost(GameName, "Tutorial Game", "This is a turn based shooter");
//Network.Instantiate(camera, transform.position, transform.rotation, 0);
}
GUILayout.EndVertical();
}
else
{
// Connecting...
if (Network.peerType == NetworkPeerType.Connecting)
{
GUILayout.Label("Connection status: Connecting");
}
// Clientside buttons
else if (Network.peerType == NetworkPeerType.Client)
{
GUILayout.Label("Connection status: Client!");
GUILayout.Label("Ping to server: " + Network.GetAveragePing(Network.connections[0]));
textToEdit = GUILayout.TextField(textToEdit, 25);
if( GUILayout.Button("Attack Server")) {
float[] args = new float[3];
args[0] = float.Parse(textToEdit);
args[1] = 4.123f;
args[2] = 23.2f;
networkView.RPC("AttackServer", RPCMode.AllBuffered, args);
}
}
// Serverside
else if (Network.peerType == NetworkPeerType.Server)
{
GUILayout.Label("Connection status: Server!");
GUILayout.Label("Hostname is:" + System.Net.Dns.GetHostName() );
GUILayout.Label("Connections: " + Network.connections.Length);
}
// Disconnect happens in both server and client
if (GUILayout.Button("Disconnect"))
{
Network.Disconnect(200);
}
}
}
// AKA While(true)
public void Update() {
/*
* If we have a "refreshing" flag, then we poll the master server
* until we get a length larger than 0. Then, we connect to server.
*/
if(refreshing) {
if (MasterServer.PollHostList().Length > 0) {
refreshing = false;
Debug.Log(MasterServer.PollHostList().Length);
hostData = MasterServer.PollHostList();
ConnectToServer();
}
}
}
/*
* If hostData does not exist, refresh
* Otherwise, connect to the first game you see.
*
* This is the "dumb" approach, but I assume that there are not going to be more
* than one game running at a time...
*/
public void ConnectToServer() {
if (hostData == null) {
MasterServer.RequestHostList(GameName);
refreshing = true;
} else {
Network.Connect(hostData[0]);
}
}
/*
* Keeping this here so that I will remember to add system info sends
*/
public void OnConnectedToServer()
{
//Application.LoadLevel(loadlevel);
}
/*
* DEBUG FUNCTION!!! This will be called when someone disconnected from
* the msater server
*/
public void OnDisconnectedFromServer(NetworkDisconnection info) {
if (info == NetworkDisconnection.LostConnection) {
if (Network.peerType == NetworkPeerType.Client) {
Debug.Log ("Client has lost connection");
} else {
Debug.Log ("Server has lost connection");
}
} else {
Debug.Log ("Disconnected Successfully");
}
}
/*
* Lawl, fail....
*/
public void OnFailedToConnect(NetworkConnectionError error)
{
Debug.LogError(error.ToString());
Network.Disconnect(400);
}
/*
* The purpose of this function is to assign a monster to a player
* Once all monsters have been assigned, I guess the Update() function will
* RPC to the phones that they are ready to play.
*/
public void OnPlayerConnected(NetworkPlayer player) {
networkView.RPC("assignPlayer", RPCMode.All, player);
}
/*
* Not interesting... Server initialized..
*/
public void OnServerInitialized()
{
//Application.LoadLevel(loadlevel);
Debug.Log("Server Started");
}
void OnMasterServerEvent(MasterServerEvent msg) {
if (msg == MasterServerEvent.RegistrationSucceeded){
Debug.Log("Registered Server!");
Network.isMessageQueueRunning = true;
}
}
/*void OnPlayerDisconnected(NetworkPlayer player) {
Transform playerTransform = GameObject.Find("Player_" + player.guid);
if (playerTransform != null) {
Destroy (playerTransform.gameObject);
}
Network.RemoveRPCs(player);
Network.DestroyPlayerObjects(player);
}*/
// Testers - Should deprecate
/*[RPC]
public void AttackServer(float[] args) {
foreach (float value in args) {
Debug.Log ("Server is under attack with force " + value);
}
}*/
// RPC's Server Side
[RPC]
public void sendLifeCount(NetworkPlayer player) {
Debug.Log("Sending Life Count to " + player.ipAddress);
}
[RPC]
public void isDead(NetworkPlayer player) {
Debug.Log("You're dead! " + player.ipAddress);
}
[RPC]
public void unlockScreen(NetworkPlayer player) {
Debug.Log("Unlocking screen for.." + player.ipAddress);
}
[RPC]
public void assignPlayer(NetworkPlayer player) {
playerList.Add(player.guid, "1");
Debug.Log(playerList[player.guid]);
Debug.Log("Player connected from: " + player.ipAddress + ":" + player.port);
Debug.Log("The player on IP " + player.ipAddress + " has been assigned the x monster");
}
public Object networkprefab { get; set; }
}
另一方面,客户端在另一个场景中,其代码在这里:(由于问题没有附加networkView ......
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Text.RegularExpressions;
public center code herelass InputField : MonoBehaviour {
// Client-server bullshit
private int loadlevel;
private HostData[] hostData;
private bool refreshing;
public string GameName = "Historical Grounds";
private bool connected;
public Canvas mainCanvas;
public Canvas gameCanvas;
public Button Connect;
public Text nameFieldInput;
public Text nameField;
public Text Error;
private string userName;
void Awake()
{
if (connected)
{
mainCanvas.enabled = false;
gameCanvas.enabled = true;
}
else {
mainCanvas.enabled = true;
gameCanvas.enabled = false;
}
Debug.Log(connected);
}
public void Update()
{
/*
* If we have a "refreshing" flag, then we poll the master server
* until we get a length larger than 0. Then, we connect to server.
*/
if (refreshing)
{
if (MasterServer.PollHostList().Length > 0)
{
refreshing = false;
Debug.Log(MasterServer.PollHostList().Length);
hostData = MasterServer.PollHostList();
ConnectToServer();
}
}
}
public void onConnect()
{
ConnectToServer();
}
public void OnConnectedToServer()
{
var viewID = Network.AllocateViewID();
}
public void ConnectToServer()
{
if (hostData == null)
{
MasterServer.RequestHostList(GameName);
refreshing = true;
}
else
{
if (Switch())
{
connected = true;
Network.Connect(hostData[0]);
}
}
}
private bool Switch(){
userName = nameFieldInput.text;
Debug.Log(userName);
if(Validate(userName)){
nameField.text = userName;
mainCanvas.enabled = false;
gameCanvas.enabled = true;
connected = true;
return true;
} else {
Error.text = "Invalid name!" + "\n" + "Name should be 2-8 characters and start with a capital letter";
return false;
}
}
private bool Validate(string input){
string pattern = @"^[A-Z][A-Za-z0-9][A-Za-z0-9]+";
Match match = Regex.Match(input, pattern);
if (match.Success)
{
return true;
}
return false;
}
public void OnDisconnectedFromServer(NetworkDisconnection info)
{
if (info == NetworkDisconnection.LostConnection)
{
if (Network.peerType == NetworkPeerType.Client)
{
Debug.Log("Client has lost connection");
}
else
{
Debug.Log("Server has lost connection");
}
}
else
{
Debug.Log("Disconnected Successfully");
}
}
public void OnFailedToConnect(NetworkConnectionError error)
{
Debug.LogError(error.ToString());
Debug.Log("FAIL!");
}
public void OnDisconnectedFromServer()
{
connected = false;
Debug.Log("Lawl Disconnected");
}
}
TL; DR:我在尝试从客户端向服务器调用RPC(fire()
)时不断收到该错误消息。谁知道为什么?
谢谢!