ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

第一周 UGUI mvvm框架、UIText本地化、csv转json文件、从谷歌下载csv表格

2020-03-02 22:07:59  阅读:311  来源: 互联网

标签:string mvvm request System value json key using csv


第一周 新项目熟悉 UGUI mvvm框架、UIText本地化、csv表格转为json文件、从谷歌服务器下载csv表工具制作

一、UGUI Mvvm框架

第一次接触mvvm框架,首先不管是什么,先看看这个东西是怎么用的,之后再来分析一下。
首先需要再 canvas 节点上放置 Root Model View,这个脚本会在运行时最先被实例出来。
在这里插入图片描述
然后再Default Context中添加你自己写的控制脚本,这个脚本将会控制所有这个Canvas上的所有UI。接下来看看这个 Context 脚本该怎么写。

//首先脚本需要继承 MonoBehaviourContext 这样才可以挂载到Default Contexts上面去
public class ModelCtrl : MonoBehaviourContext
{
	#region Property Text
	//这里定义属性 Property 这里的泛型 string 对应了绑定的UI上的属性
    private readonly Property<string> _privateTextProperty = new Property<string>();
    public string Text
    {
        get { return _privateTextProperty.GetValue(); }
        set { _privateTextProperty.SetValue(value); }
    }
    #endregion
    //这里做一个测试效果 就是按下A然后 改变text的内容 
	private void Update()
   	{
       if (Input.GetKey(KeyCode.A))
       {
           Text = "测试";
       }
   	}
}

然后接下来我们来创建一个text
在这里插入图片描述
接下来看看,我们这个Text的属性时如何改变UI显示的。
在这里插入图片描述
我们需要在UI上挂一个 UGUI Text Binding 脚本,然后再Path中填写,在ModelCtrl中的属性名称。这样Text Binding会自动去Canvas的RootModelView中寻找Default Context,然后找到path的属性与其绑定,这样只需要修改Text字符串即可,免去了查找物体,获取组件,修改这些步骤,使得ui和逻辑分离。

如果要给一个button添加点击事件,只需要在ModelCtrl中添加点击函数

	void OnButtonClick()
   {
       Debug.Log("按钮被点击");
   }

然后再button上添加onclick绑定脚本,在Path中添加函数名即可。
在这里插入图片描述
如果要设置一个UI的Active,只需要设置一个bool的Property即可。

	#region Property TextActive
 	private readonly Property<bool> _privateTextActiveProperty = new Property<bool>();
   	public bool TextActive
   	{
       get { return _privateTextActiveProperty.GetValue(); }
       set { _privateTextActiveProperty.SetValue(value); }
   	}
   	#endregion

在这里插入图片描述
这样就可以通过设置这个bool值来控制UI的Active了。这里面还有很多其他属性的绑定。其功能会在以后的博客中慢慢演示。
在这里插入图片描述
关于mvvm框架,主要分为Model、View、ViewMode。

  • Model: 代表数据模型,数据和业务逻辑都在Model中定义,
  • View:代表UI试图,负责数据的显示;
  • ViewModel :负责监听model中数据的改变并控制试图更新,处理用户交互操作。

MVVM框架的实现原理,和其他绑定组件的用法,后面博客再详细分析,这次先简单说一下用法让大家简单感受一下使用的感觉。

二、关于文字的本地化

MVVM框架中集成了文字本地化的相关功能。
在这里插入图片描述
在Format中用 $ $引起来的内容,是可以在代码中加载输出的。例如
在这里插入图片描述
之后我们需要在Awake里将TextBinding的中的 I18NModifier 委托注册一个你自己实现的函数,那么此时当这个Text要显示的时候,会将NickName传递到委托函数中,你返回的值就是 $ $中间的内容。这样就可以将各国的语言存放到json表中,在 $ $中放入key,委托函数里面通过key去寻找对应的value返回,这样就可以做到文字的本地化。 这里做一个简单的演示。

	private void Awake()
   {
       TextBinding.I18NModifier += key => { return "별명"; };
   }

   private void Start()
   {
       Text = "abcd1234";
   }

在这里插入图片描述
在这里插入图片描述

三、将CSV转换成json文件。

这里主要是因为,游戏中需要将多国的语言制作成csv表格,如果要做本地化,那么就要像之前说的,解析这些csv表格,转成json文件,然后再text中绑定key值,来寻找value实现文字的本地化功能。
在这里插入图片描述
这边工具还是比较简单的,直接上代码,需要注意的是再csv中,是用逗号作为分隔符,那么如果一个item中存在逗号的时候,这个item会被双引号引起来。如下图:
在这里插入图片描述
规律呢,就是一个item中引号的个数一定是双数的,如果你发现两个逗号中的元素引号是单数的,那么这个其中一定有一个逗号是,表中带有的,你需要拼接。


using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text;

public class ToolsMune
{

    [MenuItem("Tools/Csv2Json")]
    static void CsvToJson()
    {
        //Debug.Log(Application.dataPath + "/csvTable.csv");
        string[] scvline = File.ReadAllLines(Application.dataPath + "/csvTable.csv");
        string[] Language = scvline[0].Split(',');
        for (int i = 1; i < Language.Length; i++)
        {
            using (File.Create(Application.dataPath + "/Data/" + Language[i] + ".json")) ;

            StringBuilder jsonstr = new StringBuilder("{");
            bool falg = true;
            for (int j = 1; j < scvline.Length; j++)
            {
                string[] block = scvline[j].Split(',');
                int tempnum = 0;
                string key = block[tempnum];

                while (_isOddDoubleQuota(key))
                {
                    key += block[++tempnum];
                }

                tempnum = i;
                string value = block[tempnum];
                while (_isOddDoubleQuota(value))
                {
                    value += block[++tempnum];
                }

                if (key.StartsWith("\"") && key.EndsWith("\""))
                    key = key.Trim('"');
                if (value.StartsWith("\"") && value.EndsWith("\""))
                    value = value.Trim('"');

                if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value))
                    continue;
                if (falg)
                {
                    falg = false;
                    jsonstr.AppendLine("\"" + key + "\" :" + "\"" + value + "\"");

                }
                else
                {
                    jsonstr.AppendLine(",\"" + key + "\" :" + "\"" + value + "\"");

                }
            }
            jsonstr.AppendLine("}");

            File.WriteAllText(Application.dataPath + "/Data/" + Language[i] + ".json", jsonstr.ToString());

        }
        AssetDatabase.Refresh();
    }
    //引号个数
    private static int _getDoubleQuotaCount(string str)
    {
        string[] strArray = str.Split('"');
        int doubleQuotaCount = strArray.Length - 1;
        doubleQuotaCount = doubleQuotaCount < 0 ? 0 : doubleQuotaCount;
        return doubleQuotaCount;
    }
    //引号个数是否为双数
    private static bool _isOddDoubleQuota(string str)
    {
        return _getDoubleQuotaCount(str) % 2 == 1;
    }
}

四、从谷歌下载表格到本地

这里主要是因为项目组使用谷歌文档来实现共享文档办公,那么策划会将文件本地化的翻译文档放在Google,我们我们需要将其下载下来并且转换成josn,来实现文字本地化。
首先来演示一下我们需要一个什么样子的效果。
**在这里插入图片描述**
之后我们在Unity编辑器里面只需要输入dockey,即可获取等到文档的所有表格
在这里插入图片描述
然后我们选择需要下载的表格,点击Download就可以从谷歌文档下载到我们需要的csv表格。
在这里插入图片描述
接下来看看如何实现,首先来看看谷歌文档的url是什么样的。在这里插入图片描述
可以看到,如果我们需要下载某个表格,需要知道两个东西,第一个是dockey,第二个是gid,gid表示你具体下载这个文档中的那个表格。
在这里插入图片描述
我们需要获取到有多少个表格,分别是哪些表格,每个表格对应的gid是什么,再看看表格的下载链接时什么样的。
在这里插入图片描述
好的,我们知道了这些之后,再来具体看看怎么做,这边我直接上代码。之后会把需要注意的地方解释一下。


using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;


public class DownLoadCsvFromGoogle : EditorWindow
{
    public static List<string> downloadToggleString = new List<string>();
    public static  List<bool> downloadToggleBool = new List<bool>();
    public static List<string> gidList = new List<string>();
    private static string googleDocKey = "";
    
    public List<string> gid = new List<string>();

    [MenuItem("Tools/DownloadCsv")]
    static void Init()
    {
        DownLoadCsvFromGoogle window =
            (DownLoadCsvFromGoogle)EditorWindow.GetWindow(typeof(DownLoadCsvFromGoogle), true, "SpreadSheet Downloader");
        foreach (var VARIABLE in downloadToggleString)
        {
            downloadToggleBool.Add(false);
        }
    }


    
    private void OnGUI()
    {
        EditorGUILayout.Separator();
        googleDocKey = EditorGUILayout.TextField("GoogleDocKey", googleDocKey);
        EditorGUILayout.Separator();
        if (GUILayout.Button("Refresh SpreadSheet", GUILayout.ExpandWidth(true)))
        {
            if (string.IsNullOrEmpty(googleDocKey))
            {
                return;
            }
            
            GetSheetFormGoogle();
        }
        EditorGUILayout.Separator();
        EditorGUILayout.BeginHorizontal();
        if(GUILayout.Button("Select All",GUILayout.ExpandWidth(true)))
        {
            for (int i = 0; i < downloadToggleBool.Count; i++)
            {
                downloadToggleBool[i] = true;
            }
        }
        if(GUILayout.Button("UnSelect All",GUILayout.ExpandWidth(true)))
        {
            for (int i = 0; i < downloadToggleBool.Count; i++)
            {
                downloadToggleBool[i] = false;
            }   
        }
        EditorGUILayout.EndHorizontal();
        if (downloadToggleString.Count != 0)
        {
            for (int i = 0; i < downloadToggleString.Count; i++)
            {
                downloadToggleBool[i] = EditorGUILayout.Toggle(downloadToggleString[i], downloadToggleBool[i]);
            }
        }
        EditorGUILayout.Separator();
        if(GUILayout.Button("Download",GUILayout.ExpandWidth(true)))
        {
            downCsvToLocal();
        }
    }

    void downCsvToLocal()
    {
        for (int i = 0; i < downloadToggleBool.Count; i++)
        {
            if (downloadToggleBool[i])
            {
                string url = "https://docs.google.com/spreadsheets/d/" + googleDocKey + "/export?format=csv&id=" +
                             googleDocKey + "&gid=" + gidList[i];
                HttpWebRequest request = MakeWebRequest(url);
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                
                using (Stream st = response.GetResponseStream())
                {
                    using (StreamReader sr = new StreamReader(st,Encoding.UTF8))
                    {
                        string str = sr.ReadToEnd();
                        if (!Directory.Exists(Application.dataPath + "/CsvData/"))
                        {
                            Directory.CreateDirectory(Application.dataPath + "/CsvData/");
                        }
                        using (StreamWriter sw = File.CreateText(Application.dataPath + "/CsvData/" + downloadToggleString[i] + ".csv"))
                        {
                            sw.Write(str);
                        }
                    }
                }
                response.Close();
                request.Abort();
            }
        }
        AssetDatabase.Refresh();
    }
    
     void GetSheetFormGoogle()
     {
         string url = "https://docs.google.com/spreadsheets/d/" + googleDocKey;
         System.Net.ServicePointManager.DefaultConnectionLimit = 50;
         HttpWebRequest request = MakeWebRequest(url);
         HttpWebResponse response = request.GetResponse() as HttpWebResponse;
         string retString = string.Empty;
         using (Stream st = response.GetResponseStream())
         {
             using (StreamReader sr = new StreamReader(st,Encoding.UTF8))
             {
                 retString = sr.ReadToEnd();
             }
         }
         response.Close();
         request.Abort();
         Debug.Log(retString);
         Regex reg = new Regex("(?<=<div class=\"goog-inline-block docs-sheet-tab-caption\">)(.*?)(?=</div>)", RegexOptions.IgnoreCase);
         MatchCollection ms = reg.Matches( retString );
         downloadToggleString.Clear();
         downloadToggleBool.Clear();
         foreach (var VARIABLE in ms)
         {
             downloadToggleString.Add(VARIABLE.ToString());
             downloadToggleBool.Add(false);
         }

         Getgid(retString);
     }

     public void Getgid( string resqstr )
     {
         gidList.Clear();
         string[] strs = resqstr.Split(',');

         int number = 0;
         
         for (int i = 0; i < downloadToggleString.Count; i++)
         {
             for (int j = number; j < strs.Length; j++)
             {
                 if (strs[j].Contains(downloadToggleString[i]))
                 {
                     number = j;
                     if(i != 0)
                         break;
                 }
             }
             gidList.Add(strs[number - 3].Replace("\\\"",""));
         }
     }
     public  HttpWebRequest MakeWebRequest(string url)
     {
         HttpWebRequest request = null;
         
         if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
         {
             ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
             request = WebRequest.Create(url) as HttpWebRequest;
             request.ProtocolVersion = HttpVersion.Version11;
             
         }
         else
         {
             request = WebRequest.Create(url) as HttpWebRequest;
         }
         //由于是谷歌文档,所以需要开启代理选项,我这里没开。
         //WebProxy proxy = new WebProxy("127.0.0.1",8001);
         //request.Proxy = proxy;
         request.Method = "GET";
         request.KeepAlive = false;
         request.AllowAutoRedirect = true;
         return request;
     }
    
     private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
     {
         return true; 
     }
    
}

这里需要注意的几个点

  • 首先在unity编辑器模式下,是没法使用www和UnityWebRequest,没法使用Unity中的携程,当然网上有大佬写出可以编辑器下使用协程的工具,我这里没有用,直接用 .NET 的HttpWebRequest,这里.NET提供了很多web方法,比如:WebRequest、HttpWebRequest、WebClient、HttpClient。这些web类的区别,我这里简单抄了一点别人的总结。
    ebRequest/HttpWebRequest/HttpRequest/WebClient/HttpClient的区别
  1. WebRequest 的命名空间是: System.Net ,它是HttpWebRequest的抽象父类(还有其他子类如FileWebRequest ,FtpWebRequest),WebRequest的子类都用于从web获取资源。HttpWebRequest利用HTTP 协议和服务器交互,通常是通过 GET 和 POST 两种方式来对数据进行获取和提交。
  2. HttpRequest 类的命名空间是:System.Web,它是一个密封类,其作用是 让服务端读取客户端发送的请求,我们最熟悉的HttpRequest的实例应该是WebForm中Page类的属性Request了,我们可以轻松地从Request属性的QueryString,Form,Cookies集合获取数据中,也可以通过Request[“Key”]获取自定义数据。
  3. WebClient 命名空间是System.Net,WebClient很轻量级的访问Internet资源的类,在指定uri后可以发送和接受数据。WebClient提供了 DownLoadData,DownLoadFile,UploadData,UploadFile 方法,同时通过了这些方法对应的异步方法,通过WebClient我们可以很方便地上传和下载文件。
  4. HttpClient 是.NET4.5引入的一个HTTP客户端库,其命名空间为 System.Net.Http 。.NET 4.5之前我们可能使用WebClient和HttpWebRequest来达到相同目的。HttpClient利用了最新的面向任务模式,使得处理异步请求非常容易。
  • 第二点是下载 谷歌文档可能需要代理,可以自己设置代理,不然会超时。
  • 还有就是https 的 ssl问题了,我这边代码也有处理https的情况.
  • 最后关于获取gid和表格列表,需要分析谷歌html页面,我们通过字符串截取来获取,这块代码里写的比较清楚了,如果有不清楚的,去试一下就明白了。
iostream1000 发布了5 篇原创文章 · 获赞 0 · 访问量 237 私信 关注

标签:string,mvvm,request,System,value,json,key,using,csv
来源: https://blog.csdn.net/zhangjinlong1234/article/details/104597964

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有