一、需求梳理
当时公司让实现一个什么样的功能呐?就是在派样机(类似于饮料自动购物机那种机器)上的电脑上,开发一款Unity程序,这款程序上有一个二维码,用户用微信扫一扫扫这个二维码,这时用户的手机上就会出现一个互动的小程序,用户互动完成后,服务器判断用户互动完成,给派样机的Unity程序发一个网络指令。Unity程序收到该指令后,使用串口通信给派样机发一个指令,派样机硬件收到该指令后,即调用硬件推出一个小礼物,送给用户。
这个项目不是什么很复杂的项目,这里面有两个难点。1.获取服务器传过来的信号,进行判断。2.判断完毕服务器的信号后,调用派样机,调用硬件进行派样。只要开发完成这两个功能后,这个项目就算是完成了。
二、开发步骤
1.首先在Unity中创建UI,将二维码贴在Unity的程序里的UI上,UI如下图所示。
2.开发获取服务器指令功能,并且进行判断,如果获取到正确的信息,即对派样机发送派样指令,代码如下。
using
System
;
using
System
.
Collections
;
using
System
.
Collections
.
Generic
;
using
UnityEngine
;
using
UnityEngine
.
Networking
;
using
Newtonsoft
.
Json
;
using
UnityEngine
.
UI
;
public
class
HttpNet
:
MonoBehaviour
{
Action
callback
;
/// <summary>
/// 派样机字符类
/// </summary>
public
ComManager
comManager
;
// Start is called before the first frame update
void
Start
(
)
{
callback
+=
Dispchater
;
StartCoroutine
(
GetData
(
callback
)
)
;
}
private
void
Dispchater
(
)
{
//Debug.Log("掉小样!");
comManager
.
DemoMechineSendCom
(
)
;
}
//加载路径图片
IEnumerator
GetData
(
Action
action
)
//Action action
{
while
(
true
)
{
yield
return
new
WaitForSeconds
(
2.0f
)
;
UnityWebRequest
unityWebRequest
=
UnityWebRequest
.
Get
(
"https://www.brandxspace.com/development/sendPrototype/getPrototypeState?flag=0"
)
;
//UnityWebRequest unityWebRequest = UnityWebRequest.Get(jsonUrl);
yield
return
unityWebRequest
.
SendWebRequest
(
)
;
if
(
!
unityWebRequest
.
isNetworkError
)
{
string
data
=
unityWebRequest
.
downloadHandler
.
text
;
Data
d
=
JsonConvert
.
DeserializeObject
<
Data
>
(
data
)
;
if
(
d
!=
null
)
{
Debug
.
Log
(
data
+
"------"
)
;
if
(
d
.
status
==
"1"
)
{
//掉小样
if
(
action
!=
null
)
{
action
(
)
;
}
}
}
}
}
}
}
public
class
Data
{
public
string
status
;
public
String
message
;
public
object
data
;
}
3.开发调用派样机派样功能,该功能主要使用的是串口通信开发,如果对串口通信开发很熟悉的话这个也是十分简单的功能,主要是通过代码设置派样的顺序和速率,代码如下: (1)CRC.CS
using
System
;
using
System
.
Collections
.
Generic
;
using
System
.
Linq
;
using
System
.
Text
;
public
class
CRC
{
#
region
CRC16
public
static
byte
[
]
CRC16
(
byte
[
]
data
)
{
int
len
=
data
.
Length
;
if
(
len
>
0
)
{
ushort
crc
=
0xFFFF
;
for
(
int
i
=
0
;
i
<
len
;
i
++
)
{
crc
=
(
ushort
)
(
crc
^
(
data
[
i
]
)
)
;
for
(
int
j
=
0
;
j
<
8
;
j
++
)
{
crc
=
(
crc
&
1
)
!=
0
?
(
ushort
)
(
(
crc
>>
1
)
^
0xA001
)
:
(
ushort
)
(
crc
>>
1
)
;
}
}
byte
hi
=
(
byte
)
(
(
crc
&
0xFF00
)
>>
8
)
;
//高位置
byte
lo
=
(
byte
)
(
crc
&
0x00FF
)
;
//低位置
return
new
byte
[
]
{
hi
,
lo
}
;
}
return
new
byte
[
]
{
0
,
0
}
;
}
#
endregion
#
region
ToCRC16
public
static
string
ToCRC16
(
string
content
)
{
return
ToCRC16
(
content
,
Encoding
.
UTF8
)
;
}
public
static
string
ToCRC16
(
string
content
,
bool
isReverse
)
{
return
ToCRC16
(
content
,
Encoding
.
UTF8
,
isReverse
)
;
}
public
static
string
ToCRC16
(
string
content
,
Encoding
encoding
)
{
return
ByteToString
(
CRC16
(
encoding
.
GetBytes
(
content
)
)
,
true
)
;
}
public
static
string
ToCRC16
(
string
content
,
Encoding
encoding
,
bool
isReverse
)
{
return
ByteToString
(
CRC16
(
encoding
.
GetBytes
(
content
)
)
,
isReverse
)
;
}
public
static
string
ToCRC16
(
byte
[
]
data
)
{
return
ByteToString
(
CRC16
(
data
)
,
true
)
;
}
public
static
string
ToCRC16
(
byte
[
]
data
,
bool
isReverse
)
{
return
ByteToString
(
CRC16
(
data
)
,
isReverse
)
;
}
#
endregion
#
region
ToModbusCRC16
public
static
string
ToModbusCRC16
(
string
s
)
{
return
ToModbusCRC16
(
s
,
true
)
;
}
public
static
string
ToModbusCRC16
(
string
s
,
bool
isReverse
)
{
return
ByteToString
(
CRC16
(
StringToHexByte
(
s
)
)
,
isReverse
)
;
}
public
static
string
ToModbusCRC16
(
byte
[
]
data
)
{
return
ToModbusCRC16
(
data
,
true
)
;
}
public
static
string
ToModbusCRC16
(
byte
[
]
data
,
bool
isReverse
)
{
return
ByteToString
(
CRC16
(
data
)
,
isReverse
)
;
}
#
endregion
#
region
ByteToString
public
static
string
ByteToString
(
byte
[
]
arr
,
bool
isReverse
)
{
try
{
byte
hi
=
arr
[
0
]
,
lo
=
arr
[
1
]
;
return
Convert
.
ToString
(
isReverse
?
hi
+
lo
*
0x100
:
hi
*
0x100
+
lo
,
16
)
.
ToUpper
(
)
.
PadLeft
(
4
,
'0'
)
;
}
catch
(
Exception
ex
)
{
throw
(
ex
)
;
}
}
public
static
string
ByteToString
(
byte
[
]
arr
)
{
try
{
return
ByteToString
(
arr
,
true
)
;
}
catch
(
Exception
ex
)
{
throw
(
ex
)
;
}
}
#
endregion
#
region
StringToHexString
public
static
string
StringToHexString
(
string
str
)
{
StringBuilder
s
=
new
StringBuilder
(
)
;
foreach
(
short
c
in
str
.
ToCharArray
(
)
)
{
s
.
Append
(
c
.
ToString
(
"X4"
)
)
;
}
return
s
.
ToString
(
)
;
}
#
endregion
#
region
StringToHexByte
private
static
string
ConvertChinese
(
string
str
)
{
StringBuilder
s
=
new
StringBuilder
(
)
;
foreach
(
short
c
in
str
.
ToCharArray
(
)
)
{
if
(
c
<=
0
||
c
>=
127
)
{
s
.
Append
(
c
.
ToString
(
"X4"
)
)
;
}
else
{
s
.
Append
(
(
char
)
c
)
;
}
}
return
s
.
ToString
(
)
;
}
private
static
string
FilterChinese
(
string
str
)
{
StringBuilder
s
=
new
StringBuilder
(
)
;
foreach
(
short
c
in
str
.
ToCharArray
(
)
)
{
if
(
c
>
0
&&
c
<
127
)
{
s
.
Append
(
(
char
)
c
)
;
}
}
return
s
.
ToString
(
)
;
}
/// <summary>
/// 字符串转16进制字符数组
/// </summary>
/// <param name="hex"></param>
/// <returns></returns>
public
static
byte
[
]
StringToHexByte
(
string
str
)
{
return
StringToHexByte
(
str
,
false
)
;
}
/// <summary>
/// 字符串转16进制字符数组
/// </summary>
/// <param name="str"></param>
/// <param name="isFilterChinese">是否过滤掉中文字符</param>
/// <returns></returns>
public
static
byte
[
]
StringToHexByte
(
string
str
,
bool
isFilterChinese
)
{
string
hex
=
isFilterChinese
?
FilterChinese
(
str
)
:
ConvertChinese
(
str
)
;
//清除所有空格
hex
=
hex
.
Replace
(
" "
,
""
)
;
//若字符个数为奇数,补一个0
hex
+=
hex
.
Length
%
2
!=
0
?
"0"
:
""
;
byte
[
]
result
=
new
byte
[
hex
.
Length
/
2
]
;
for
(
int
i
=
0
,
c
=
result
.
Length
;
i
<
c
;
i
++
)
{
result
[
i
]
=
Convert
.
ToByte
(
hex
.
Substring
(
i
*
2
,
2
)
,
16
)
;
}
return
result
;
}
#
endregion
}
(2)ComManager.cs
using
UnityEngine
;
using
System
.
Collections
;
using
System
;
using
System
.
Threading
;
using
System
.
Collections
.
Generic
;
using
System
.
IO
.
Ports
;
public
class
ComManager
:
MonoBehaviour
{
//public ComManager instance;
//端口号
string
com2
=
""
;
private
SerialPort
sp2
;
//波特率
private
int
baudRate
;
public
float
timer
=
0.1f
;
//private bool isShinning = false;
//配置文件管理类
public
ConfigTest
configTest
;
//private void Awake()
//{
//instance = this;
//}
void
Start
(
)
{
//string com2 = "COM7";
com2
=
configTest
.
dic
[
"端口号"
]
[
"portName"
]
;
baudRate
=
int
.
Parse
(
configTest
.
dic
[
"波特率"
]
[
"baudRate"
]
)
;
//row = 8;
row
=
int
.
Parse
(
configTest
.
dic
[
"参数"
]
[
"row"
]
)
;
//column = 4;
column
=
int
.
Parse
(
configTest
.
dic
[
"参数"
]
[
"column"
]
)
;
//depth = 5;
depth
=
int
.
Parse
(
configTest
.
dic
[
"参数"
]
[
"depth"
]
)
;
mainCount
=
int
.
Parse
(
configTest
.
dic
[
"参数"
]
[
"mainCount"
]
)
;
StartCoroutine
(
StartCom
(
)
)
;
}
IEnumerator
StartCom
(
)
{
yield
return
new
WaitForSeconds
(
0.1f
)
;
sp2
=
new
SerialPort
(
com2
,
baudRate
,
Parity
.
None
,
8
,
StopBits
.
One
)
;
if
(
!
sp2
.
IsOpen
)
{
sp2
.
Open
(
)
;
}
}
/// <summary>
/// 派样机串口
/// </summary>
/// <param name="data"></param>
private
void
SendDemoMechineData
(
byte
[
]
data
)
{
if
(
sp2
.
IsOpen
)
{
sp2
.
Write
(
data
,
0
,
data
.
Length
)
;
}
}
void
OnDisable
(
)
{
if
(
sp2
.
IsOpen
)
{
sp2
.
Close
(
)
;
}
}
private
int
row
;
//8
private
int
column
;
//5
private
int
depth
;
//10
private
int
mainCount
=
40
;
//总数
private
static
int
index
=
0
;
public
void
DemoMechineSendCom
(
)
{
int
tempRow
=
index
%
row
;
//第几个
int
tempColumn
=
(
index
/
row
)
%
row
;
//第几行
int
tempdepth
=
index
/
(
row
*
column
)
%
depth
;
Debug
.
Log
(
index
+
" row: "
+
tempRow
+
"col: "
+
tempColumn
+
"depth "
+
tempdepth
)
;
string
pos
=
tempColumn
.
ToString
(
"0"
)
+
tempRow
.
ToString
(
"0"
)
;
string
corPos
=
System
.
Convert
.
ToString
(
int
.
Parse
(
pos
)
,
16
)
.
PadLeft
(
2
,
'0'
)
;
string
data
=
"0105"
+
corPos
+
"030000000000000000000000000000"
;
byte
[
]
byteData
=
CRC
.
StringToHexByte
(
data
)
;
byte
[
]
crcByteData
=
CRC
.
CRC16
(
byteData
)
;
//Debug.Log(CRC.ByteToString(crcByteData));
data
+=
CRC
.
ByteToString
(
crcByteData
)
;
//Debug.Log(data);
byte
[
]
byteDatas
=
CRC
.
StringToHexByte
(
data
)
;
SendDemoMechineData
(
byteDatas
)
;
index
++
;
if
(
index
>=
mainCount
)
{
index
=
0
;
}
}
}
三、小结
就这样,派样机的功能就基本开发完成了。虽然功能十分简单,但是用处很大,创作不易,如果喜欢文章,请点个赞。另外安利一波本人新开的网店,如果有什么需求自己做的费劲,可以在网店联系我,我会尽力帮助大家,希望大家支持一下。网店地址
小程工作室
本文详细介绍了如何使用Unity开发一个结合微信二维码扫描的互动程序,当用户完成互动后,通过服务器指令控制派样机送出小礼物。开发过程中涉及的主要难点包括接收服务器信号并触发派样,以及通过串口通信调用派样机硬件。通过Unity创建UI、实现网络请求及串口通信功能,成功实现了派样机的自动化操作。
2861

被折叠的 条评论
为什么被折叠?



