一、创建一个Unity项目OnlineGameClient并导入资源包
二、项目结构
三、代码
1、Manager包下
①AudioManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioManager : BaseManager {
public AudioManager(GameFacade facade) : base(facade) { }
}
②BaseManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//不需要继承MonoBehaviour,因为不需要作为组件存在,也不需要start和update方法
public class BaseManager : MonoBehaviour {
//每个类都包含一个GameFacade的引用,这样子类可以将facade作为中介调用各个manager
protected GameFacade facade;
public BaseManager(GameFacade facade)
{
this.facade = facade;
}
public virtual void OnInit() { }
public virtual void OnDestroy() { }
}
③CameraManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraManager : BaseManager {
public CameraManager(GameFacade facade) : base(facade) { }
}
④PlayerManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerManager : BaseManager {
public PlayerManager(GameFacade facade) : base(facade) { }
}
⑤RequestManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RequestManager : BaseManager {
public RequestManager(GameFacade facade) : base(facade) { }
}
2、Net包下
①ClientManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using System;
using Common;
//这个是用来管理和服务器端的socket连接
public class ClientManager : BaseManager {
public const string IP = "127.0.0.1";
private const int PORT = 6688;
private Socket clientSocket;
private Message msg = new Message();
//创建clientsocket和服务端建立连接
public override void OnInit()
{
base.OnInit();
clientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
try
{
clientSocket.Connect(IP, PORT);
}
catch (Exception e)
{
Debug.LogWarning("无法连接到服务器端,请检查您的网络!!"+e);
}
}
//开始监听
private void Start()
{
//开始接收
clientSocket.BeginReceive(msg.Data,msg.StartIndex,msg.RemainSize,SocketFlags.None, ReceiveCallback,null);
}
//消息的接收
private void ReceiveCallback(IAsyncResult ar)
{
try
{
int count = clientSocket.EndReceive(ar);
msg.ReadMessage(count, OnProcessDataCallback);
}
catch (Exception e)
{
Debug.Log(e);
}
}
private void OnProcessDataCallback(RequestCode requestCode,string data)
{
}
//发送请求
public void SendRequest(RequestCode requestCode,ActionCode actionCode,string data)
{
//进行数据的打包
byte[] bytes = Message.PackData(requestCode,actionCode,data);
//进行数据的发送
clientSocket.Send(bytes);
}
public override void OnDestroy()
{
base.OnDestroy();
try
{
clientSocket.Close();
}
catch (Exception e)
{
Debug.LogWarning("无法关闭跟服务器端的连接!!" + e);
}
}
}
②Message
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using Common;
using System.Text;
using System.Linq;
public class Message {
private byte[] data = new byte[1024]; //定义一个数组用来存取数据,数组的长度要保证可以存下所有的消息
private int startIndex = 0; //表示存取了多少个字节的数据在数组里面
//public void AddCount(int count) //提供一个增加数量的方法
//{
// startIndex += count;
//}
public byte[] Data //提供一个返回data数组的方法
{
get { return data; }
}
public int StartIndex
{
get { return startIndex; }
}
public int RemainSize
{
get { return data.Length - startIndex; } //剩余的空间
}
public void ReadMessage(int newDataAmount, Action<RequestCode, string> processDataCallBack) //解析数据
{
startIndex += newDataAmount;
while (true)
{
if (startIndex <= 4)
return;
int count = BitConverter.ToInt32(data, 0); //获取数据的长度,从索引为0的位置开始读取4个字节
if (startIndex - 4 >= count) //前四个字节是数据的长度,如果减去长度大于数据字节长度,则表示数据可以被完整地保存
{
//string s = Encoding.UTF8.GetString(data,4,count);
//Console.WriteLine("解析 :" + s );
//Array.Copy(data, count + 4, data, 0, startIndex - 4-count );
//startIndex -= (count + 4);
//解析RequestCode从4的位置开始解析
RequestCode requestCode = (RequestCode)BitConverter.ToInt32(data, 4);
//解析ActionCode从8的位置开始解析
ActionCode actionCode = (ActionCode)BitConverter.ToInt32(data, 8);
//解析数据,从第12个字节开始,数据长度是count-8
string s = Encoding.UTF8.GetString(data, 8, count - 4);
//解析完成后调用一下回调
processDataCallBack(requestCode, s);
Array.Copy(data, count + 4, data, 0, startIndex - 4 - count);
startIndex -= (count + 4);
}
else //数据不完整
{
break;
}
}
}
//数据的包装
public static byte[] PackData(RequestCode requestCode, ActionCode actionCode,string data)
{
//requestCode的字节数组
byte[] requestCodeBytes = BitConverter.GetBytes((int)requestCode);
//actionCode的字节数组
byte[] actionCodeBytes = BitConverter.GetBytes((int)actionCode);
//数据的字节数组
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
//requestcode、actioncode和数据的长度
int dataAmount = requestCodeBytes.Length + dataBytes.Length+ actionCodeBytes.Length;
//所有长度的字节数组
byte[] dataAmountBytes = BitConverter.GetBytes(dataAmount);
//进行组装
return dataAmountBytes.Concat(requestCodeBytes).ToArray<byte>()
.Concat(actionCodeBytes).ToArray<byte>()
.Concat(dataBytes).ToArray<byte>();
}
}
3、Request包下
① BaseRequest
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Common;
public class BaseRequest : MonoBehaviour {
private RequestCode requestCode = RequestCode.None;
public virtual void Awake()
{
}
}
4、Scripts下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameFacade : MonoBehaviour {
private UIManager uiMng;
private AudioManager audioMng;
private PlayerManager playerMng;
private CameraManager cameraMng;
private RequestManager requestMng;
private ClientManager clientMng;
// Use this for initialization
void Start () {
InitManager();
}
// Update is called once per frame
void Update () {
DestroyManager();
}
//创建和初始化
private void InitManager()
{
uiMng = new UIManager(this);
audioMng = new AudioManager(this);
playerMng = new PlayerManager(this);
cameraMng = new CameraManager(this);
requestMng = new RequestManager(this);
clientMng = new ClientManager();
uiMng.OnInit();
audioMng.OnInit();
playerMng.OnInit();
cameraMng.OnInit();
requestMng.OnInit();
clientMng.OnInit();
}
private void DestroyManager()
{
uiMng.OnDestroy();
audioMng.OnDestroy();
playerMng.OnDestroy();
cameraMng.OnDestroy();
requestMng.OnDestroy();
clientMng.OnDestroy();
}
}
注:
游戏客户端架构
2.使用共享项目的文件
①在共享项目上点击鼠标右键“生成”
②在文件资源管理器中打开文件夹
③在目录G:\games\conglin\use socket tcp to develope games\Common\bin\Debug\netstandard1.4下可以看到Common.dll文件
④然后放到所需要引用的地方
⑤
⑥
⑦
3、错误:Plugin targets .NET 4.x and is marked as compatible with Editor,Editor can oly use assemblies targeting .NET 3.5 or lower,please unselect Editor as compatible platform.
原因:.dll版本太高了,unity只支持3.5版本之下的
解决办法:项目的类库应该选择.NET Framework,目标框架改为2.0以下再重新生成