Unity notes - common small function integration

   Organize records of commonly used functions (some relatively simple function implementation collections (some better solutions found on the Internet) are placed here)

Table of contents

console print

deep copy

Objects move with the mouse

The UI moves with the player (Canvas can be overlaid in screen coordinates or world coordinates)

Easy Archiving Tool

Sprite font usage

API to prevent mouse rays from penetrating the UI

UniWebview cannot load Https solution

AB package loading widget

Singleton

Unity object looking at mouse

Unity applet released

GoogleProtobuf uses learning links

Adrressable Tutorial

material site

Convert digital to KBT unit 


console print

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ConsoleToSceen : MonoBehaviour
{
    const int maxLines = 50;
    const int maxLineLength = 120;
    private string _logStr = "";

    private readonly List<string> _lines = new List<string>();
    void OnEnable() { Application.logMessageReceived += Log; }
    void OnDisable() { Application.logMessageReceived -= Log; }
    void Update() { }

    public void Log(string logString, string stackTrace, LogType type)
    {
        foreach (var line in logString.Split('\n'))
        {
            if (line.Length <= maxLineLength)
            {
                _lines.Add(line);
                continue;
            }
            var lineCount = line.Length / maxLineLength + 1;
            for (int i = 0; i < lineCount; i++)
            {
                if ((i + 1) * maxLineLength <= line.Length)
                {
                    _lines.Add(line.Substring(i * maxLineLength, maxLineLength));
                }
                else
                {
                    _lines.Add(line.Substring(i * maxLineLength, line.Length - i * maxLineLength));
                }
            }
        }
        if (_lines.Count > maxLines)
        {
            _lines.RemoveRange(0, _lines.Count - maxLines);
        }
        _logStr = string.Join("\n", _lines);
    }

    void OnGUI()
    {
        GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity,
           new Vector3(Screen.width / 1200.0f, Screen.height / 800.0f, 1.0f));
        GUI.Label(new Rect(10, 10, 800, 370), _logStr, new GUIStyle() { fontSize = 30 });
    }
}

deep copy

	public static T DeepCopyByReflection<T>(T obj)
	{
		if (obj is string || obj.GetType().IsValueType)
			return obj;

		object retval = Activator.CreateInstance(obj.GetType());
		FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
		foreach (var field in fields)
		{
			try
			{
				field.SetValue(retval, DeepCopyByReflection(field.GetValue(obj)));
			}
			catch { }
		}

		return (T)retval;
	}

Objects move with the mouse

private Vector3 cubeScreenPos;

    private Vector3 mouseScreenPos;

    private Vector3 objOffset;// 偏移

    private void OnMouseDown()

    {
        Vector3 screenPos = Camera.main.WorldToScreenPoint(transform.position);

        mouseScreenPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPos.z);

        objOffset = transform.position - Camera.main.ScreenToWorldPoint(mouseScreenPos);

    }

    private void OnMouseDrag()

    {

        //为什么要先把cube转化为屏幕坐标?这样可以保证cube的z轴坐标不变

        cubeScreenPos = Camera.main.WorldToScreenPoint(transform.position);

        mouseScreenPos.x = Input.mousePosition.x;

        mouseScreenPos.y = Input.mousePosition.y;

        mouseScreenPos.z = cubeScreenPos.z;

        Vector3 endPos = Camera.main.ScreenToWorldPoint(mouseScreenPos) + objOffset;

        //  transform.Translate(new Vector3(endPos.x, transform.position.y, transform.position.z) * Time.deltaTime, Space.World);

        //transform.Translate(new Vector3(endPos.x, endPos.y, endPos.z) * Time.deltaTime, Space.World);

        transform.position = new Vector3(endPos.x, transform.position.y, transform.position.z);

        // transform.

    }

The UI moves with the player (Canvas can be overlaid in screen coordinates or world coordinates)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIContraller : MonoBehaviour
{
	public GameObject player;
	public Camera cam;
	// Update is called once per frame
	void Update()
	{
		CalPosition();
		//	Vector2 pos = Camera.main.WorldToScreenPoint(player.transform.position);
		//	GetComponent<RectTransform>().localPosition = pos;
	}
	public Vector3 Offset = new Vector3(0, 1, 0);
	private void CalPosition()
	{
		Vector3 vector3 = Vector3.zero;
		Vector3 screenPosition = cam.WorldToScreenPoint(player.transform.position + Offset);//将目标物体的坐标转化为屏幕坐标
		Vector3 uiPosition = Vector3.zero;
		//;//将得到的屏幕坐标转化为UGUI坐标
		if (RectTransformUtility.ScreenPointToWorldPointInRectangle(transform as RectTransform, screenPosition, null, out uiPosition))
		{
			uiPosition = new Vector3(Mathf.FloorToInt(uiPosition.x), Mathf.FloorToInt(uiPosition.y), Mathf.FloorToInt(uiPosition.z));
			transform.position = uiPosition;
		}
	}

}

Control the UI display order: the UI is controlled according to the camera, the layer order under the canvas is useless, and the Canvas display depth can be set by controlling the depth value of the camera

The ratio of the Canvas of the world coordinates to the world coordinates is 100:1, set the Canvas scaling to 0.01, and set the coordinates directly

go.GetComponent<RectTransform>().position = Entity.transform.position;

The new version of VSCode code does not prompt:

Search Snippet, modify "editor.suggest.snippetsPreventQuickSuggestions" in settingJson: false

Easy Archiving Tool

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEditor;
public static class SaveJson
{
	public static void WriteToJson(string fileName, object data)
	{
		var json = JsonUtility.ToJson(data, true);
		Debug.Log(json);
		var path = Path.Combine(Application.persistentDataPath, fileName);
		try
		{
			File.WriteAllText(path, json);
		}
		catch (System.Exception e)
		{
			Debug.LogError("未能写入到该json文件" + e);
		}
	}
	public static T ReadJsonFile<T>(string fileName, object data)
	{
		var path = Path.Combine(Application.persistentDataPath, fileName);

		try
		{
			string file = null;
			if (!File.Exists(path))
			{
				WriteToJson(fileName, data);
				file = File.ReadAllText(path);
			}
			else
			{
				file = File.ReadAllText(path);
			}
			var json = JsonUtility.FromJson<T>(file);
			return json;
		}
		catch (System.Exception e)
		{

			Debug.LogError("无法读取当前文件" + e);
			return default;
		}

	}
	public static void DeleteAllJson(string fileName)
	{
		var path = Path.Combine(Application.persistentDataPath, fileName);
		try
		{
			File.Delete(path);
		}
		catch (System.Exception e)
		{
			Debug.LogError("未能成功删除存档" + e);
		}

	}


}

Sprite font usage

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEditor;
public class SetTTf : MonoBehaviour
{
	//本方法是通过裁切的sprite导出字体文件,裁切使用的是unity自带的sprite editor,方便操作。
	//另外,裁切之后,每个sprite的名字的最后一个字符对应了ascii码的编码,比如:
	//0: 我们只要将sprite的名字命名成xxx0,就可以了!
	//由于使用到的了sprite加载,所以字体图片请放在Resources目录下面,等制作完毕,再把他们放到fonts文件夹或者其他文件夹中即可。
	[MenuItem("SetTTf/CreateMyFontSprite")]
	static void CreateMyFontSprite()
	{
		if (Selection.objects == null) return;
		if (Selection.objects.Length == 0)
		{
			Debug.LogWarning("没有选中Sprite文件,需要将Sprite Mode设置成Multiple,切分好,并且以以名字的最后一个字符当做ascii码");
			return;
		}
		string resoursePath = "Resources";
		Object o = Selection.objects[0];
		if (o.GetType() != typeof(Texture2D))
		{
			Debug.LogWarning("选中的并不是图片文件");
			return;
		}
		string selectionPath = AssetDatabase.GetAssetPath(o);
		if (selectionPath.Contains(resoursePath))
		{
			string selectionExt = Path.GetExtension(selectionPath);
			if (selectionExt.Length == 0)
			{
				return;
			}
			string loadPath = selectionPath.Remove(selectionPath.Length - selectionExt.Length);
			string fontPathName = loadPath + ".fontsettings";
			string matPathName = loadPath + ".mat";
			float lineSpace = 0.1f;//字体行间距,下面会根据最高的字体得到行间距,如果是固定高度,可以在这里自行调整
			loadPath = Path.GetFileNameWithoutExtension(selectionPath);
			Sprite[] sprites = Resources.LoadAll<Sprite>(loadPath);
			if (sprites.Length > 0)
			{
				//以textrue方式获得该资源,可以设置到创建的材质中去
				Texture2D tex = o as Texture2D;
				//创建字体材质,并且将图片设置好
				Material mat = new Material(Shader.Find("GUI/Text Shader"));
				AssetDatabase.CreateAsset(mat, matPathName);
				mat.SetTexture("_MainTex", tex);
				//创建字体文件,设置字体文件的材质
				Font m_myFont = new Font();
				m_myFont.material = mat;
				AssetDatabase.CreateAsset(m_myFont, fontPathName);
				//创建字体中的字符集数组
				CharacterInfo[] characterInfo = new CharacterInfo[sprites.Length];
				//得到最高的高度,设置行高和进行偏移计算
				for (int i = 0; i < sprites.Length; i++)
				{
					if (sprites[i].rect.height > lineSpace)
					{
						lineSpace = sprites[i].rect.height;
					}
				}
				for (int i = 0; i < sprites.Length; i++)
				{
					Sprite spr = sprites[i];
					CharacterInfo info = new CharacterInfo();
					//设置ascii码,使用切分sprite的最后一个字母
					info.index = (int)spr.name[spr.name.Length - 1];
					Rect rect = spr.rect;
					//根据pivot设置字符的偏移,具体需要做成什么样的,可以根据自己需要修改公式
					float pivot = spr.pivot.y / rect.height - 0.5f;
					if (pivot > 0)
					{
						pivot = -lineSpace / 2 - spr.pivot.y;
					}
					else if (pivot < 0)
					{
						pivot = -lineSpace / 2 + rect.height - spr.pivot.y;
					}
					else
					{
						pivot = -lineSpace / 2;
					}
					Debug.Log(pivot);
					int offsetY = (int)(pivot + (lineSpace - rect.height) / 2);
					//设置字符映射到材质上的坐标
					info.uvBottomLeft = new Vector2((float)rect.x / tex.width, (float)(rect.y) / tex.height);
					info.uvBottomRight = new Vector2((float)(rect.x + rect.width) / tex.width, (float)(rect.y) / tex.height);
					info.uvTopLeft = new Vector2((float)rect.x / tex.width, (float)(rect.y + rect.height) / tex.height);
					info.uvTopRight = new Vector2((float)(rect.x + rect.width) / tex.width, (float)(rect.y + rect.height) / tex.height);
					//设置字符顶点的偏移位置和宽高
					info.minX = 0;
					info.minY = -(int)rect.height - offsetY;
					info.maxX = (int)rect.width;
					info.maxY = -offsetY;
					//设置字符的宽度
					info.advance = (int)rect.width;
					characterInfo[i] = info;
				}
				// lineSpace += 2;
				m_myFont.characterInfo = characterInfo;
				EditorUtility.SetDirty(m_myFont);//设置变更过的资源
				AssetDatabase.SaveAssets();//保存变更的资源
				AssetDatabase.Refresh();//刷新资源,貌似在Mac上不起作用

				//由于上面fresh之后在编辑器中依然没有刷新,所以暂时想到这个方法,
				//先把生成的字体导出成一个包,然后再重新导入进来,这样就可以直接刷新了
				//这是在Mac上遇到的,不知道Windows下面会不会出现,如果不出现可以把下面这一步注释掉
				AssetDatabase.ExportPackage(fontPathName, "temp.unitypackage");
				AssetDatabase.DeleteAsset(fontPathName);
				AssetDatabase.ImportPackage("temp.unitypackage", true);
				AssetDatabase.Refresh();

				//最佳高度:上下各留一个像素的间距,如果不需要可以注释掉,根据需求更改
				//打印是为了使使用者方便填写行高,因为font不支持设置行高。
				Debug.Log("创建字体成功, 最大高度:" + lineSpace + ", 最佳高度:" + (lineSpace + 2));
			}
			else
			{
				Debug.LogWarning("没有选中Sprite文件,需要将Sprite放到Resources文件夹下面,可以参考函数上方的说明操作");
			}
		}
	}
}

API to prevent mouse rays from penetrating the UI

	if (!EventSystem.current.IsPointerOverGameObject())
		{
			//
		}

UniWebview cannot load Https solution

网址https://blog.csdn.net/boyZhenGui/article/details/121250008

UniWebView,是一个支持安卓,ios和mac系统的网页插件(Windows不可用,意味着Windows系统的Unity编辑器无法看到效果,只有打包放到手机上才可以看到效果)。

原因
出现ERR_CLEARTEXT_NOT_PERMITTED这个报错的原因,在于安卓。从Android 9.0(API级别28)开始,默认情况下禁用明文支持。因此http的url均无法在webview中加载。

解决方案
所以我们需要在安卓的清单中AndroidManifest.xml,添加可以加载http的标签。

在Unity中完成修改AndroidManifest.xml
在Unity中无AndroidManifest.xml文件的情况下。Unity默认情况会根据插件中的所有 Android 清单,和打包设置,自动生成一份清单文件AndroidManifest.xml。

如果Unity中Assets/Plugins/Android/AndroidManifest.xml,有清单文件,则会使用此清单。

对于在Unity中的安卓清单详细解释可以看Unity官方手册。

网上找到的清单都不符合Unity需求,我们需要得到Unity需要的清单文件。

一、打包apk,得到Unity自动生成的最终清单文件AndroidManifest.xml
打包成功apk后,在关闭Unity编辑器之前,在Temp/StagingArea/AndroidManifest.xml 可以找到此apk使用的最终清单。

二、将最终清单文件放到Unity中
复制步骤一中得到的清单,放到如下链接Assets/Plugins/Android/AndroidManifest.xml。

三、修改AndroidManifest.xml
打开AndroidManifest.xml,找到标签, 在里面加入android:usesCleartextTraffic="true"即可,这个代码标表示可以使用http明文传输,

解决方法:找到AndroidManifest.xml的方法=“找到Player下安卓的发布设置找到custom mina manifest”;或者在unity主程序找相同文件复制
<application android:usesCleartextTraffic="true">

AB package loading widget


using System.Net.Mime;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

    /// <summary>
    /// AB包管理器 全局唯一 使用单例模式
    /// </summary>
    public class ABManager : MonoSingleton<ABManager>
    {
        //AB包缓存---解决AB包无法重复加载的问题 也有利于提高效率。
        private Dictionary<string, AssetBundle> abCache=new Dictionary<string, AssetBundle>();

        private AssetBundle mainAB = null; //主包

        private AssetBundleManifest mainManifest = null; //主包中配置文件---用以获取依赖包

        //各个平台下的基础路径 --- 利用宏判断当前平台下的streamingAssets路径
        private string basePath
        {
            get
            {
                //使用StreamingAssets路径注意AB包打包时 勾选copy to streamingAssets
#if UNITY_EDITOR || UNITY_STANDALONE
                return Application.dataPath + "/StreamingAssets/";
#elif UNITY_IPHONE
                return Application.dataPath + "/Raw/";
#elif UNITY_ANDROID
                return Application.dataPath + "!/assets/";
#endif
            }
        }
        //各个平台下的主包名称 --- 用以加载主包获取依赖信息
        private string mainABName
        {
            get
            {
#if UNITY_EDITOR || UNITY_STANDALONE
                return "StandaloneWindows";
#elif UNITY_IPHONE
                return "IOS";
#elif UNITY_ANDROID
                return "Android";
#endif
            }
        }

     


        //加载AB包
        private AssetBundle LoadABPackage(string abName)
        {
            AssetBundle ab;
            //加载ab包,需一并加载其依赖包。
            if (mainAB == null)
            {
                //根据各个平台下的基础路径和主包名加载主包
                mainAB = AssetBundle.LoadFromFile(basePath + mainABName);
                //获取主包下的AssetBundleManifest资源文件(存有依赖信息)
                mainManifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
            }
            //根据manifest获取所有依赖包的名称 固定API
            string[] dependencies = mainManifest.GetAllDependencies(abName);
            //循环加载所有依赖包
            for (int i = 0; i < dependencies.Length; i++)
            {
                //如果不在缓存则加入
                if (!abCache.ContainsKey(dependencies[i]))
                {
                    //根据依赖包名称进行加载
                    ab = AssetBundle.LoadFromFile(basePath + dependencies[i]);
                    //注意添加进缓存 防止重复加载AB包
                    abCache.Add(dependencies[i], ab);
                }
            }
            //加载目标包 -- 同理注意缓存问题
            if (abCache.ContainsKey(abName)) return abCache[abName];
            else
            {
                ab = AssetBundle.LoadFromFile(basePath + abName);
                abCache.Add(abName, ab);
                return ab;
            }


        }


        //==================三种资源同步加载方式==================
        //提供多种调用方式 便于其它语言的调用(Lua对泛型支持不好)
        #region 同步加载的三个重载

        /// <summary>
        /// 同步加载资源---泛型加载 简单直观 无需显示转换
        /// </summary>
        /// <param name="abName">ab包的名称</param>
        /// <param name="resName">资源名称</param>
        public T LoadResource<T>(string abName, string resName) where T : UnityEngine. Object
        {
            //加载目标包
            AssetBundle ab = LoadABPackage(abName);

            //返回资源
            return ab.LoadAsset<T>(resName);
        }


        //不指定类型 有重名情况下不建议使用 使用时需显示转换类型
        public Object LoadResource(string abName, string resName)
        {
            //加载目标包
            AssetBundle ab = LoadABPackage(abName);

            //返回资源
            return ab.LoadAsset(resName);
        }


        //利用参数传递类型,适合对泛型不支持的语言调用,使用时需强转类型
        public Object LoadResource(string abName, string resName, System.Type type)
        {
            //加载目标包
            AssetBundle ab = LoadABPackage(abName);

            //返回资源
            return ab.LoadAsset(resName, type);
        }

        #endregion


        //================三种资源异步加载方式======================

        /// <summary>
        /// 提供异步加载----注意 这里加载AB包是同步加载,只是加载资源是异步
        /// </summary>
        /// <param name="abName">ab包名称</param>
        /// <param name="resName">资源名称</param>
        public void LoadResourceAsync(string abName, string resName, System.Action<Object> finishLoadObjectHandler)
        {
            AssetBundle ab = LoadABPackage(abName);
            //开启协程 提供资源加载成功后的委托
            StartCoroutine(LoadRes(ab, resName, finishLoadObjectHandler));
        }


        private IEnumerator LoadRes(AssetBundle ab, string resName, System.Action<Object> finishLoadObjectHandler)
        {
            if (ab == null) yield break;
            //异步加载资源API
            AssetBundleRequest abr = ab.LoadAssetAsync(resName);
            yield return abr;
            //委托调用处理逻辑
            finishLoadObjectHandler(abr.asset);
        }


        //根据Type异步加载资源
        public void LoadResourceAsync(string abName, string resName, System.Type type, System.Action<Object> finishLoadObjectHandler)
        {
            AssetBundle ab = LoadABPackage(abName);
            StartCoroutine(LoadRes(ab, resName, type, finishLoadObjectHandler));
        }


        private IEnumerator LoadRes(AssetBundle ab, string resName, System.Type type, System.Action<Object> finishLoadObjectHandler)
        {
            if (ab == null) yield break;
            AssetBundleRequest abr = ab.LoadAssetAsync(resName, type);
            yield return abr;
            //委托调用处理逻辑
            finishLoadObjectHandler(abr.asset);
        }


        //泛型加载
        public void LoadResourceAsync<T>(string abName, string resName, System.Action<Object> finishLoadObjectHandler) where T : Object
        {
            AssetBundle ab = LoadABPackage(abName);
            StartCoroutine(LoadRes<T>(ab, resName, finishLoadObjectHandler));
        }

        private IEnumerator LoadRes<T>(AssetBundle ab, string resName, System.Action<Object> finishLoadObjectHandler) where T : Object
        {
            if (ab == null) yield break;
            AssetBundleRequest abr = ab.LoadAssetAsync<T>(resName);
            yield return abr;
            //委托调用处理逻辑
            finishLoadObjectHandler(abr.asset as T);
        }


        //====================AB包的两种卸载方式=================
        //单个包卸载
        public void UnLoad(string abName)
        {
            if (abCache.ContainsKey(abName))
            {
                abCache[abName].Unload(false);
                //注意缓存需一并移除
                abCache.Remove(abName);
            }
        }

        //所有包卸载
        public void UnLoadAll()
        {
            AssetBundle.UnloadAllAssetBundles(false);
            //注意清空缓存
            abCache.Clear();
            mainAB = null;
            mainManifest = null;
        }
    }


Singleton

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 无需挂载直接调用即可
/// </summary>
/// <typeparam name="T"></typeparam>
public class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
	private static T instance;
	public static T Instance
	{
		get
		{
			if (instance == null)
			{
				instance = FindObjectOfType(typeof(T)) as T;
				if (instance == null)
				{
					GameObject go = new GameObject();
					go.name = typeof(T).ToString();
					instance = go.AddComponent<T>();
				}
			}
			return instance;
		}
	}
	/// <summary>
	/// 如果需要跟随场景在Awake中调用Init即可
	/// </summary>
	protected void Init()
	{	
		DontDestroyOnLoad(gameObject);
		if (instance == null)
		{
			instance = this as T;
		}
		else
		{
			Destroy(gameObject);
		}
	}



}

Unity object looking at mouse

	public LayerMask whatIsGround;

	// Update is called once per frame
	void Update()
	{
		GetPos();
	}
	void GetPos()
	{
		Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
		RaycastHit hitInfo;
		if (Physics.Raycast(ray, out hitInfo, 200, whatIsGround))
		{
			Vector3 target = hitInfo.point;
			target.y = transform.position.y;
			transform.LookAt(target);
		}
	}

Unity applet released

Unity Docking Douyin

GoogleProtobuf uses learning links

How protobuf uses the Protogen tool to generate CS code detailed teaching articles_Little、Seven's Blog-CSDN Blog_protobuf protogen

Adrressable Tutorial

[Game development exploration] Unity Addressables resource management method is so cool to use, resource packaging, loading, hot update become so easy (Addressable Asset System | AA for short)_Lin Xinfa's Blog-CSDN Blog

Unity Addressable publishes to the server process and automatically packages the code_Lexus·C Blog-CSDN Blog

material site

Alibaba Vector Library, Address: iconfont-Alibaba Vector Icon Library 

How to adjust the 3D physical model you want to display (for example, the full body is displayed only when it is close, and the base model is displayed when it is far away, just add this component)

Adjust shadow distance

Npm related

npm install third-party plug-in (moment.js)_weixin_44134551's blog-CSDN blog_npm install moment

https://blog.csdn.net/lenfranky/article/details/90177121

How to conveniently and quickly open cmd in a specified folder

Convert digital to KBT unit 

/// <summary>
	/// 数字换算
	/// </summary>
	/// <param name="num"></param>
	/// <returns></returns>
	public string Numdispose(double Allcount)
	{
		string num = Allcount.ToString();
		if (Allcount < 999)
		{
			return num;
		}

		string[] symbol = { "K", "M", "B", "T", "aa", "ab", "ac", "ad" };
		bool isSciece = false;
		bool isInt = false;
		if (Allcount > 999999999999999)
		{
			isSciece = true;
		}
		int endLength;

		if (isSciece)
		{
			int len = num.Length;
			string lengStr = num.Substring(len - 2, 2);
			int taille = int.Parse(lengStr);
			//Debug.Log(lengStr + "      " + taille);
			endLength = taille + 1;
			//TODO
			if (num.Contains("."))
			{
				num = num.Remove(1, 1);

			}
			else
			{
				isInt = true;
			}

		}
		else
		{
			endLength = num.Length; ;
		}
		int remainCount = endLength / 3;

		string sym = symbol[remainCount - 1];
		int reNum = endLength % 3;
		if (reNum == 0)
		{
			reNum = 3;
			sym = symbol[remainCount - 2];
		}
		string head = num.Substring(0, reNum);
		string tail = num.Substring(reNum, 2);
		num = head + "." + tail + sym;// + sym;
		if (isInt)
		{
			num = 10 * reNum + sym;
		}
		//Debug.Log(num);
		return num;
	}

Guess you like

Origin blog.csdn.net/qq_55042292/article/details/125427953