NetWork学习小结
1.首先是服务器代码:
using UnityEngine;
using System.Collections;
/// <summary>
/// 1.服务器函数实现功能
/// 2.该函数里的一些功能函数是系统自己在条件满足的时候,自己调用,不需要我们通过代码来调用,我们只
/// 需要把功能添加好就可以了,简单的说相当远OnUpdate一样,都是系统自己调用的,不受我们支配
/// 例如OnServerInitialized()、OnPlayerConnected()、OnPlayerDisconnected()这写都是的
/// 3.服务端只画出Create the server,但前提是服务器还没有创建
/// </summary>
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);//第二个参数是把player信息放在缓冲池中,这样要是有新的玩家来了,可以看到之前玩家的状态信息
}
}
2.客户端代码
using UnityEngine;
using System.Collections;
/// <summary>
/// 客户端只在ui上面画connecte to the server按钮当按钮点击的时候按钮会改变成为Close the connection按钮,
/// 给玩家很好的体验
/// </summary>
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);
}
}
3.人物控制脚本
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 = true;//当是客户端的时候,不能对服务器端的人控制
}
}
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);//改变serverHInput,serverVInput的值,来实现移动
}
else if (Network.isClient) //是否是客户端
{
networkView.RPC("SendInput", RPCMode.Server, currentHInput, currentVInput);//改变serverHInput,serverVInput的值,来实现移动
}
}
}
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;
}
}
}
浙公网安备 33010602011771号