使用Unity调用派样机技术小结

小编:迷魂雪 更新时间:2022-08-25

距离这个开发这个项目已经过去差不多两年时间了,今天我闲来无事清理电脑里项目的时候无意看到了这个项目。已经都过去将近两年时间了,时光荏苒啊!两年前的自己也是一个冲动的年轻人,拼了命的做项目,现在想想自己,年轻人还是真年轻呀。算了,废话不多说,今天在这里总结一下调用派样机的开发流程。

需求梳理

当时公司让实现一个什么样的功能呐?就是在派样机(类似于饮料自动购物机那种机器)上的电脑上,开发一款Unity程序,这款程序上有一个二维码,用户用微信扫一扫扫这个二维码,这时用户的手机上就会出现一个互动的小程序,用户互动完成后,服务器判断用户互动完成,给派样机的Unity程序发一个网络指令。Unity程序收到该指令后,使用串口通信给派样机发一个指令,派样机硬件收到该指令后,即调用硬件推出一个小礼物,送给用户。

使用Unity调用派样机技术小结

图1使用的派样机

这个项目不是什么很复杂的项目,这里面有两个难点。1.获取服务器传过来的信号,进行判断。2.判断完毕服务器的信号后,调用派样机,调用硬件进行派样。只要开发完成这两个功能后,这个项目就算是完成了。

开发步骤

1.首先在Unity中创建UI,将二维码贴在Unity的程序里的UI上,UI如下图所示。

使用Unity调用派样机技术小结

图2设计的程序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; ///

/// 派样机字符类 /// 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); 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(); } ///

/// 字符串转16进制字符数组 /// ///

/// public static byte[] StringToHexByte(string str) { return StringToHexByte(str, false); } ///

/// 字符串转16进制字符数组 /// ///

///

是否过滤掉中文字符 /// 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(); } } ///

/// 派样机串口 /// ///

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; } } }

小结

就这样,派样机的功能就基本开发完成了。虽然这个程序的功能十分简单,但是用处很大,创作不易,如果喜欢文章,请点个赞。