Unity教程之-Unity3d内置网络Network之授权服务器案例

 

上一篇文章Unity教程之-Unity3d内置网络Network之非授权服务器实例

我们学习了非授权服务器的实例,那么接下来我们来学习下Unity3d内置网络Network之授权服务器案例,下面我们开始!

新建一个场景,创建一个Plane物体命名为Ground,创建一个空物体命名为Spawn,创建一束方向光用于照亮整个场景,如图:


从Unity3D官方教程(Steal,即秘密潜如)素材包中导入主角模型和Idle动画和Walk动画,(素材地址:点击打开链接),为主角添加动画控制器,Rigidbody组件,NetworkView组件和BoxCollider组件,(脚本组件稍后讲解)并将主角保存为预制体(prefab)如图:




创建三个脚本Server,Client和PlayerCtrl,将Server脚本和Client脚本添加到主相机,如图:


将PlayerCtrl脚本添加到主角人物中,如图:


各个脚本代码如下:

Server代码:


using UnityEngine;
using System.Collections;

public class Server : MonoBehaviour
{
private int connectionNum = 15;
private int listenPort = 10000;
private bool useNAT = false;

public GameObject playerPrefab;            //新建的目标对象
public GameObject spawn;                   //玩家产生的位置
public ArrayList list = new ArrayList();   //用于存储玩家的PlayerCtrl脚本组件

void OnGUI()
{
switch (Network.peerType)
{
case NetworkPeerType.Disconnected:
if (GUI.Button(new Rect(10, 10, 200, 40), "Create the server"))
{
Network.incomingPassword = "UnityNetwork";
Network.InitializeServer(connectionNum, listenPort, useNAT);
}
break;
case NetworkPeerType.Server:
GUILayout.Label("Initailize server is successful");
GUILayout.Label("There are the clients that connecte to the server");
for (int i = 0; i < Network.connections.Length; i++)
{
GUILayout.Label("client's IP is: " + Network.connections[i].ipAddress);
GUILayout.Label("client's Port is: " + Network.connections[i].port);
}
if (GUILayout.Button("close the connection"))
{
Network.Disconnect(200);
}
break;
default:
break;
}
}

//实例化服务器玩家
void OnServerInitialized()                   //服务端调用
{
InitPlayer(Network.player);
}

//实例化客户端玩家
public void OnPlayerConnected(NetworkPlayer player)                        //服务端调用
{
InitPlayer(player);
}

//玩家断开连接时
public void OnPlayerDisconnected(NetworkPlayer player)
{
foreach (PlayerCtrl pctrl in list)
{
if (pctrl.ownPlayer == player)
{
Network.RemoveRPCs(pctrl.gameObject.networkView.viewID);
Network.Destroy(pctrl.gameObject);
list.Remove(pctrl);
break;
}
}

int playerID = int.Parse(player.ToString());
Network.RemoveRPCs(player, playerID);
Network.RemoveRPCs(player);
Network.DestroyPlayerObjects(player);   //服务端调用
}

void InitPlayer(NetworkPlayer player)
{
int playerID = int.Parse(player.ToString());          //获取玩家ID

GameObject goPlayer = Network.Instantiate(playerPrefab, spawn.transform.position, spawn.transform.rotation, playerID) as GameObject;

list.Add(goPlayer.GetComponent<PlayerCtrl>());

//设置每个玩家对象的NetworkPlayer标示
goPlayer.GetComponent<NetworkView>().RPC("SetPlayer", RPCMode.AllBuffered, player);
}

}

Client代码如下:


using UnityEngine;
using System.Collections;

public class Client : MonoBehaviour
{
private string remoteIP = "127.0.0.1";
private int remotePort = 10000;
private string passWord = "UnityNetwork";

void OnGUI()
{
switch (Network.peerType)
{
case NetworkPeerType.Disconnected:
if (GUI.Button(new Rect(Screen.width / 2 + 10, 10, 200, 40), "connecte to the server"))
{
Network.Connect(remoteIP, remotePort, passWord);
}
break;
case NetworkPeerType.Connecting:
GUI.Label(new Rect(Screen.width / 2 + 10, 10, 200, 40), "connecting....");
break;
case NetworkPeerType.Client:
GUI.Label(new Rect(Screen.width / 2 + 10, 10, 200, 40), "connection is successful");
if (GUI.Button(new Rect(Screen.width / 2 + 10, 60, 200, 40), "Close the connection"))
{
Network.Disconnect(200);
}
break;
default:
break;
}
}

public void OnDisconnectedFromServer(NetworkDisconnection info)
{
Application.LoadLevel(Application.loadedLevel);
}
}

PlayerCtrl代码如下:


using UnityEngine;
using System.Collections;

public class PlayerCtrl : MonoBehaviour
{
public NetworkPlayer ownPlayer;                //每个玩家的NetworkPlayer标示

public float rotationSpeed = 15f;              //玩家转身速度

private Animator anim;

//客户端存储的输入值
private float clientHInput = 0f;
private float clientVInput = 0f;

//服务端存储的输入值
private float serverHInput = 0f;
private float serverVInput = 0f;

//游戏对象当前状态
private float currentHInput = 0f;
private float currentVInput = 0f;

void Awake()
{
anim = GetComponent<Animator>();
if (Network.isClient)
{
enabled = false;
}
}

void Update()
{
if (Network.player == ownPlayer)
{
currentHInput = Input.GetAxis("Horizontal");
currentVInput = Input.GetAxis("Vertical");

if (currentHInput != clientHInput || currentVInput != clientVInput)
{
clientVInput = currentVInput;
clientHInput = currentHInput;

if (Network.isServer)
{
SendInput(currentHInput, currentVInput);
}
else
if (Network.isClient)
{
networkView.RPC("SendInput", RPCMode.Server, currentHInput, currentVInput);
}
}
}

if (Network.isServer)
{
if (serverHInput != 0 || serverVInput != 0)
{
WalkState(serverHInput, serverVInput);
}
else
{
IdleState();
networkView.RPC("SetFloat", RPCMode.OthersBuffered, 0f);
}
}
}

void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
{
if (stream.isWriting)                //发送数据
{
Vector3 pos = rigidbody.position;
Quaternion rota = rigidbody.rotation;
Vector3 veloc = rigidbody.velocity;
Vector3 angVeloc = rigidbody.angularVelocity;

stream.Serialize(ref pos);
stream.Serialize(ref rota);
stream.Serialize(ref veloc);
stream.Serialize(ref angVeloc);
}
else                              //接受数据
{
Vector3 pos = Vector3.zero;
Quaternion rota = Quaternion.identity;
Vector3 veloc = Vector3.zero;
Vector3 angVeloc = Vector3.zero;
}
}

[RPC]
void SendInput(float currentHInput, float currentVInput)
{
serverHInput = currentHInput;
serverVInput = currentVInput;
}

void WalkState(float serverHInput, float serverVInput)
{
anim.SetFloat("Speed", 0.2f);
networkView.RPC("SetFloat", RPCMode.OthersBuffered, 0.2f);
Vector3 dir = new Vector3(serverHInput, 0, serverVInput);
Quaternion look = Quaternion.LookRotation(dir, transform.up);
transform.rotation = Quaternion.Lerp(transform.rotation, look, rotationSpeed * Time.deltaTime);
}

[RPC]
void IdleState()
{
anim.SetFloat("Speed", 0f);
}

[RPC]
void SetFloat(float speed)
{
anim.SetFloat("Speed", speed);
}

[RPC]
void SetPlayer(NetworkPlayer player)
{
ownPlayer = player;
if (player == Network.player)
{
enabled = true;
}
}
}

将游戏发布,测试,如图:


成功,OK!好了,本节unity教程到此结束!