原文:http://my.oschina.net/faint/blog/296785
第一部分 dll
1 下面大多数内容,都是使用c#编译的dll来实现的。
2 编译为dll后,要拖放到unity3d的Assets里面,才能using到。
3 有以下类似错误,就是使用了非.net 2.0编译的dll。注意项目必须是在.net 2.0版本编译的才能正常在unity3d当中使用。
Unhandled Exception: System.TypeLoadException: Could not load type 'System.Runtime.Versioning.TargetFrameworkAttribute' from assembly 'MyModel'
4 应该不能用MonoDevelop编译下面会提到的Serializer部分(编译不出dll,会报错)。需用vs编译。
第二部分 tcp/ip
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
using System;
using System.IO;
using System.Net.Sockets;
namespace TcpConnector{
public struct Msg {
public int Type;
public int Size;
public byte[] Content;
}
public class Connector{
const int HEAD_SIZE = 4;
private TcpClient client;
NetworkStream stream;
public bool Connect(string ip,int port){
try{
client = new TcpClient(ip,port);
stream = client.GetStream();
return true;
}
catch{
return false;
}
}
public void Disconnect(){
stream.Close();
client.Close();
}
private int readType(){
byte[] headData = new byte[HEAD_SIZE];
stream.Read(headData,0,headData.Length);
int msgType = BitConverter.ToInt32(headData,0);
return msgType;
}
private int readSize(){
byte[] headData = new byte[HEAD_SIZE];
stream.Read(headData,0,headData.Length);
int msgSize = BitConverter.ToInt32(headData,0);
return msgSize;
}
private byte[] readContent(int leghth){
byte[] content = new byte[leghth];
stream.Read(content,0,content.Length);
return content;
}
public Msg Read(){
Msg msg = new Msg();
msg.Type = readType();
msg.Size = readSize();
if (msg.Size > 0) {
msg.Content = readContent(msg.Size);
}
return msg;
}
public void Write(int msgType,byte[] msgContent){
byte[] msgTypeByte = BitConverter.GetBytes(msgType);
int msgSize = HEAD_SIZE+HEAD_SIZE+msgContent.Length;
byte[] msgSizeByte = BitConverter.GetBytes(msgSize);
int totalSize = HEAD_SIZE+HEAD_SIZE+msgSize;
byte[] msgByte = new byte[totalSize];
int index = 0;
int i = 0;
for (i=0;i<HEAD_SIZE;i++){ // put msg type
if (msgTypeByte.Length>i){
msgByte[index] = msgTypeByte[i];
}
index++;
}
for (i=0;i<HEAD_SIZE;i++){ // put msg size
if (msgTypeByte.Length>i){
msgByte[index+i] = msgSizeByte[i];
}
index++;
}
for (i=0;i<msgSize;i++){ // put msg content
if (msgTypeByte.Length>i){
msgByte[index+i] = msgContent[i];
}
index++;
}
stream.Write(msgByte,0,msgByte.Length);
stream.Flush();
}
}
} |
主要用的是TcpClient,NetworkStream,BitConverter.
|
1
2
3
4
5
6
7
8
9
|
TcpClient client = new TcpClient(ip,port); // 获取与服务器连接
NetworkStream stream = client.GetStream(); // 获取连接的流
stream.Read(buf,0,lenght); // 读取至buf
stream.Write(buf,0,lenght); // 写至buf
BitConverter.GetBytes(data); // 用于将整数转为字节
BitConverter.ToInt32(data,0); // 用于将字节转为整数
stream.Flush(); // 将流中缓存发出,而不等候
stream.Close(); // 关闭流
client.Close(); // 关闭连接
|
第三部分 protobuf-net
FQ下载安装:http://code.google.com/p/protobuf-net/
数据结构编译成dll:
先新建解决方案,新建库,添加下载的full/unity/dll。具体代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
using System;
using ProtoBuf;
namespace CSProtoData
{ [ProtoContract]
public class Head
{
[ProtoMember(1)]
public Int32 DataType { get; set; }
[ProtoMember(2)]
public Int64 DataDate { get; set; }
[ProtoMember(3)]
public byte[] DataContent { get; set; }
}
[ProtoContract]
public class Number
{
[ProtoMember(1)]
public Int32 Index { get; set; }
[ProtoMember(2)]
public Int64 Value { get; set; }
}
public class Board
{
[ProtoMember(1)]
public Int64 Rank { get; set; }
[ProtoMember(2)]
public string TargetName { get; set; }
[ProtoMember(3)]
public Int64 Number { get; set; }
}
public class Request
{
[ProtoMember(1)]
public string DataType { get; set; }
[ProtoMember(2)]
public Int64 DataDate { get; set; }
[ProtoMember(3)]
public Int32 Start { get; set; }
[ProtoMember(4)]
public Int32 End { get; set; }
}
} |
编译完后,生成dll下面马上用到(同时也要拖放到unity/assets下)。
第三部分 下
因为protobuf-net的序列化和反序列化用的是jit,ios不支持jit,所以需采用编译成dll的方式来解决问题:
vs中,新建命令行程序,添加protobuf-net/full/unity/dll,添加刚生成的dll,代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
using System;
using ProtoBuf;
using ProtoSerializer;
using CSProtoData;
namespace ProtoSerializer
{ class MainClass
{
public static void Main(string[] args)
{
var model = ProtoBuf.Meta.TypeModel.Create();
model.Add(typeof(Head), true);
model.Add(typeof(Number), true);
model.Add(typeof(Board), true);
model.Add(typeof(Request), true);
model.Compile("CSProtoSerializer", "CSProtoSerializer.dll");
}
}
} |
这里按运行后,会在目录下生成:CSProtoSerializer.dll,一样拖放到unity/assets下。
其中typeof()的,就是proto数据类型,在上半部分有定义的内容。
第四部分 unity代码
执行完以上步骤,unity/assets下应该有这么几个dll:
protobuf-net/full/unity/dll
proto的data的dll(第三部分)
data的序列化的dll(第三部分下,运行后生成的那个)
还有用于tcp连接的dll(第二部分)
那么实际在unity当中调用的代码则是:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
using UnityEngine;
using System.Collections;
using TcpConnector;
using ProtoBuf;
using CSProtoData;
using System.IO;
public class testTcp : MonoBehaviour {
// Use this for initialization
void Start () {
Connector conn = new Connector();
bool result = conn.Connect("127.0.0.1",17093);
Debug.Log(result);
Head head=new Head{};
head.DataType = 2;
head.DataDate = 201407312;
MemoryStream memStream = new MemoryStream();
ProtoBuf.Serializer.Serialize<CSProtoData.Head>(memStream, head);
byte[] x = memStream.ToArray();
conn.Write(1,x);
conn.Write(1,x);
}
// Update is called once per frame
void Update () {
}
} |
新建个script,随便挂在比如camara的组件里即可。