热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Unity笔记—常用小功能整合

常用功能整理记录(一些比较简单的功能实现集合(网上找的一些比较好的解决方案)放在这里)目录控制台打印深拷贝物体跟随鼠

   常用功能整理记录(一些比较简单的功能实现集合(网上找的一些比较好的解决方案)放在这里)

目录

控制台打印

深拷贝

物体跟随鼠标移动

UI跟随玩家移动(Canvas在屏幕坐标覆盖或者世界坐标皆可)

简易存档工具

Sprite字体使用

防止鼠标射线穿透UI的API

UniWebview无法加载Https解决办法

AB包加载小工具

Singleton

Unity物体看向鼠标

Unity小程序发布

GoogleProtobuf使用学习链接

Adrressable教程






控制台打印

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 _lines = new List();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(&#39;\n&#39;)){if (line.Length <= maxLineLength){_lines.Add(line);continue;}var lineCount = line.Length / maxLineLength + 1;for (int i = 0; i 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 });}
}

深拷贝

public static T DeepCopyByReflection(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;}

物体跟随鼠标移动

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


UI跟随玩家移动(Canvas在屏幕坐标覆盖或者世界坐标皆可)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class UIContraller : MonoBehaviour
{public GameObject player;public Camera cam;// Update is called once per framevoid Update(){CalPosition();// Vector2 pos = Camera.main.WorldToScreenPoint(player.transform.position);// GetComponent().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;}}}

控制UI显示顺序:UI是根据摄像机控制的,canvas下的图层顺序没用,控制摄像机的深度值即可设置Canvas显示深度

世界坐标的Canvas和世界坐标比例100:1,设置Canvas缩放0.01,直接设置坐标即可

go.GetComponent().position = Entity.transform.position;

VSCode新版代码不提示:

搜索Snippet,settingJson中修改"editor.suggest.snippetsPreventQuickSuggestions": false


简易存档工具

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(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(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字体使用

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(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 lineSpace){lineSpace = sprites[i].rect.height;}}for (int i = 0; i 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文件夹下面,可以参考函数上方的说明操作");}}}
}

防止鼠标射线穿透UI的API

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

UniWebview无法加载Https解决办法

网址https://blog.csdn.net/boyZhenGui/article/details/121250008UniWebView,是一个支持安卓,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主程序找相同文件复制


AB包加载小工具


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

/// AB包管理器 全局唯一 使用单例模式/// public class ABManager : MonoSingleton{//AB包缓存---解决AB包无法重复加载的问题 也有利于提高效率。private Dictionary abCache=new Dictionary();private AssetBundle mainAB = null; //主包private AssetBundleManifest mainManifest = null; //主包中配置文件---用以获取依赖包//各个平台下的基础路径 --- 利用宏判断当前平台下的streamingAssets路径private string basePath{get{//使用StreamingAssets路径注意AB包打包时 勾选copy to streamingAssets
#if UNITY_EDITOR || UNITY_STANDALONEreturn Application.dataPath + "/StreamingAssets/";
#elif UNITY_IPHONEreturn Application.dataPath + "/Raw/";
#elif UNITY_ANDROIDreturn Application.dataPath + "!/assets/";
#endif}}//各个平台下的主包名称 --- 用以加载主包获取依赖信息private string mainABName{get{
#if UNITY_EDITOR || UNITY_STANDALONEreturn "StandaloneWindows";
#elif UNITY_IPHONEreturn "IOS";
#elif UNITY_ANDROIDreturn "Android";
#endif}}//加载AB包private AssetBundle LoadABPackage(string abName){AssetBundle ab;//加载ab包,需一并加载其依赖包。if (mainAB == null){//根据各个平台下的基础路径和主包名加载主包mainAB = AssetBundle.LoadFromFile(basePath + mainABName);//获取主包下的AssetBundleManifest资源文件(存有依赖信息)mainManifest = mainAB.LoadAsset("AssetBundleManifest");}//根据manifest获取所有依赖包的名称 固定APIstring[] dependencies = mainManifest.GetAllDependencies(abName);//循环加载所有依赖包for (int i = 0; i /// 同步加载资源---泛型加载 简单直观 无需显示转换/// ///

ab包的名称///

资源名称public T LoadResource(string abName, string resName) where T : UnityEngine. Object{//加载目标包AssetBundle ab = LoadABPackage(abName);//返回资源return ab.LoadAsset(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//================三种资源异步加载方式======================///

/// 提供异步加载----注意 这里加载AB包是同步加载,只是加载资源是异步/// ///

ab包名称///

资源名称public void LoadResourceAsync(string abName, string resName, System.Action finishLoadObjectHandler){AssetBundle ab = LoadABPackage(abName);//开启协程 提供资源加载成功后的委托StartCoroutine(LoadRes(ab, resName, finishLoadObjectHandler));}private IEnumerator LoadRes(AssetBundle ab, string resName, System.Action finishLoadObjectHandler){if (ab == null) yield break;//异步加载资源APIAssetBundleRequest abr = ab.LoadAssetAsync(resName);yield return abr;//委托调用处理逻辑finishLoadObjectHandler(abr.asset);}//根据Type异步加载资源public void LoadResourceAsync(string abName, string resName, System.Type type, System.Action finishLoadObjectHandler){AssetBundle ab = LoadABPackage(abName);StartCoroutine(LoadRes(ab, resName, type, finishLoadObjectHandler));}private IEnumerator LoadRes(AssetBundle ab, string resName, System.Type type, System.Action finishLoadObjectHandler){if (ab == null) yield break;AssetBundleRequest abr = ab.LoadAssetAsync(resName, type);yield return abr;//委托调用处理逻辑finishLoadObjectHandler(abr.asset);}//泛型加载public void LoadResourceAsync(string abName, string resName, System.Action finishLoadObjectHandler) where T : Object{AssetBundle ab = LoadABPackage(abName);StartCoroutine(LoadRes(ab, resName, finishLoadObjectHandler));}private IEnumerator LoadRes(AssetBundle ab, string resName, System.Action finishLoadObjectHandler) where T : Object{if (ab == null) yield break;AssetBundleRequest abr = ab.LoadAssetAsync(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;
///


/// 无需挂载直接调用即可
///

///
public class Singleton : MonoBehaviour where T : Singleton
{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();}}return instance;}}/// /// 如果需要跟随场景在Awake中调用Init即可/// protected void Init(){ DontDestroyOnLoad(gameObject);if (instance == null){instance = this as T;}else{Destroy(gameObject);}}}


Unity物体看向鼠标

public LayerMask whatIsGround;// Update is called once per framevoid 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小程序发布

Unity对接抖音_暗夜血媚的博客-CSDN博客_unity 抖音小游戏


GoogleProtobuf使用学习链接

protobuf如何使用Protogen工具生成CS代码详细教学篇_Little丶Seven的博客-CSDN博客_protobuf protogen


Adrressable教程

【游戏开发探究】Unity Addressables资源管理方式用起来太爽了,资源打包、加载、热更变得如此轻松(Addressable Asset System | 简称AA)_林新发的博客-CSDN博客

Unity Addressable发布至服务器流程与自动打包代码_凌志·C的博客-CSDN博客


素材网站


阿里巴巴矢量图库,地址:iconfont-阿里巴巴矢量图标库 

如何调节你想显示的3d物理模型(比如离得近才显示完全体,离得远显示底模,加上这个组件就可以)

调节阴影距离

Npm相关

npm 安装第三方插件(moment.js)_weixin_44134551的博客-CSDN博客_npm安装moment

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

如何方便快速的在指定文件夹打开cmd_LenFranky的博客-CSDN博客_在文件夹打开cmd


推荐阅读
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 集合的遍历方式及其局限性
    本文介绍了Java中集合的遍历方式,重点介绍了for-each语句的用法和优势。同时指出了for-each语句无法引用数组或集合的索引的局限性。通过示例代码展示了for-each语句的使用方法,并提供了改写为for语句版本的方法。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 生成对抗式网络GAN及其衍生CGAN、DCGAN、WGAN、LSGAN、BEGAN介绍
    一、GAN原理介绍学习GAN的第一篇论文当然由是IanGoodfellow于2014年发表的GenerativeAdversarialNetworks(论文下载链接arxiv:[h ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 本文介绍了在实现了System.Collections.Generic.IDictionary接口的泛型字典类中如何使用foreach循环来枚举字典中的键值对。同时还讨论了非泛型字典类和泛型字典类在foreach循环中使用的不同类型,以及使用KeyValuePair类型在foreach循环中枚举泛型字典类的优势。阅读本文可以帮助您更好地理解泛型字典类的使用和性能优化。 ... [详细]
  • 可空类型可空类型主要用于参数类型声明和函数返回值声明。主要的两种形式如下: ... [详细]
  • ListBox.SelectedItem.Value可以获取当前被选中的一个值.但如果ListBox同时有多个值被选中应该如何获取这些值呢? ... [详细]
  • 渗透测试基础bypass绕过阻挡我们的WAF(下)
    渗透测试基础-bypass ... [详细]
author-avatar
失败人一枚
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有