2019-01-10 12:43:00 weixin_41738734 阅读数 509
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4646 人正在学习 去看看 张刚

在Unity3D上进行TCP Client的创建与通讯

简介

Unity3D版本: 2018.3.0f2 Personal
Visual Studio版本:2017

在Unity3D上连接TCP Server建立通讯
建立通讯后进行双向数据传输

代码

创建文件TCPUDPSocket.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Net.Sockets;
using System.Text;

public class TCPUDPSocket : MonoBehaviour
{
    NetworkStream sendStream;
    TcpClient client;
    bool flag = false;
    public void Start_TCPClient(string ip, int port)
    {
        client = new TcpClient(ip, port);
        sendStream = client.GetStream();
        flag = true;
    }

    public void Close_TCPClient()
    {
        sendStream.Close();
        client.Close();
        flag = false;
    }

    public void Write_TCPClient(string data)
    {
        if (flag == false)
            return;
        byte[] sendBytes = Encoding.Default.GetBytes(data);
        sendStream.Write(sendBytes, 0, sendBytes.Length);
    }

    public string Read_TCPClient()
    {
        if (flag == false)
            return "";
        byte[] readbyte = new byte[sendStream.Length];
        sendStream.Read(readbyte, 0, (int)sendStream.Length);
        return Encoding.ASCII.GetString(readbyte);
    }
    // Start is called before the first frame update
    void Start()
    {
        Start_TCPClient("192.168.199.231",2333);
    }

    // Update is called once per frame
    void Update()
    {
        
    }

   
}

根据需要可以进行发送与接收函数的调用,函数功能很简单,看名字就知道

2014-09-02 16:04:00 weixin_33877092 阅读数 52
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4646 人正在学习 去看看 张刚

原文: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 { getset; }
        [ProtoMember(2)]
        public Int64 DataDate { getset; }
        [ProtoMember(3)]
        public byte[] DataContent { getset; }
    }
 
    [ProtoContract]
    public class Number
    {
        [ProtoMember(1)]
        public Int32 Index { getset; }
        [ProtoMember(2)]
        public Int64 Value { getset; }
    }
 
    public class Board
    {
        [ProtoMember(1)]
        public Int64 Rank { getset; }
        [ProtoMember(2)]
        public string TargetName { getset; }
        [ProtoMember(3)]
        public Int64 Number { getset; }
    }
 
    public class Request
    {
        [ProtoMember(1)]
        public string DataType { getset; }
        [ProtoMember(2)]
        public Int64 DataDate { getset; }
        [ProtoMember(3)]
        public Int32 Start { getset; }
        [ProtoMember(4)]
        public Int32 End { getset; }
    }
}

编译完后,生成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的组件里即可。

 

2017-09-20 17:51:17 BattleTiger 阅读数 904
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4646 人正在学习 去看看 张刚

TCP的特性
1.TCP只会寻址一次
2.TCP 是有序的
3.TCP链接的时候有三次握手 如图
这里写图片描述

4.TCP断开链接的时候需要四次握手 如图
这里写图片描述

整体流程
这里写图片描述

服务端

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//引用两个命名空间
using System.Net;
using System.Net.Sockets;
using System;
//引用线程的命名空间
using System.Threading;

public class SocketState
{
    Socket ClientSocket;
    /// <summary>
    /// 存放接收到的字节流
    /// </summary>
    byte[] ReciveDataBytes = new byte[1024];
    public SocketState(Socket temSocket)
    {
        ClientSocket = temSocket;
    }
    /// <summary>
    /// 客户端向服务器端的链接请求
    /// </summary>
    public void ConnectRequest(string ip,int port)
    {
        IPEndPoint IP = new IPEndPoint(IPAddress.Parse(ip),port);
        ClientSocket.BeginConnect(IP, ConnectCallBack,null);
    }
    /// <summary>
    /// 发送链接请求的回调函数
    /// </summary>
    /// <param name="ar"></param>
    public void ConnectCallBack(IAsyncResult ar)
    {
        //ClientSocket.EndSend(ar)   表示跟服务器成功连接
        ClientSocket.EndConnect(ar);
    }
    /// <summary>
    /// 发送函数
    /// </summary>
    /// <param name="buffer">发送的字节流</param>
    public void SendData(byte[] buffer)
    {

        //发送
        //buffer  发送的字节流
        //0 偏移量 从buffer第0个字节开始
        //buffer.Length 读取长度为buffer的长度
        //SocketFlags.None 
        //SendCallBack 回调函数
        ClientSocket.BeginSend(buffer,0,buffer.Length,SocketFlags.None, SendCallBack,null);Debug.Log(buffer.Length);
    }
    /// <summary>
    /// 发送成功的回调函数
    /// </summary>
    /// <param name="ar"></param>
    public void SendCallBack(IAsyncResult ar)
    {
        //ClientSocket.EndSend(ar) 返回值类型为int  表示成功发送了多少个字节流
        int SendCount = ClientSocket.EndSend(ar);
        Debug.Log("send" + SendCount);
    }
    /// <summary>
    /// 接收函数
    /// </summary>
    /// <param name="buffer">发送的字节流</param>
    public void ReciveData()
    {
        //接收
        //ReciveDataBytes  接收的字节流
        //0 偏移量 从ReciveDataBytes第0个字节开始
        //ReciveDataBytes.Length 读取长度为ReciveDataBytes的长度
        //SocketFlags.None 
        //ReciveCallBack 回调函数
        ClientSocket.BeginReceive(ReciveDataBytes,0, ReciveDataBytes.Length,SocketFlags.None, ReciveCallBack, null);
    }
    /// <summary>
    /// 接收成功的回调函数
    /// </summary>
    /// <param name="ar"></param>
    public void ReciveCallBack(IAsyncResult ar)
    {
        //ClientSocket.EndSend(ar) 返回值类型为int  表示成功接收了多少个字节流
        int ReciveCount = ClientSocket.EndReceive(ar);
        Debug.Log("ReciveCount" + ReciveCount);
    }
}
public class TCPSever : MonoBehaviour {


    Socket severSocket;
    /// <summary>
    /// 端口号  和此端口号绑定
    /// </summary>
    public int port = 18001;
    /// <summary>
    /// 声明一个线程
    /// </summary>
    private Thread TemThread;
    /// <summary>
    /// 线程控制
    /// </summary>
    private bool IsRuningRecive = true;
    /// <summary>
    /// 存放客户端的映射
    /// </summary>
    List<SocketState> ClientSocketList;
    public void Init()
    {

        //AddressFamily 表示地址协议族 IPV4  IPV6
        //SocketType.Stream 数据报格式----> TCP
        //ProtocolType.Tcp  采用的哪种协议 
        severSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
        //获得一个ip
        IPEndPoint ip = new IPEndPoint(IPAddress.Any, port);
        //绑定ip
        severSocket.Bind(ip);
        //实例化线程
        TemThread = new Thread(ReciveThread);
        //开启线程
        TemThread.Start();
        //实例化List
        ClientSocketList = new List<SocketState>();
    }
    /// <summary>
    /// 接收线程
    /// </summary>
    public void ReciveThread()
    {
        while (IsRuningRecive)
        {
            //异步 接收
            //ReciveCallBack  回调函数
            //null 如果不需要就传null就可以了
            severSocket.BeginAccept(ReciveCallBack,null);
            //每隔100毫秒监听一次是否有客户端发送请求
            Thread.Sleep(100);
        }
    }
    /// <summary>
    /// 回调函数  有客户端请求就会调用
    /// </summary>
    /// <param name="ar"></param>
    public void ReciveCallBack(IAsyncResult ar)
    {
        //severSocket.EndAccept(ar.AsyncState) 返回值就是客户端的映射  需要我们保存下来
        Socket ClientSocket = severSocket.EndAccept(ar);
        //实例化一个SocketState
        SocketState temSocketState = new SocketState(ClientSocket);
        //添加到List
        ClientSocketList.Add(temSocketState);
    }

    // Use this for initialization
    void Start () {
        Init();
    }

    // Update is called once per frame
    void Update () {
        //不断的请求询问客户端
        for (int i = 0; i < ClientSocketList.Count; i++)
        {
            ClientSocketList[i].ReciveData();
        }
    }
}

客户端

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//引用两个命名空间
using System.Net;
using System.Net.Sockets;

public class TCPClient : MonoBehaviour {

    SocketState clientSocket;
    // Use this for initialization
    void Start () {
        Socket temSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

        clientSocket = new SocketState(temSocket);

        clientSocket.ConnectRequest("127.0.0.1",18001);    
    }

    // Update is called once per frame
    void Update () {


        if (Input.GetMouseButtonDown(0))
        {
            byte[] temB = System.Text.Encoding.Default.GetBytes("123456");
            clientSocket.SendData(temB);
        }
        if (clientSocket != null)
        {
            clientSocket.ReciveData();
        }
    }
}
2018-12-10 10:00:24 hu123456__ 阅读数 110
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4646 人正在学习 去看看 张刚

准备工作:

1、打开 Unity3D 安装目录,到这个路径下 Editor > Data > Mono > lib > mono > 2.0 拷贝出下图的五个动态链接库,放到 Unity3D 工程目录下 Assets/Plugins 文件夹中。这里我想重点说一下,在使用过程中这五个动态链接库需要与 Unity3D 版本匹配,也就是说你不要在 Uniyt3D 5.3 版本拷贝出来,拿去 Uniyt3D 5.4 版本中使用,这是有可能出问题的,最好是在自己的 Unity3D 安装目录下去拷贝。I18N.CJK.dll 这个链接库,如果是 PC 端连接数据库可以不需要,如果是移动端连接数据库就必须要。

2、网上下载一个 MySql.Data.dll 动态链接库,也放到 Unity3D 工程目录下 Assets/Plugins 文件夹中。

using MySql.Data.MySqlClient;
  2 using System;
  3 using System.Data;
  4 
  5 public class MySqlAccess
  6 {
  7     public static MySqlConnection mySqlConnection;//连接类对象
  8 
  9     private static string host;     //IP地址。如果只是在本地的话,写localhost就可以。
 10     private static string id;       //用户名。
 11     private static string pwd;      //密码。
 12     private static string dataBase; //数据库名称。
 13 
 14     /// <summary>
 15     /// 构造方法
 16     /// </summary>
 17     /// <param name="_host">IP地址</param>
 18     /// <param name="_id">用户名</param>
 19     /// <param name="_pwd">密码</param>
 20     /// <param name="_dataBase">数据库名称</param>
 21     public MySqlAccess(string _host, string _id, string _pwd, string _dataBase)
 22     {
 23         host = _host;
 24         id = _id;
 25         pwd = _pwd;
 26         dataBase = _dataBase;
 27         OpenSql();
 28     }
 29 
 30     /// <summary>  
 31     /// 打开数据库  
 32     /// </summary>  
 33     public static void OpenSql()
 34     {
 35         try
 36         {
 37             //string.Format是将指定的 String类型的数据中的每个格式项替换为相应对象的值的文本等效项。  
 38             string mySqlString = string.Format("Database={0};Data Source={1};User Id={2};Password={3};", dataBase, host, id, pwd, "3306");
 39             mySqlConnection = new MySqlConnection(mySqlString);
 40             mySqlConnection.Open();
 41         }
 42         catch (Exception e)
 43         {
 44             throw new Exception("服务器连接失败,请重新检查是否打开MySql服务。" + e.Message.ToString());
 45         }
 46     }
 47 
 48     /// <summary>  
 49     /// 创建表  
 50     /// </summary>  
 51     /// <param name="name">表名</param>  
 52     /// <param name="colName">属性列</param>  
 53     /// <param name="colType">属性类型</param>  
 54     /// <returns></returns>  
 55     public DataSet CreateTable(string name, string[] colName, string[] colType)
 56     {
 57         if (colName.Length != colType.Length)
 58         {
 59             throw new Exception("输入不正确:" + "columns.Length != colType.Length");
 60         }
 61         string query = "CREATE TABLE  " + name + "(" + colName[0] + " " + colType[0];
 62         for (int i = 1; i < colName.Length; i++)
 63         {
 64             query += "," + colName[i] + " " + colType[i];
 65         }
 66         query += ")";
 67         return QuerySet(query);
 68     }
 69 
 70     /// <summary>  
 71     /// 创建具有id自增的表  
 72     /// </summary>  
 73     /// <param name="name">表名</param>  
 74     /// <param name="col">属性列</param>  
 75     /// <param name="colType">属性列类型</param>  
 76     /// <returns></returns>  
 77     public DataSet CreateTableAutoID(string name, string[] col, string[] colType)
 78     {
 79         if (col.Length != colType.Length)
 80         {
 81             throw new Exception("columns.Length != colType.Length");
 82         }
 83         string query = "CREATE TABLE  " + name + " (" + col[0] + " " + colType[0] + " NOT NULL AUTO_INCREMENT";
 84         for (int i = 1; i < col.Length; ++i)
 85         {
 86             query += ", " + col[i] + " " + colType[i];
 87         }
 88         query += ", PRIMARY KEY (" + col[0] + ")" + ")";
 89         return QuerySet(query);
 90     }
 91 
 92     /// <summary>  
 93     /// 插入一条数据,包括所有,不适用自动累加ID。  
 94     /// </summary>  
 95     /// <param name="tableName">表名</param>  
 96     /// <param name="values">插入值</param>  
 97     /// <returns></returns>  
 98     public DataSet InsertInto(string tableName, string[] values)
 99     {
100         string query = "INSERT INTO " + tableName + " VALUES (" + "'" + values[0] + "'";
101         for (int i = 1; i < values.Length; ++i)
102         {
103             query += ", " + "'" + values[i] + "'";
104         }
105         query += ")";
106         return QuerySet(query);
107     }
108 
109     /// <summary>  
110     /// 插入部分ID  
111     /// </summary>  
112     /// <param name="tableName">表名</param>  
113     /// <param name="col">属性列</param>  
114     /// <param name="values">属性值</param>  
115     /// <returns></returns>  
116     public DataSet InsertInto(string tableName, string[] col, string[] values)
117     {
118         if (col.Length != values.Length)
119         {
120             throw new Exception("columns.Length != colType.Length");
121         }
122         string query = "INSERT INTO " + tableName + " (" + col[0];
123         for (int i = 1; i < col.Length; ++i)
124         {
125             query += ", " + col[i];
126         }
127         query += ") VALUES (" + "'" + values[0] + "'";
128         for (int i = 1; i < values.Length; ++i)
129         {
130             query += ", " + "'" + values[i] + "'";
131         }
132         query += ")";
133         return QuerySet(query);
134     }
135 
136     /// <summary>  
137     /// 查询表数据 
138     /// </summary>  
139     /// <param name="tableName">表名</param>  
140     /// <param name="items">需要查询的列</param>  
141     /// <param name="whereColName">查询的条件列</param>  
142     /// <param name="operation">条件操作符</param>  
143     /// <param name="value">条件的值</param>  
144     /// <returns></returns>  
145     public DataSet Select(string tableName, string[] items, string[] whereColName, string[] operation, string[] value)
146     {
147         if (whereColName.Length != operation.Length || operation.Length != value.Length)
148         {
149             throw new Exception("输入不正确:" + "col.Length != operation.Length != values.Length");
150         }
151         string query = "SELECT " + items[0];
152         for (int i = 1; i < items.Length; i++)
153         {
154             query += "," + items[i];
155         }
156         query += "  FROM  " + tableName + "  WHERE " + " " + whereColName[0] + operation[0] + " '" + value[0] + "'";
157         for (int i = 1; i < whereColName.Length; i++)
158         {
159             query += " AND " + whereColName[i] + operation[i] + "' " + value[i] + "'";
160         }
161         return QuerySet(query);
162     }
163 
164     /// <summary>  
165     /// 更新表数据 
166     /// </summary>  
167     /// <param name="tableName">表名</param>  
168     /// <param name="cols">更新列</param>  
169     /// <param name="colsvalues">更新的值</param>  
170     /// <param name="selectkey">条件:列</param>  
171     /// <param name="selectvalue">条件:值</param>  
172     /// <returns></returns>  
173     public DataSet UpdateInto(string tableName, string[] cols, string[] colsvalues, string selectkey, string selectvalue)
174     {
175         string query = "UPDATE " + tableName + " SET " + cols[0] + " = " + colsvalues[0];
176         for (int i = 1; i < colsvalues.Length; ++i)
177         {
178             query += ", " + cols[i] + " =" + colsvalues[i];
179         }
180         query += " WHERE " + selectkey + " = " + selectvalue + " ";
181         return QuerySet(query);
182     }
183 
184     /// <summary>  
185     /// 删除表数据  
186     /// </summary>  
187     /// <param name="tableName">表名</param>  
188     /// <param name="cols">条件:删除列</param>  
189     /// <param name="colsvalues">删除该列属性值所在得行</param>  
190     /// <returns></returns>  
191     public DataSet Delete(string tableName, string[] cols, string[] colsvalues)
192     {
193         string query = "DELETE FROM " + tableName + " WHERE " + cols[0] + " = " + colsvalues[0];
194         for (int i = 1; i < colsvalues.Length; ++i)
195         {
196             query += " or " + cols[i] + " = " + colsvalues[i];
197         }
198         return QuerySet(query);
199     }
200 
201     /// <summary>
202     /// 释放
203     /// </summary>
204     public void Close()
205     {
206         if (mySqlConnection != null)
207         {
208             mySqlConnection.Close();
209             mySqlConnection.Dispose();
210             mySqlConnection = null;
211         }
212     }
213 
214     /// <summary>    
215     /// 执行Sql语句  
216     /// </summary>  
217     /// <param name="sqlString">sql语句</param>  
218     /// <returns></returns>  
219     public static DataSet QuerySet(string sqlString)
220     {
221         if (mySqlConnection.State == ConnectionState.Open)
222         {
223             DataSet ds = new DataSet();
224             try
225             {
226                 MySqlDataAdapter mySqlDataAdapter = new MySqlDataAdapter(sqlString, mySqlConnection);
227                 mySqlDataAdapter.Fill(ds);
228             }
229             catch (Exception e)
230             {
231                 throw new Exception("SQL:" + sqlString + "/n" + e.Message.ToString());
232             }
233             finally
234             {
235             }
236             return ds;
237         }
238         return null;
239     }
240 }
接下来我们就可以访问数据库了
 1 using UnityEngine;
 2 using System.Data;
 3 
 4 public class Test : MonoBehaviour
 5 {
 6     private void Start()
 7     {
 8         MySqlAccess mySql = new MySqlAccess("localhost", "root", "root", "Test");
 9         mySql.CreateTableAutoID("tableTest", new string[] { "id", "name", "age" }, new string[] { "int", "text", "text" });
10         mySql.InsertInto("tableTest", new string[] { "name", "age" }, new string[] { "张三", "28" });
11         mySql.InsertInto("tableTest", new string[] { "name", "age" }, new string[] { "李四", "20" });
12         for (int i = 1; i < 3; i++)
13         {
14             DataSet ds = mySql.Select("tableTest", new string[] { "name", "age" }, new string[] { "id" }, new string[] { "=" }, new string[] { i.ToString() });
15             if (ds != null)
16             {
17                 DataTable table = ds.Tables[0];
18                 foreach (DataRow row in table.Rows)
19                 {
20                     foreach (DataColumn column in table.Columns)
21                     {
22                         Debug.Log(row[column]);
23                     }
24                 }
25             } 
26         }
27         mySql.Close();
28     }
29 }

转载:https://www.cnblogs.com/xiaoyulong/p/8686886.html#4053314

2018-03-17 12:50:26 MadBam_boo 阅读数 589
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4646 人正在学习 去看看 张刚

Unity3d实战之Unity3d网络游戏实战篇(8):网络管理类ServNet

学习书籍《Unity3d网络游戏实战》 罗培羽著 机械工业出版社
本文是作者在学习过程中遇到的认为值得记录的点,因此引用的代码等资源基本出资罗培羽老师的书籍,如有侵权请联系,必删。

 本章所讲的内容与网络基础章节的内容有关:
 【实战】Unity3d实战之Unity3d网络游戏实战篇(3):网络基础之TCP协议
 【实战】Unity3d实战之Unity3d网络游戏实战篇(4):网络基础之Socket套接字

 根据TCP的机制,Server和Client之间会维持一个连接进行数据的收发。
 如果发送的数据包太小,TCP会合并较小的数据报再发送,另一端便无法区分哪些才是正确的,这种现象称为黏包。例如:
  Client Send: hello
  Client Send: world
  Server Receive: helloworld
  Client 发送两次,Server只响应一次接收。
 如果发送的数据报太大,TCP有可能会将它拆分成多个包发送,接收端一次可能只收到部分数据。这种现象称为分包。例如:
  Client Send: helloworld
  Server Receive: hel
  Server Receive: loworld
  Client只发送一个数据包,Server收到两个数据包。
 如果有认真的学习Socket通信的话相信都会遇到过这种问题。

 其中一种处理方法是发送端在要发送的数据最前端加入本次发送的数据包的长度,接收端在接收到数据时,根据数据包的长度来判断是否需要等待下一次数据的接收(直到接收完该长度指定的数据)。因为按照TCP机制,接收到收到的字节顺序一定跟发送端发送的顺序一致。例如:
 Client Send: 10helloworld
 Client Send: 4baby
 Server readBuff: 10hel
 Server readBuff: 10helloworld4b
 Server 读出helloworld,并将该数据包的内容从readBuff中清除。
 Server readBuff: 4b
 Server readBuff: 4baby
 Server 读出baby,并将该数据包的内容从readBuff中清除。
 Server readBuff:
 
 设计一条完整消息的框架(这里将消息定义为发送端发送的数据(包含消息长度))。
 这里写图片描述
 代码如下(代码后有简单的解释,如果不懂请留言讨论):

void ReceiveCb(IAsyncResult ar)
{
    Conn conn = (Conn)ar.AsyncState;

    try {
        int count = conn.socket.EndReceive(ar);
        if(count > 0){
            conn.buffCount += count;        // buffCount means total length of data which sstored in readBuff
            ProcessData(conn);              // Handle the data 
        }

        conn.socket.BeginReceive(
            conn.readBuff,
            conn.buffCount,
            conn.BufferRemain(),
            SocketFlags.None,
            ReceiveCb,
            conn);
    } catch (Exception ex) {
        Console.WriteLine ("[ServNet.ReceiveCb] Receive byte fail." + ex.Message);
        conn.Close ();
    }
}

void ProcessData(Conn conn)
{
    if (conn.buffCount < sizeof(Int32))         // If buffCount less than 4 Byte, error
        return;

    Array.Copy (conn.readBuff, conn.lenBytes, sizeof(Int32));   // Get lenBytes
    conn.msgLength = BitConverter.ToInt16 (conn.lenBytes, 0);   // Use BitConverter get the msgLenth
    if (conn.buffCount < sizeof(Int32) + conn.msgLength)        // If current buffCount is less than msgLength + 4Byte, error
        return;

    string str = System.Text.Encoding.UTF8.GetString(conn.readBuff, sizeof(Int32), conn.msgLength); // get the data and ignore the lenBytes
    HandleMsg (str);            // Handle message

    int count = conn.buffCount - sizeof(Int32) - conn.msgLength;    // Reset the readBuff
    Array.Copy (conn.readBuff, sizeof(Int32) + conn.msgLength, conn.readBuff, 0, count);
    conn.buffCount = count;
    if (conn.buffCount > 0) {
        ProcessData (conn);
    }
}

 流程:
 注意:buffCount表示当前readBuff中所拥有的的数据的长度。
  ReceiveCb接收数据 -> 修改buffCount的长度 -> 对readBuff进行处理;
 ProcessData:
  如果readBuff的长度不足4字节,说明readBuff中的数据不完整,返回;
  否则,读出4字节的lenBytes,将它转换成Int32整型msgLenght;
   如果buffCount - 4字节长后,剩余的长度小于msgLength,说明数据还未接收完整,返回接收下一次的数据;
   否则,读出这条消息的有效数据部分(即排除掉lenBytes),然后更新readBuff(将下一数据前置)进行下一次消息读取的准备;

 这样,接收端就能正确地对接收到的数据进行区分,获取到完整的数据再对数据进行其他处理。
  
  

Unity3D中四元数

阅读数 4207

unity3d联机调试

阅读数 4275

没有更多推荐了,返回首页