Unity中SendMessage和Delegate效率比较

最后更新于:2022-04-01 09:50:23

本文章由cartzhang编写,转载请注明出处。 所有权利保留。  文章链接: [http://blog.csdn.net/cartzhang/article/details/50686627](http://blog.csdn.net/cartzhang/article/details/50686627)  作者:cartzhang 网上直接搜的代码。需要的使用也简单,所以就不过多说明。  但是网上都说,他们之间的差距,delegate比较快,效果高。怎么个高法呢?还是自己来测试下时间。  故此,  个人之用来比较下时间差别。 ### 一、直接代码 ~~~ using UnityEngine; using System.Collections; /// <summary> /// Delegate basic. /// just test Delegate && SendMessage .. /// /// By Chiuan 2012.8 /// </summary> public class DelegateBasic : MonoBehaviour { static int loopNumber = 5000000; //define my delegate statement. public delegate void MyDelegate(string arg1); //create my delegate object public MyDelegate myDelegate; //need some values to debug time spent. bool isStart; float timeStart; int count; bool isStartSendMessage; // Use this for initialization void Start() { myDelegate += myFunciton1; //myDelegate += myFunciton2; } // Update is called once per frame void Update() { if (isStart) { isStart = false; count = 0; timeStart = Time.realtimeSinceStartup; Debug.Log("Start = " + timeStart); for (int i = 0; i < loopNumber; i++) { if (myDelegate != null) myDelegate(""); } } if (isStartSendMessage) { isStartSendMessage = false; count = 0; timeStart = Time.realtimeSinceStartup; Debug.Log("Start = " + timeStart); for (int i = 0; i < loopNumber; i++) { this.gameObject.SendMessage("myFunciton1", "", SendMessageOptions.DontRequireReceiver); } } } void OnGUI() { if (GUILayout.Button("INVOKE Delegate")) { isStart = true; } if (GUILayout.Button("SendMessage")) { isStartSendMessage = true; } } void myFunciton1(string s) { count++; if (count == loopNumber) { Debug.Log("End = " + Time.realtimeSinceStartup); Debug.Log("Time Spent = " + (Time.realtimeSinceStartup - timeStart)); } } } ~~~ ### 二、说明 代码基本没有做更改,删掉了没用的函数。也名字也带着呢!!在此表示感谢!!! 但说道具体测试,要每次都需要重新开始,才能计时。要不就会有问题,后测试的就会产生多次循环。 ### 三、效率比较 系统配置:”Win7 64位,i7处理器 16G内存,英伟达660显卡” ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda8869afc.jpg) 对比为倍数关系!!也就说,随着次数增加,效率差距越来越大!!! ### 相关链接: [https://unity3d.com/cn/learn/tutorials/modules/intermediate/scripting/delegates](https://unity3d.com/cn/learn/tutorials/modules/intermediate/scripting/delegates) [http://www.xuanyusong.com/archives/1895/](http://www.xuanyusong.com/archives/1895/) [http://blog.csdn.net/chiuan/article/details/7918833](http://blog.csdn.net/chiuan/article/details/7918833) 若有问题,请随时联系!!!  再次表示感谢!!!
';

Untiy中的数据平滑处理

最后更新于:2022-04-01 09:50:20

本文章由cartzhang编写,转载请注明出处。 所有权利保留。  文章链接:[http://blog.csdn.net/cartzhang/article/details/50680237](http://blog.csdn.net/cartzhang/article/details/50680237)  作者:cartzhang ### 数据平滑处理 由于需要处理硬件的传给数据,硬件是其他商家的。  坑爹的是发送频率太低了,20HZ左右,也是服气了。好处有么,肯定是便宜。  这个用在VR游戏上,不做评论了。  既然这样,生活还得继续!!!  怎么办? ### 插值 第一考虑的就是插值。  插值,内插和外推插值。插值算法,有多种,5点,7点,二次插值等,不一一列举。  游戏的帧率在DK2上75fps,这帧率插值,需要至少有2秒数据,再加上硬件数据的抖动,个人觉得这不算是个好的方案。 ### 缓动函数 在ITween中有个缓动曲线函数。  这个不错啊!我们来细说下。 ### 1.先看看各种函数都长啥样? 截图:  ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda882f19a.jpg) ### 2.网址介绍 相关网址啊:  [http://easings.net/zh-cn#](http://easings.net/zh-cn#) 说明网址上的各个图都是可以点开,动态的哦。 [http://robertpenner.com/easing/easing_demo.html](http://robertpenner.com/easing/easing_demo.html)  这个也是可以看看每个曲线的样子。真是方便啊!! 微软msdn上带有代码和图例的  [https://msdn.microsoft.com/zh-cn/library/ee308751.aspx](https://msdn.microsoft.com/zh-cn/library/ee308751.aspx) ### 3.在看看所有曲线种类。 可以在ITween中找到EaseType. ~~~ /// <summary> /// The type of easing to use based on Robert Penner's open source easing equations (http://www.robertpenner.com/easing_terms_of_use.html). /// </summary> public enum EaseType{ easeInQuad, easeOutQuad, easeInOutQuad, easeInCubic, easeOutCubic, easeInOutCubic, easeInQuart, easeOutQuart, easeInOutQuart, easeInQuint, easeOutQuint, easeInOutQuint, easeInSine, easeOutSine, easeInOutSine, easeInExpo, easeOutExpo, easeInOutExpo, easeInCirc, easeOutCirc, easeInOutCirc, linear, spring, /* GFX47 MOD START */ //bounce, easeInBounce, easeOutBounce, easeInOutBounce, /* GFX47 MOD END */ easeInBack, easeOutBack, easeInOutBack, /* GFX47 MOD START */ //elastic, easeInElastic, easeOutElastic, easeInOutElastic, /* GFX47 MOD END */ punch } ~~~ 根据需要各区所需啊!!不一定要全部都带上。 ### 4\. 函数代码: ITween中这个代码比较长,代码中更多的是算法。  代码在ITween.cs中,就不一一贴上来。 ### 缓动曲线代码 我需要的只有这些曲线,其他的不需要,就摘了出来,写成了静态函数,这样方便在需要时候直接调用。 ~~~ /************************************************************************** Copyright:@cartzhang Author: cartzhang Date: Description: **************************************************************************/ using UnityEngine; using System.Collections; public enum EaseType:int { easeInQuad, //easeOutQuad, easeInOutQuad, easeInCubic, //easeOutCubic, easeInOutCubic, easeInQuart, //easeOutQuart, easeInOutQuart, easeInQuint, //easeOutQuint, easeInOutQuint, //easeInSine, //easeOutSine, //easeInOutSine, easeInExpo, //easeOutExpo, easeInOutExpo, //easeInCirc, //easeOutCirc, easeInOutCirc, //linear, //spring, ///* GFX47 MOD START */ ////bounce, //easeInBounce, //easeOutBounce, //easeInOutBounce, ///* GFX47 MOD END */ //easeInBack, //easeOutBack, //easeInOutBack, ///* GFX47 MOD START */ ////elastic, //easeInElastic, //easeOutElastic, //easeInOutElastic, ///* GFX47 MOD END */ //punch } public class DataAlgorithm { #region Easing Curves public static float linear(float start, float end, float value) { return Mathf.Lerp(start, end, value); } public static float clerp(float start, float end, float value) { float min = 0.0f; float max = 360.0f; float half = Mathf.Abs((max - min) / 2.0f); float retval = 0.0f; float diff = 0.0f; if ((end - start) < -half) { diff = ((max - start) + end) * value; retval = start + diff; } else if ((end - start) > half) { diff = -((max - end) + start) * value; retval = start + diff; } else retval = start + (end - start) * value; return retval; } public static float spring(float start, float end, float value) { value = Mathf.Clamp01(value); value = (Mathf.Sin(value * Mathf.PI * (0.2f + 2.5f * value * value * value)) * Mathf.Pow(1f - value, 2.2f) + value) * (1f + (1.2f * (1f - value))); return start + (end - start) * value; } public static float easeInQuad(float start, float end, float value) { end -= start; return end * value * value + start; } public static float easeOutQuad(float start, float end, float value) { end -= start; return -end * value * (value - 2) + start; } public static float easeInOutQuad(float start, float end, float value) { value /= .5f; end -= start; if (value < 1) return end / 2 * value * value + start; value--; return -end / 2 * (value * (value - 2) - 1) + start; } public static float easeInCubic(float start, float end, float value) { end -= start; return end * value * value * value + start; } public static float easeOutCubic(float start, float end, float value) { value--; end -= start; return end * (value * value * value + 1) + start; } public static float easeInOutCubic(float start, float end, float value) { value /= .5f; end -= start; if (value < 1) return end / 2 * value * value * value + start; value -= 2; return end / 2 * (value * value * value + 2) + start; } public static float easeInQuart(float start, float end, float value) { end -= start; return end * value * value * value * value + start; } public static float easeOutQuart(float start, float end, float value) { value--; end -= start; return -end * (value * value * value * value - 1) + start; } public static float easeInOutQuart(float start, float end, float value) { value /= .5f; end -= start; if (value < 1) return end / 2 * value * value * value * value + start; value -= 2; return -end / 2 * (value * value * value * value - 2) + start; } public static float easeInQuint(float start, float end, float value) { end -= start; return end * value * value * value * value * value + start; } public static float easeOutQuint(float start, float end, float value) { value--; end -= start; return end * (value * value * value * value * value + 1) + start; } public static float easeInOutQuint(float start, float end, float value) { value /= .5f; end -= start; if (value < 1) return end / 2 * value * value * value * value * value + start; value -= 2; return end / 2 * (value * value * value * value * value + 2) + start; } public static float easeInSine(float start, float end, float value) { end -= start; return -end * Mathf.Cos(value / 1 * (Mathf.PI / 2)) + end + start; } public static float easeOutSine(float start, float end, float value) { end -= start; return end * Mathf.Sin(value / 1 * (Mathf.PI / 2)) + start; } public static float easeInOutSine(float start, float end, float value) { end -= start; return -end / 2 * (Mathf.Cos(Mathf.PI * value / 1) - 1) + start; } public static float easeInExpo(float start, float end, float value) { end -= start; return end * Mathf.Pow(2, 10 * (value / 1 - 1)) + start; } public static float easeOutExpo(float start, float end, float value) { end -= start; return end * (-Mathf.Pow(2, -10 * value / 1) + 1) + start; } public static float easeInOutExpo(float start, float end, float value) { value /= .5f; end -= start; if (value < 1) return end / 2 * Mathf.Pow(2, 10 * (value - 1)) + start; value--; return end / 2 * (-Mathf.Pow(2, -10 * value) + 2) + start; } public static float easeInCirc(float start, float end, float value) { end -= start; return -end * (Mathf.Sqrt(1 - value * value) - 1) + start; } public static float easeOutCirc(float start, float end, float value) { value--; end -= start; return end * Mathf.Sqrt(1 - value * value) + start; } public static float easeInOutCirc(float start, float end, float value) { value /= .5f; end -= start; if (value < 1) return -end / 2 * (Mathf.Sqrt(1 - value * value) - 1) + start; value -= 2; return end / 2 * (Mathf.Sqrt(1 - value * value) + 1) + start; } /* GFX47 MOD START */ public static float easeInBounce(float start, float end, float value) { end -= start; float d = 1f; return end - easeOutBounce(0, end, d - value) + start; } /* GFX47 MOD END */ /* GFX47 MOD START */ //public static float bounce(float start, float end, float value){ public static float easeOutBounce(float start, float end, float value) { value /= 1f; end -= start; if (value < (1 / 2.75f)) { return end * (7.5625f * value * value) + start; } else if (value < (2 / 2.75f)) { value -= (1.5f / 2.75f); return end * (7.5625f * (value) * value + .75f) + start; } else if (value < (2.5 / 2.75)) { value -= (2.25f / 2.75f); return end * (7.5625f * (value) * value + .9375f) + start; } else { value -= (2.625f / 2.75f); return end * (7.5625f * (value) * value + .984375f) + start; } } /* GFX47 MOD END */ /* GFX47 MOD START */ public static float easeInOutBounce(float start, float end, float value) { end -= start; float d = 1f; if (value < d / 2) return easeInBounce(0, end, value * 2) * 0.5f + start; else return easeOutBounce(0, end, value * 2 - d) * 0.5f + end * 0.5f + start; } /* GFX47 MOD END */ public static float easeInBack(float start, float end, float value) { end -= start; value /= 1; float s = 1.70158f; return end * (value) * value * ((s + 1) * value - s) + start; } public static float easeOutBack(float start, float end, float value) { float s = 1.70158f; end -= start; value = (value / 1) - 1; return end * ((value) * value * ((s + 1) * value + s) + 1) + start; } public static float easeInOutBack(float start, float end, float value) { float s = 1.70158f; end -= start; value /= .5f; if ((value) < 1) { s *= (1.525f); return end / 2 * (value * value * (((s) + 1) * value - s)) + start; } value -= 2; s *= (1.525f); return end / 2 * ((value) * value * (((s) + 1) * value + s) + 2) + start; } public static float punch(float amplitude, float value) { float s = 9; if (value == 0) { return 0; } if (value == 1) { return 0; } float period = 1 * 0.3f; s = period / (2 * Mathf.PI) * Mathf.Asin(0); return (amplitude * Mathf.Pow(2, -10 * value) * Mathf.Sin((value * 1 - s) * (2 * Mathf.PI) / period)); } /* GFX47 MOD START */ public static float easeInElastic(float start, float end, float value) { end -= start; float d = 1f; float p = d * .3f; float s = 0; float a = 0; if (value == 0) return start; if ((value /= d) == 1) return start + end; if (a == 0f || a < Mathf.Abs(end)) { a = end; s = p / 4; } else { s = p / (2 * Mathf.PI) * Mathf.Asin(end / a); } return -(a * Mathf.Pow(2, 10 * (value -= 1)) * Mathf.Sin((value * d - s) * (2 * Mathf.PI) / p)) + start; } /* GFX47 MOD END */ /* GFX47 MOD START */ //public static float elastic(float start, float end, float value){ public static float easeOutElastic(float start, float end, float value) { /* GFX47 MOD END */ //Thank you to rafael.marteleto for fixing this as a port over from Pedro's UnityTween end -= start; float d = 1f; float p = d * .3f; float s = 0; float a = 0; if (value == 0) return start; if ((value /= d) == 1) return start + end; if (a == 0f || a < Mathf.Abs(end)) { a = end; s = p / 4; } else { s = p / (2 * Mathf.PI) * Mathf.Asin(end / a); } return (a * Mathf.Pow(2, -10 * value) * Mathf.Sin((value * d - s) * (2 * Mathf.PI) / p) + end + start); } /* GFX47 MOD START */ public static float easeInOutElastic(float start, float end, float value) { end -= start; float d = 1f; float p = d * .3f; float s = 0; float a = 0; if (value == 0) return start; if ((value /= d / 2) == 2) return start + end; if (a == 0f || a < Mathf.Abs(end)) { a = end; s = p / 4; } else { s = p / (2 * Mathf.PI) * Mathf.Asin(end / a); } if (value < 1) return -0.5f * (a * Mathf.Pow(2, 10 * (value -= 1)) * Mathf.Sin((value * d - s) * (2 * Mathf.PI) / p)) + start; return a * Mathf.Pow(2, -10 * (value -= 1)) * Mathf.Sin((value * d - s) * (2 * Mathf.PI) / p) * 0.5f + end + start; } /* GFX47 MOD END */ #endregion } ~~~ ### 总结: 这个使用还是非常方便的。对于数据的处理和抖动,目前来看还是比较有用的。 这么实用有好用 的东西,当然要记录下来,仅供参考。 若有问题,请随时联系!!  非常感谢!!!! ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda884ba15.jpg)
';

Unity 多场景打包

最后更新于:2022-04-01 09:50:18

本文章由cartzhang编写,转载请注明出处。 所有权利保留。  文章链接:[http://blog.csdn.net/cartzhang/article/details/50580641](http://blog.csdn.net/cartzhang/article/details/50580641)  作者:cartzhang ### Unity 多场景打包问题 ### Unity 5.3多场景编辑功能 Unity 5.3 有了很好的新功能,不仅仅是VR的功能牛逼啊。多场景编辑对编辑大场景和多人合作处理场景,提供了很大的帮助,效果明显啊。  不用在苦逼的,大家各自版本,一不留心就提交版本冲突了,美术说,你TM能不老动我资源不,程序说,你TM瞎提交啥,又整不过了,打包不了了。  各种心碎啊!!对编辑大场景,这是福音啊!! 对于多关卡编辑,大大优化工作流程啊!! ### 多场景打包问题 那问题来了!!!  ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda87a96f3.jpg)  对新手来说,看到多场景,在编辑器中发现很好,很不错啊。但是打包后,发现只有一个场景,其他的场景都没被加载啊!!  咋办?这Tm不是坑人嘛!!  那就交给“SceneManager”来处理吧!! ### 你需要一行代码 只需要,程序在加载中加一行代码即可。 ~~~ [Header("场景名称")] public string LoadLevelName; void Start() { //异步叠加场景 SceneManager.LoadSceneAsync(LoadLevelName,LoadSceneMode.Additive); } ~~~ 注意要是调试可以直接在编辑器中拉入两个场景,然后编辑即可。要是运行,最好把作为背景的场景改为Unload Scene,以保证运行时,不会产生同一个场景,加载两遍。  ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda87b760a.jpg)  就是这么简单!! ### LoadSceneMode 异步加载场景中,会发现除了场景名称或ID外,有个LoadSceneMode,就是加载模式啊!  我们来看看具体是干啥的,什么作用。 ~~~ public enum LoadSceneMode { // // 摘要: 关闭所有场景,只打开一个场景 // /// // Closes all current loaded scenes and loads a scene. // /// Single = 0, // // 摘要:场景一个场景到当前场景中。 // /// // Adds the scene to the current loaded scenes. // /// Additive = 1 } ~~~ 发现了没,就是这么样。具体注释里面都说的很明白了。 我们需要把场景添加到主场景中,当然使用Additive就可以完成了。 就这样!!!! 若有问题,请随时联系!!  非常感谢!!! ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda87cc80a.jpg)
';

Unity版本与虚拟现实头盔Deepoon大朋版本测试

最后更新于:2022-04-01 09:50:16

本文章由cartzhang编写,转载请注明出处。 所有权利保留。  文章链接:[http://blog.csdn.net/cartzhang/article/details/50524654](http://blog.csdn.net/cartzhang/article/details/50524654)  作者:cartzhang OCulus DK2比较贵,再说,现在大家开始哄抢CV1,我本着有啥资源,就开弄的原则。  测试了下,我能用的手边有的大朋Deepoon头盔。 ### 一、看这里 Unity官方与OC runtime版本兼容性说明:  [https://developer.oculus.com/documentation/game-engines/latest/concepts/unity-sdk-version-compatibility/](https://developer.oculus.com/documentation/game-engines/latest/concepts/unity-sdk-version-compatibility/) 需要测试的是Unity与大朋,Unity与DK2 runtime的版本。 ### 二、Unity5.3版本搭配OC runtime 0.8版本 先说,Oculus Dk2,现有的Unity版本5.3.0版,测试过,直接PlayerSetting中勾选Virtual Reality Supported,OC runtime版本0.8.0,直接肯定是没有问题的嘛。  在编辑器模式下,直接可以在DK2头盔中看到效果。 既然这样,我就顺带把大朋拿来用用,同样环境,大鹏插上,同样可用,也可以在大朋VR头盔中看到Unity编辑效果。 ### 三、Unity5.1版本搭配大鹏0.4版本 说明使用的是大朋特别定制版本的,内部版本号:1.2.4.81,对于OC runtime版本为0.6.0.1,不要问我咋知道的,我们是定制啊。 大朋有个切换模式,我需要Dk2模式,切换到Dk2模型下。 在Unity版本为5.1.1版本,编辑器模型下,同样勾选PlayerSetting中勾选Virtual Reality Supported,结果发现,大朋头盔上可以用的,完全没有问题。 但是在Unity5.3版本下,同样设置,大朋则不可用。这个是Unity官方都说了,5.3针对VR做了优化处理,必须要匹配OC runtime 0.8.0版本,还有可能需要更新显卡驱动。 当然,驱动我都更新过了。  所以,所做实验是真实可靠的啊。 ### 四、做个表格,方便看 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda877b58a.jpg) —————THE ———————-END———  以上,就是这样!!!  若有问题,请随时联系!  非常感谢!!
';

Unity中一键创建常用文件夹

最后更新于:2022-04-01 09:50:13

本文章由cartzhang编写,转载请注明出处。 所有权利保留。 文章链接:[http://blog.csdn.net/cartzhang/article/details/50474664](http://blog.csdn.net/cartzhang/article/details/50474664) 作者:cartzhang ### Unity中一键创建常用文件夹 ### 说明 项目测试版本Unity5.3。 这个一个小工具;功能非常简单,就是一键给新建工程添加所有文件夹。到此结束。 但是具体咋操作呢? 与把大象装进冰箱一样,三步,下载代码,把代码放到工程中,点击工具下的创建按钮。 ### 一、下载代码 哪里有代码啊?下面会给出下载地址。 [http://download.csdn.net/detail/cartzhang/9393932](http://download.csdn.net/detail/cartzhang/9393932) 也可以直接负责粘贴, 代码如下: ~~~ /************************************************************************** Copyright:@cartzhang Author: cartzhang Date:[2016/1/6] Description: **************************************************************************/ using UnityEngine; using System.Collections; using System.IO; #if UNITY_EDITOR using UnityEditor; #endif public class GenerateFolders : MonoBehaviour { #if UNITY_EDITOR [MenuItem("Tools/CreateBasicFolder #&_b")] private static void CreateBasicFolder() { GenerateFolder(); Debug.Log("Folders Created"); } [MenuItem("Tools/CreateALLFolder")] private static void CreateAllFolder() { GenerateFolder(1); Debug.Log("Folders Created"); } private static void GenerateFolder(int flag = 0) { // 文件路径 string prjPath = Application.dataPath + "/"; Directory.CreateDirectory(prjPath + "Audio"); Directory.CreateDirectory(prjPath + "Prefabs"); Directory.CreateDirectory(prjPath + "Materials"); Directory.CreateDirectory(prjPath + "Resources"); Directory.CreateDirectory(prjPath + "Scripts"); Directory.CreateDirectory(prjPath + "Textures"); Directory.CreateDirectory(prjPath + "Scenes"); if (1== flag) { Directory.CreateDirectory(prjPath + "Meshes"); Directory.CreateDirectory(prjPath + "Shaders"); Directory.CreateDirectory(prjPath + "GUI"); } AssetDatabase.Refresh(); } #endif } ~~~ 代码很简单。 当然也可以从这里下载: 下载地址:[http://download.csdn.net/detail/cartzhang/9393932](http://download.csdn.net/detail/cartzhang/9393932) ### 二、使用 使用就有很简单。 首先,需要把下载或编写的代码放到工程中,放哪里呢?原理上放哪里都可以,随你喜欢。 本例测试过程中,就放在了工程最外层:如下图: ![这里写图片描述](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda871a602.jpg "") 在菜单中,会发现已经有了一个新的Tools选项,下面有两个可选项。如下图: ![这里写图片描述](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda872c5b4.jpg "") 然后就会发现,工程Project中已经创建了你需要的基础文件夹,如下图: ![文件夹](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda8740747.jpg "") 这时候,你想创建更多文件夹,也可以点击下面的CreateALLFolder,当然,若这样,你还觉得与你的使用习惯不一样,你可以到代码中修改。 在**private static void GenerateFolder(int flag = 0)** 函数中, 一目了然,自由添加你想要或去掉你不想要的文件夹。是不是很方便呢?!!! ### 三、问题 这样,文件就来了,要是我之前创建的文件夹中,有自己已经做的文件或材质,纹理等,会给覆盖掉么? 答案是,不会的。我这边测试的结果是,文件夹中存在的东西依旧会存在不会做更改。 ![不会覆盖](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda875e5dc.jpg "") ——-THE———END—————— 若有问题,请随时联系!!! 非常感谢!!!
';

Unity 的OCulus VR开发遇到的坑—OC版本差异

最后更新于:2022-04-01 09:50:11

本文章由cartzhang编写,转载请注明出处。 所有权利保留。 文章链接:[http://blog.csdn.net/cartzhang/article/details/50419709](http://blog.csdn.net/cartzhang/article/details/50419709) 作者:cartzhang ### Unity 的OCulus VR开发遇到的坑—OC版本差异 ### 一、关于Unity和Oculus插件版本 针对Unity的Oculus开发,Oculus官方给出了官方插件,不同的Unity版本,对应不同的插件版本,但是在使用中,发现有些不同或是bug. Oculus的Unity 插件官方地址:[https://developer.oculus.com/doc/0.1.0.0-unity/index.html](https://developer.oculus.com/doc/0.1.0.0-unity/index.html) 我作为Unity新人,没有用过Unity5之前的任何版本,不熟悉任何操作。所以,就根据官方推荐,使用了5.1.1版本,然后根据官方版本对应推荐,果断选择下载了PC端的OC的0.6.0.1版本,对应的Unity开发工具当时是下载的0.010beta版本。 官方推荐的各个版本对应的runtime表: [https://developer.oculus.com/documentation/game-engines/latest/concepts/unity-sdk-version-compatibility/](https://developer.oculus.com/documentation/game-engines/latest/concepts/unity-sdk-version-compatibility/) 问题是,根据游戏情节要求,需要在某个时刻或场景下锁定头盔,不能让它转动了。(先说需要,关于需求是否合理,这个下次接着再说)。 ### 二、初步了解插件 首先,先初步了解下插件啊。 下载完毕插件,建立个Unity空项目,拖拽到工程下,可以看到导入后,在资源目录下如图: ![Unity OC插件导入](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda86e2375.jpg "") 在prefabs下有三个预制,而在0.4.4或0.4.2版本下有两个预制。 ![插件预制体](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda87011eb.jpg "") 就是实现不让头盔来回旋转,这个锁定相机就好了嘛,很简单啊。关键是找对地方,代码修改一下,就搞定了。结果并不如我想象。 ### 三、说的容易 要找的代码速度找到,OC插件的重要使用脚本文件有三个, ~~~ OVRCameraRig head tracking and stereo rendering. Exposes the user's head pose with "anchor" bones. OVRPlayerController Represents a standing user and enables locomotion in the world. OVRManager A singleton that exposes the VR configuration and status to Unity. ~~~ 要实现锁定相机,并不是要在Update中实时的给相机的旋转角度赋值为某个值的过程。 要是真这么实现,会有什么影响么? 答案是肯定的。锁不住,你动下,它就动下,来回晃。 我只需要OVRCameraRig.cs文件的一个函数就可以,找到函数: ~~~ private void UpdateAnchors() { bool monoscopic = OVRManager.instance.monoscopic; OVRPose tracker = OVRManager.tracker.GetPose(0d); trackerAnchor.localRotation = tracker.orientation; centerEyeAnchor.localRotation = VR.InputTracking.GetLocalRotation(VR.VRNode.CenterEye); leftEyeAnchor.localRotation = monoscopic ? centerEyeAnchor.localRotation : VR.InputTracking.GetLocalRotation(VR.VRNode.LeftEye); rightEyeAnchor.localRotation = monoscopic ? centerEyeAnchor.localRotation : VR.InputTracking.GetLocalRotation(VR.VRNode.RightEye); trackerAnchor.localPosition = tracker.position; centerEyeAnchor.localPosition = VR.InputTracking.GetLocalPosition(VR.VRNode.CenterEye); leftEyeAnchor.localPosition = monoscopic ? centerEyeAnchor.localPosition : VR.InputTracking.GetLocalPosition(VR.VRNode.LeftEye); rightEyeAnchor.localPosition = monoscopic ? centerEyeAnchor.localPosition : VR.InputTracking.GetLocalPosition(VR.VRNode.RightEye); if (UpdatedAnchors != null) { UpdatedAnchors(this); } } ~~~ 在OVRCameraRig.cs文件的122行附近。 怎么办呢?写个变量来控制,就是在外面加个if判断,屏蔽掉所有代码即可。 结果,是然并卵。 ### 四、做着难,咋就不行呢 我迅速的郁闷了。 各种纠结和尝试之后,卸载OC,重新安装0.4.4版本。我回退了我的OC插件版本,重建工程,使用了0.4.4版本的插件,同样的文件,同样的函数,同样操作,奇迹就发生了。 附0.4.4版本的OVRCameraRig.cs文件的UpdateAnchors函数: ~~~ private void UpdateAnchors() { OVRPose leftEye = OVRManager.display.GetEyePose(OVREye.Left); OVRPose rightEye = OVRManager.display.GetEyePose(OVREye.Right); leftEyeAnchor.localRotation = leftEye.orientation; centerEyeAnchor.localRotation = leftEye.orientation; // using left eye for now rightEyeAnchor.localRotation = rightEye.orientation; leftEyeAnchor.localPosition = leftEye.position; centerEyeAnchor.localPosition = 0.5f * (leftEye.position + rightEye.position); rightEyeAnchor.localPosition = rightEye.position; } ~~~ 那还有什么好说的。轻松实现了,锁定头盔,在场景中,你不可以乱看的效果(非常规的反人类的操作!) 就只好使用0.4.4来凑合吧!! ### 五、实践是检验标准 总结: 在OC开发工程中,要时刻记得OC runtime版本与插件版本相配套。 上面这个结果的出现,可能是OC runtime版本的问题,但是也排除不了插件实现问题,比方说,用错了接口,使用了当前OC版本之前的兼容版本接口,而OC内部怎么实现的,我一概不知啊! “0.1.0”–对应的OC 0.6 .0版本有19个接口,不算兼容的老的接口。 0.4.4—对应OC的0.4.4版本,接口实现有57个左右。 我只能说,接口对0.6.0,精简了,但是我相信大的基础功能肯定都是有的。 怎么才能避免跳入这样的坑呢?没有办法,只有尝试。 ### 六、其他 遇到老板提这么怪异的VR问题怎么解决? 下回再说吧!! 若有问题,请随时联系! 非常感谢!!!
';

Unity的Json解析<二>–写Json文件

最后更新于:2022-04-01 09:50:09

本文章由cartzhang编写,转载请注明出处。 所有权利保留。 文章链接:[http://blog.csdn.net/cartzhang/article/details/50378805](http://blog.csdn.net/cartzhang/article/details/50378805) 作者:cartzhang ### Unity的Json解析<二>–写Json文件 上篇做了对Json格式文件读操作, 链接地址:[http://blog.csdn.net/cartzhang/article/details/50373558](http://blog.csdn.net/cartzhang/article/details/50373558) 本章对Json的写文件,做个处理. 写文件也非常简单,把大象装冰箱一样,分三步, 创建文件, 把内容写入文件, 然后关闭文件. ### 内容 我们要处理的是所写的内容,我们打算写什么都Json文件中呢? 我们打算把昨天的格式继续利用,还记得GameStatus ,这个是我修改的.不过,还算好用啊. GameStatus.cs文件代码如下: ~~~ using UnityEngine; using System; using System.Collections; [Serializable] public class GameStatus { public string gameName; public string version; public bool isStereo; public bool isUseHardWare; public refencenes[] statusList; } [Serializable] public class refencenes { public refencenes() { name = ""; id = -1; } public string name; public int id; } ~~~ ### 写Json格式 写JSon格式呢,我看网上都用的BinaryFormatter来处理,但是我发现这个跟昨天的问题类型,要是用BinaryFormatter的话,等保存好的Json文本打开后,各种空格,NULL和乱码.这个主要是编码格式的问题. 所以,我拒绝使用它了. 我使用**File**,直接WriteALLText来处理. 代码如下: ~~~ public void SaveJson() { string json = JsonUtility.ToJson(gameStatus); string savePath = Application.dataPath + "/Resources/Test01.json"; File.WriteAllText(savePath, json, Encoding.UTF8); Debug.Log("save:::" + savePath); } ~~~ 这样就完成了写文件是否很简便呢??!!! ### 写Json的完整代码 完整代码如下: ~~~ using UnityEngine; using System.Collections; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Text; public class WriteJson : MonoBehaviour { public GameStatus gameStatus; public GameObject[] objects; void Start() { gameStatus = new GameStatus(); gameStatus.statusList = new refencenes[objects.Length]; gameStatus.gameName = "JSON Write Test"; for (int i = 0; i < objects.Length; i++) { gameStatus.statusList[i] = new refencenes(); gameStatus.statusList[i].id = i; gameStatus.statusList[i].name = objects[i].name; } } public void SaveJson() { string json = JsonUtility.ToJson(gameStatus); string savePath = Application.dataPath + "/Resources/Test01.json"; File.WriteAllText(savePath, json, Encoding.UTF8); Debug.Log("save:::" + savePath); } } ~~~ ### 怎么使用? 我建立了一个测试工程. 只能如图了: ![Json读](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda86b9659.jpg "") 你依然可以看到昨天写文件的痕迹. 当然我们只关注写Json了. 在writeJson的属性面板上,可看到,给它的Objects拖拽了一个cube,一个Capsule,作为保存到JSon文件中的内容的一部分. 然后在运行Unity 编辑器时,按下”S”,保存键,就会在当前工程下的\Assets\Resources\中,产生了一个Test01.json的文件,这个代码中可以看到的,你可随意修改. ### 结果 让我们来看看我们都保持都Json文件中了什么东西. ~~~ {"gameName":"JSON Write Test","version":"","isStereo":true,"isUseHardWare":false,"statusList":[{"name":"Cube","id":0},{"name":"Capsule","id":1}]} ~~~ 这就是你所保存的Json文件中的内容. 我打算上传都github,但是现在我github一直让更新,更新不成功,打不开啊! ### 留下地方吧!! github一大早来更新,终于更新成功。 所以,源码地址:[https://github.com/cartzhang/UnityJsonTest](https://github.com/cartzhang/UnityJsonTest) 快捷到达源码:[Unity Json Test for 5.3 ](https://github.com/cartzhang/UnityJsonTest) 至此,Json文件的读写都搞定了. ### 更多 关于Json文件的使用,我打算尝试一个,能不能做个更好的配置,比如控制游戏的场景配置和游戏流程.打包后面不用修改,直接修改json 就可以创建一个完全不一样的游戏了. 这样,是不是比较蠢呢!!可能会,比较复杂吧!! 只个想法,若有兴趣,看看能不能实现一下. ———THE—–END————————– 若有问题,请随时联系!! 非常感谢!!!
';

Unity的Json解析<一>–读取Json文件

最后更新于:2022-04-01 09:50:06

本文章由cartzhang编写,转载请注明出处。 所有权利保留。 文章链接:[http://blog.csdn.net/cartzhang/article/details/50373558](http://blog.csdn.net/cartzhang/article/details/50373558) 作者:cartzhang ### Unity的Json解析<一>–读取Json文件 因为需要做一个外部文件配置,考虑了XML和Json,而5.3版本对Json做了更新,所以就尝试一下。 版本更新的Json部分介绍哦:[ [Unity5.3版本更新的Json部分 ]](#) ### Json的在线编辑 Json parser :[http://json.parser.online.fr/](http://json.parser.online.fr/) Json在线编辑:[http://www.kjson.com/jsoneditor/?f=1](http://www.kjson.com/jsoneditor/?f=1) 第二个是可以直接下载保存到本地的,此操作甚好啊! ### JsonUtility 先看看,在Unity中,我们在其Json工具类中,可用的函数,总共就5个,好少啊!不过,simple is better. ~~~ #region 程序集 UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null // H:\Unity\Project\JsonReadTest\Library\UnityAssemblies\UnityEngine.dll #endregion using System; namespace UnityEngine { // // 摘要: // /// // Utility functions for working with JSON data. // /// public static class JsonUtility { // // 摘要: // /// // Create an object from its JSON representation. // /// // // 参数: // json: // The JSON representation of the object. // // type: // The type of object represented by the JSON. // // 返回结果: // /// // An instance of the object. // /// [WrapperlessIcall] public static object FromJson(string json, Type type); public static T FromJson<T>(string json); // // 摘要: // /// // Overwrite data in an object by reading from its JSON representation. // /// // // 参数: // json: // The JSON representation of the object. // // objectToOverwrite: // The object that should be overwritten. [WrapperlessIcall] public static void FromJsonOverwrite(string json, object objectToOverwrite); // // 摘要: // /// // Generate a JSON representation of the public fields of an object. // /// // // 参数: // obj: // The object to convert to JSON form. // // prettyPrint: // If true, format the output for readability. If false, format the output for minimum // size. Default is false. // // 返回结果: // /// // The object's data in JSON format. // /// public static string ToJson(object obj); // // 摘要: // /// // Generate a JSON representation of the public fields of an object. // /// // // 参数: // obj: // The object to convert to JSON form. // // prettyPrint: // If true, format the output for readability. If false, format the output for minimum // size. Default is false. // // 返回结果: // /// // The object's data in JSON format. // /// [WrapperlessIcall] public static string ToJson(object obj, bool prettyPrint); } } ~~~ 可以看到,主要就是创建对象的和变成Json格式的两个类型。 ### 准备工作 我们需要一个Json文件,这是主角啊,就是要读取其内容啊。 好了。我随便写了个,命名为Test.json放到了我的.\Assets\Resources\目录下; Json文件内容如下: ~~~ {"gameName":"JSON Serializer Test","version":"1.0","isStereo":"false","isUseHardWare":"true","statusList":[{"name":"test","id":"1u702"}]} ~~~ ### 创建对象类 首先,我们需要创建一个对象类,用来存放从Json文本中读取的内容。 给这个类命名为GameStatus.cs ~~~ using UnityEngine; using System; using System.Collections; [Serializable] public class GameStatus { public string gameName; public string version; public bool isStereo; public bool isUseHardWare; public refencenes[] statusList; } [Serializable] public class refencenes { public string name; public int id; } ~~~ ### 需要一个读取类 这个写了一个静态类,以后也可添加写的内容 名字为LoadJson.cs ~~~ using UnityEngine; using System.Collections; using System.IO; using System.Runtime.Serialization.Formatters.Binary; public class LoadJson : MonoBehaviour { public static GameStatus LoadJsonFromFile() { BinaryFormatter bf = new BinaryFormatter(); if (!File.Exists(Application.dataPath + "/Resources/Test.json")) { return null; } StreamReader sr = new StreamReader(Application.dataPath + "/Resources/Test.json"); //FileStream file = File.Open(Application.dataPath + "/Test.json", FileMode.Open, FileAccess.ReadWrite); //if (file.Length == 0) //{ // return null; //} //string json = (string)bf.Deserialize(file); //file.Close(); if (sr == null) { return null; } string json = sr.ReadToEnd(); if (json.Length > 0) { return JsonUtility.FromJson<GameStatus>(json); } return null; } } ~~~ 说明:代码被注释掉的部分,是从网上找的,解析Json为二进制格式,然后在反序列化为字符串,结果,可能是编码格式问题,不能正确的反序列化,总是报错。 我表示无奈,只好从写实使用了StreamReader来处理。 ### 调用 调用蛮简单的,就是在Update中,使用L键来加载Json文件。 代码如下: ~~~ using UnityEngine; using System.Collections; using System; using System.Runtime.Serialization.Formatters.Binary; using System.IO; public class ReadJson : MonoBehaviour { void Update() { if(Input.GetKeyDown(KeyCode.S)) { //Save(); } if (Input.GetKeyDown(KeyCode.L)) { GameStatus status = LoadJson.LoadJsonFromFile(); Debug.Log(status); } } } ~~~ ### 测试结果 在场景中,建立一个空对象,然后把ReadJson拖拽到对象上,运行,按下L键,就可以使用断点查看,当然也后Log输出。 结果如下图: ![Unity视图](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda86827b5.jpg "") ![Debug](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda86a3a13.jpg "") ### 说明 总体过程都很简单。工程就不一一上传。 若有问题,请随时联系! 非常感谢!
';

Unity 实现Log实时输出到屏幕或控制台上&lt;二&gt;

最后更新于:2022-04-01 09:50:04

本文章由cartzhang编写,转载请注明出处。 所有权利保留。  文章链接:http://blog.csdn.net/cartzhang/article/details/49884507 作者:cartzhang 第一部分博客链接: http://blog.csdn.net/cartzhang/article/details/49818953 [第一部分博客链接](http://blog.csdn.net/cartzhang/article/details/49818953) Github 地址:https://github.com/cartzhang/TestConsoleWindow  [github console window](https://github.com/cartzhang/TestConsoleWindow) ### 一、你还是想要一个控制台来显示信息? 为什么呢?这样就不会占用Unity本身的GUI的显示,不去调用Unity的渲染,转而该为Windows的渲染了。 是不是很惬意,花费少了,还更灵活了。 好极了。 ### 二、你都需要些什么? 当然是一个控制台窗口和写到控制台的输入了。 代码是歪果仁写的,但是很好用。 首先,输入的代码: 名字为ConsoleInput.cs ~~~ using UnityEngine; using System; using System.Collections; using System.Runtime.InteropServices; using System.IO; namespace ConsoleTestWindows { public class ConsoleInput { //public delegate void InputText( string strInput ); public event System.Action<string> OnInputText; public string inputString; public void ClearLine() { //System.Text.Encoding test = Console.InputEncoding; Console.CursorLeft = 0; Console.Write( new String( ' ', Console.BufferWidth ) ); Console.CursorTop--; Console.CursorLeft = 0; } public void RedrawInputLine() { if ( inputString.Length == 0 ) return; if ( Console.CursorLeft > 0 ) ClearLine(); System.Console.ForegroundColor = ConsoleColor.Green; System.Console.Write( inputString ); } internal void OnBackspace() { if ( inputString.Length < 1 ) return; inputString = inputString.Substring( 0, inputString.Length - 1 ); RedrawInputLine(); } internal void OnEscape() { ClearLine(); inputString = ""; } internal void OnEnter() { ClearLine(); System.Console.ForegroundColor = ConsoleColor.Green; System.Console.WriteLine( "> " + inputString ); var strtext = inputString; inputString = ""; if ( OnInputText != null ) { OnInputText( strtext ); } } public void Update() { if ( !Console.KeyAvailable ) return; var key = Console.ReadKey(); if ( key.Key == ConsoleKey.Enter ) { OnEnter(); return; } if ( key.Key == ConsoleKey.Backspace ) { OnBackspace(); return; } if ( key.Key == ConsoleKey.Escape ) { OnEscape(); return; } if ( key.KeyChar != '\u0000' ) { inputString += key.KeyChar; RedrawInputLine(); return; } } } } ~~~ 然后,你还需要一个控制台窗口 如下: ~~~ using UnityEngine; using System; using System.Collections; using System.Runtime.InteropServices; using System.IO; namespace ConsoleTestWindows { /// <summary> /// Creates a console window that actually works in Unity /// You should add a script that redirects output using Console.Write to write to it. /// </summary> public class ConsoleWindow { TextWriter oldOutput; public void Initialize() { // // Attach to any existing consoles we have // failing that, create a new one. // if ( !AttachConsole( 0x0ffffffff ) ) { AllocConsole(); } oldOutput = Console.Out; try { IntPtr stdHandle = GetStdHandle( STD_OUTPUT_HANDLE ); Microsoft.Win32.SafeHandles.SafeFileHandle safeFileHandle = new Microsoft.Win32.SafeHandles.SafeFileHandle( stdHandle, true ); FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write); System.Text.Encoding encoding = System.Text.Encoding.ASCII; StreamWriter standardOutput = new StreamWriter( fileStream, encoding ); standardOutput.AutoFlush = true; Console.SetOut( standardOutput ); } catch ( System.Exception e ) { Debug.Log( "Couldn't redirect output: " + e.Message ); } } public void Shutdown() { Console.SetOut( oldOutput ); FreeConsole(); } public void SetTitle( string strName ) { SetConsoleTitle( strName ); } private const int STD_OUTPUT_HANDLE = -11; [DllImport( "kernel32.dll", SetLastError = true )] static extern bool AttachConsole( uint dwProcessId ); [DllImport( "kernel32.dll", SetLastError = true )] static extern bool AllocConsole(); [DllImport( "kernel32.dll", SetLastError = true )] static extern bool FreeConsole(); [DllImport( "kernel32.dll", EntryPoint = "GetStdHandle", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall )] private static extern IntPtr GetStdHandle( int nStdHandle ); [DllImport( "kernel32.dll" )] static extern bool SetConsoleTitle( string lpConsoleTitle ); } } ~~~ ### 三、输入和窗口准备齐全了,问题来了。 当你试图编译代码时候,你会发现居然编译报错,各种找不到。 Console.CursorLeft等大量的方法和变量都找不到。 这是因为Untiy5 默认的目标框架Unity3.5 .net sbu base class Libraries.。在Player Setting中,可设置为.Net 2.0。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda863241b.jpg) 这就可以改变了VS下的编译环境了。 但是要是你想要修改编译环境为你想要的其他呢? ### 四、那么问题来了?怎么修改编译环境的目标框架呢? ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda8642948.jpg) 你肯定不会是想出这个问题的第一人?所以那就有人来解决问题; 动态的修改你的FrameWork,就可以解答这个问题。 代码:UpgradeVSProject.cs ~~~ //#define USE_UPGRADEVS using UnityEngine; using System.Collections; using UnityEditor; using System.IO; using System.Text.RegularExpressions; class UpgradeVSProject : AssetPostprocessor { #if USE_UPGRADEVS private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { string currentDir = Directory.GetCurrentDirectory(); string[] slnFile = Directory.GetFiles(currentDir, "*.sln"); string[] csprojFile = Directory.GetFiles(currentDir, "*.csproj"); bool hasChanged = false; if (slnFile != null) { for (int i = 0; i < slnFile.Length; i++) { if (ReplaceInFile(slnFile[i], "Format Version 10.00", "Format Version 11.00")) hasChanged = true; } } if (csprojFile != null) { for (int i = 0; i < csprojFile.Length; i++) { if (ReplaceInFile(csprojFile[i], "ToolsVersion=\"3.5\"", "ToolsVersion=\"4.0\"")) hasChanged = true; if (ReplaceInFile(csprojFile[i], "<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>", "<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>")) hasChanged = true; } } if (hasChanged) { Debug.LogWarning("Project is now upgraded to Visual Studio 2010 Solution!"); } else { Debug.Log("Project-version has not changed..."); } } static private bool ReplaceInFile(string filePath, string searchText, string replaceText) { StreamReader reader = new StreamReader(filePath); string content = reader.ReadToEnd(); reader.Close(); if (content.IndexOf(searchText) != -1) { content = Regex.Replace(content, searchText, replaceText); StreamWriter writer = new StreamWriter(filePath); writer.Write(content); writer.Close(); return true; } return false; } #endif } ~~~ 同样,我写了代码屏蔽的宏定义。使用的时候启用就可以了。 就可以自动升高版本到4.0上,当然你也可以修改代码来升高到其他版本的。 注意:这个代码很明显,需要放置在Editor文件夹下。 ### 五、测试结果 我写了个几行的测试代码: ~~~ using UnityEngine; using System.Collections; public class Tes : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { if (Input.GetKey(KeyCode.A)) { Debug.Log("this is debug log"); System.Console.WriteLine("this is system console write line"); } } } ~~~ 结果就出来了: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda8656f48.jpg) 别告诉我,这不是你想要的控制台窗口。 你看看,在写Log时,会不会造成你的游戏卡顿了呢?? ---------THE END------------------------ 若有问题,请随时联系! 非常感谢!!
';

Unity 实现Log实时输出到屏幕或控制台上&lt;一&gt;

最后更新于:2022-04-01 09:50:02

本文章由cartzhang编写,转载请注明出处。 所有权利保留。  文章链接:http://blog.csdn.net/cartzhang/article/details/49818953 作者:cartzhang ### 一、Unity 打印日志 Unity中,在其编辑器上有个专门的Console,快捷键:shift + Ctrl+ c 。 代码中的Debug.Log("this is a test");就会打印到这里。 但是在打包后,只有从Log中找到,能不能找到一个可以实时显示的工具呢? 很明显,必须有啊!!要不写这篇不就是瞎扯了么?!! 我辗转腾挪,到处寻觅,我肯定不是第一个有这个想法的人。 终于有一天,我来到了七环!!!找到了几种方法,与君共享!! ### 二、我想有个控制台 之前说的Debug.Log();此函数是打印Unity控制台的。 好办,有高人已经重新把控制台给换了地方,打印到界面的控制台上。 就是类似控制台的一个界面。 先放结果图样: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda85d308f.jpg) #### 1.问题来了,怎么实现的呢? 上代码: 我给改了名字叫TestConsole.cs了,因为之前名字为Console,这样想我这样都在一个工程中为大家测试,容易造成混乱。 ~~~ //#define USE_TESTCONSOLE using System.Collections.Generic; using UnityEngine; namespace Consolation { /// <summary> /// A console to display Unity's debug logs in-game. /// </summary> class TestConsole : MonoBehaviour { #if USE_TESTCONSOLE struct Log { public string message; public string stackTrace; public LogType type; } #region Inspector Settings /// <summary> /// The hotkey to show and hide the console window. /// </summary> public KeyCode toggleKey = KeyCode.BackQuote; /// <summary> /// Whether to open the window by shaking the device (mobile-only). /// </summary> public bool shakeToOpen = true; /// <summary> /// The (squared) acceleration above which the window should open. /// </summary> public float shakeAcceleration = 3f; /// <summary> /// Whether to only keep a certain number of logs. /// /// Setting this can be helpful if memory usage is a concern. /// </summary> public bool restrictLogCount = false; /// <summary> /// Number of logs to keep before removing old ones. /// </summary> public int maxLogs = 1000; #endregion readonly List<Log> logs = new List<Log>(); Vector2 scrollPosition; bool visible; bool collapse; // Visual elements: static readonly Dictionary<LogType, Color> logTypeColors = new Dictionary<LogType, Color> { { LogType.Assert, Color.white }, { LogType.Error, Color.red }, { LogType.Exception, Color.red }, { LogType.Log, Color.white }, { LogType.Warning, Color.yellow }, }; const string windowTitle = "Console"; const int margin = 20; static readonly GUIContent clearLabel = new GUIContent("Clear", "Clear the contents of the console."); static readonly GUIContent collapseLabel = new GUIContent("Collapse", "Hide repeated messages."); readonly Rect titleBarRect = new Rect(0, 0, 10000, 20); Rect windowRect = new Rect(margin, margin, Screen.width - (margin * 2), Screen.height - (margin * 2)); void OnEnable() { #if UNITY_5 Application.logMessageReceived += HandleLog; #else Application.RegisterLogCallback(HandleLog); #endif } void OnDisable() { #if UNITY_5 Application.logMessageReceived -= HandleLog; #else Application.RegisterLogCallback(null); #endif } void Update() { if (Input.GetKeyDown(toggleKey)) { visible = !visible; } if (shakeToOpen && Input.acceleration.sqrMagnitude > shakeAcceleration) { visible = true; } } void OnGUI() { if (!visible) { return; } windowRect = GUILayout.Window(123456, windowRect, DrawConsoleWindow, windowTitle); } /// <summary> /// Displays a window that lists the recorded logs. /// </summary> /// <param name="windowID">Window ID.</param> void DrawConsoleWindow(int windowID) { DrawLogsList(); DrawToolbar(); // Allow the window to be dragged by its title bar. GUI.DragWindow(titleBarRect); } /// <summary> /// Displays a scrollable list of logs. /// </summary> void DrawLogsList() { scrollPosition = GUILayout.BeginScrollView(scrollPosition); // Iterate through the recorded logs. for (var i = 0; i < logs.Count; i++) { var log = logs[i]; // Combine identical messages if collapse option is chosen. if (collapse && i > 0) { var previousMessage = logs[i - 1].message; if (log.message == previousMessage) { continue; } } GUI.contentColor = logTypeColors[log.type]; GUILayout.Label(log.message); } GUILayout.EndScrollView(); // Ensure GUI colour is reset before drawing other components. GUI.contentColor = Color.white; } /// <summary> /// Displays options for filtering and changing the logs list. /// </summary> void DrawToolbar() { GUILayout.BeginHorizontal(); if (GUILayout.Button(clearLabel)) { logs.Clear(); } collapse = GUILayout.Toggle(collapse, collapseLabel, GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); } /// <summary> /// Records a log from the log callback. /// </summary> /// <param name="message">Message.</param> /// <param name="stackTrace">Trace of where the message came from.</param> /// <param name="type">Type of message (error, exception, warning, assert).</param> void HandleLog(string message, string stackTrace, LogType type) { logs.Add(new Log { message = message, stackTrace = stackTrace, type = type, }); TrimExcessLogs(); } /// <summary> /// Removes old logs that exceed the maximum number allowed. /// </summary> void TrimExcessLogs() { if (!restrictLogCount) { return; } var amountToRemove = Mathf.Max(logs.Count - maxLogs, 0); if (amountToRemove == 0) { return; } logs.RemoveRange(0, amountToRemove); } #endif } } ~~~ 我在代码最前面**添加了宏定义,使用的时候屏蔽此宏定义即可**。 #### 2.怎么使用呢? 恩。我写的使用很简单。 随便写个C#代码,在Update中测试的。 ~~~ // Update is called once per frame void Update () { //DebugConsole.Log(" test s"); Debug.Log("Debug log test"); Console.WriteLine("this is Console Write line test "); /// //DebugConsole.instance.AddMessage("this is instance AddMessage test by cartzhang", "warning"); //DebugConsole.Log("this is debug console log test cartzhang"); } ~~~ #### 3.结果上面已经说明了。 这里就不重复了。 #### 4.这怎么实现的呢? 原理很简单。写一个面板,往上面写字啊! 说下啊,这个有个切换按键,就是可以控制是否显示这个面板的,按键为BackQuote,你也可以修改,BackQuote这个键呢,在ESC按键的下面就是这个“~”。 ### 三、这不是我想要的,我要显示在屏幕上。 我想要显示在控制台上,就是CMD出来的那样。 可以啊! #### 1. 直接写在屏幕上的代码 不过,我先赠送一个显示在屏幕上的。 这样我觉得大部分的人就会满足了,最起码不用自己写GUI .Label()了啊。 说明这个是国外友人好早之前写的,我只改变了其中某些不符合现在Unity 5 的语句,其他没有动。 还是代码: ~~~ /*==== DebugConsole.cs ==================================================== * Class for handling multi-line, multi-color debugging messages. * Original Author: Jeremy Hollingsworth * Based On: Version 1.2.1 Mar 02, 2006 * * Modified: Simon Waite * Date: 22 Feb 2007 * * Modification to original script to allow pixel-correct line spacing * * Setting the boolean pixelCorrect changes the units in lineSpacing property * to pixels, so you have a pixel correct gui font in your console. * * It also checks every frame if the screen is resized to make sure the * line spacing is correct (To see this; drag and let go in the editor * and the text spacing will snap back) * * USAGE: * ::Drop in your standard assets folder (if you want to change any of the * default settings in the inspector, create an empty GameObject and attach * this script to it from you standard assets folder. That will provide * access to the default settings in the inspector) * * ::To use, call DebugConsole.functionOrProperty() where * functionOrProperty = one of the following: * * -Log(string message, string color) Adds "message" to the list with the * "color" color. Color is optional and can be any of the following: "error", * "warning", or "normal". Default is normal. * * Clear() Clears all messages * * isVisible (true,false) Toggles the visibility of the output. Does _not_ * clear the messages. * * isDraggable (true, false) Toggles mouse drag functionality * =========================================================================*/ //#define USE_DEBUGCONSOLE using UnityEngine; using System.Collections; public class DebugConsole : MonoBehaviour { #if USE_DEBUGCONSOLE public GameObject DebugGui = null; // The GUI that will be duplicated public Vector3 defaultGuiPosition = new Vector3(0.01F, 0.98F, 0F); public Vector3 defaultGuiScale = new Vector3(0.5F, 0.5F, 1F); public Color normal = Color.green; public Color warning = Color.yellow; public Color error = Color.red; public int maxMessages = 30; // The max number of messages displayed public float lineSpacing = 0.02F; // The amount of space between lines public ArrayList messages = new ArrayList(); public ArrayList guis = new ArrayList(); public ArrayList colors = new ArrayList(); public bool draggable = true; // Can the output be dragged around at runtime by default? public bool visible = true; // Does output show on screen by default or do we have to enable it with code? public bool pixelCorrect = false; // set to be pixel Correct linespacing public static bool isVisible { get { return DebugConsole.instance.visible; } set { DebugConsole.instance.visible = value; if (value == true) { DebugConsole.instance.Display(); } else if (value == false) { DebugConsole.instance.ClearScreen(); } } } public static bool isDraggable { get { return DebugConsole.instance.draggable; } set { DebugConsole.instance.draggable = value; } } private static DebugConsole s_Instance = null; // Our instance to allow this script to be called without a direct connection. public static DebugConsole instance { get { if (s_Instance == null) { s_Instance = FindObjectOfType(typeof(DebugConsole)) as DebugConsole; if (s_Instance == null) { GameObject console = new GameObject(); console.AddComponent<DebugConsole>(); console.name = "DebugConsoleController"; s_Instance = FindObjectOfType(typeof(DebugConsole)) as DebugConsole; DebugConsole.instance.InitGuis(); } } return s_Instance; } } void Awake() { s_Instance = this; InitGuis(); } protected bool guisCreated = false; protected float screenHeight =-1; public void InitGuis() { float usedLineSpacing = lineSpacing; screenHeight = Screen.height; if(pixelCorrect) usedLineSpacing = 1.0F / screenHeight * usedLineSpacing; if (guisCreated == false) { if (DebugGui == null) // If an external GUIText is not set, provide the default GUIText { DebugGui = new GameObject(); DebugGui.AddComponent<GUIText>(); DebugGui.name = "DebugGUI(0)"; DebugGui.transform.position = defaultGuiPosition; DebugGui.transform.localScale = defaultGuiScale; } // Create our GUI objects to our maxMessages count Vector3 position = DebugGui.transform.position; guis.Add(DebugGui); int x = 1; while (x < maxMessages) { position.y -= usedLineSpacing; GameObject clone = null; clone = (GameObject)Instantiate(DebugGui, position, transform.rotation); clone.name = string.Format("DebugGUI({0})", x); guis.Add(clone); position = clone.transform.position; x += 1; } x = 0; while (x < guis.Count) { GameObject temp = (GameObject)guis[x]; temp.transform.parent = DebugGui.transform; x++; } guisCreated = true; } else { // we're called on a screensize change, so fiddle with sizes Vector3 position = DebugGui.transform.position; for(int x=0;x < guis.Count; x++) { position.y -= usedLineSpacing; GameObject temp = (GameObject)guis[x]; temp.transform.position= position; } } } bool connectedToMouse = false; void Update() { // If we are visible and the screenHeight has changed, reset linespacing if (visible == true && screenHeight != Screen.height) { InitGuis(); } if (draggable == true) { if (Input.GetMouseButtonDown(0)) { if (connectedToMouse == false && DebugGui.GetComponent<GUIText>().HitTest((Vector3)Input.mousePosition) == true) { connectedToMouse = true; } else if (connectedToMouse == true) { connectedToMouse = false; } } if (connectedToMouse == true) { float posX = DebugGui.transform.position.x; float posY = DebugGui.transform.position.y; posX = Input.mousePosition.x / Screen.width; posY = Input.mousePosition.y / Screen.height; DebugGui.transform.position = new Vector3(posX, posY, 0F); } } } //+++++++++ INTERFACE FUNCTIONS ++++++++++++++++++++++++++++++++ public static void Log(string message, string color) { DebugConsole.instance.AddMessage(message, color); } //++++ OVERLOAD ++++ public static void Log(string message) { DebugConsole.instance.AddMessage(message); } public static void Clear() { DebugConsole.instance.ClearMessages(); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //---------- void AddMesage(string message, string color) ------ //Adds a mesage to the list //-------------------------------------------------------------- public void AddMessage(string message, string color) { messages.Add(message); colors.Add(color); Display(); } //++++++++++ OVERLOAD for AddMessage ++++++++++++++++++++++++++++ // Overloads AddMessage to only require one argument(message) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ public void AddMessage(string message) { messages.Add(message); colors.Add("normal"); Display(); } //----------- void ClearMessages() ------------------------------ // Clears the messages from the screen and the lists //--------------------------------------------------------------- public void ClearMessages() { messages.Clear(); colors.Clear(); ClearScreen(); } //-------- void ClearScreen() ---------------------------------- // Clears all output from all GUI objects //-------------------------------------------------------------- void ClearScreen() { if (guis.Count < maxMessages) { //do nothing as we haven't created our guis yet } else { int x = 0; while (x < guis.Count) { GameObject gui = (GameObject)guis[x]; gui.GetComponent<GUIText>().text = ""; //increment and loop x += 1; } } } //---------- void Prune() --------------------------------------- // Prunes the array to fit within the maxMessages limit //--------------------------------------------------------------- void Prune() { int diff; if (messages.Count > maxMessages) { if (messages.Count <= 0) { diff = 0; } else { diff = messages.Count - maxMessages; } messages.RemoveRange(0, (int)diff); colors.RemoveRange(0, (int)diff); } } //---------- void Display() ------------------------------------- // Displays the list and handles coloring //--------------------------------------------------------------- void Display() { //check if we are set to display if (visible == false) { ClearScreen(); } else if (visible == true) { if (messages.Count > maxMessages) { Prune(); } // Carry on with display int x = 0; if (guis.Count < maxMessages) { //do nothing as we havent created our guis yet } else { while (x < messages.Count) { GameObject gui = (GameObject)guis[x]; //set our color switch ((string)colors[x]) { case "normal": gui.GetComponent<GUIText>().material.color = normal; break; case "warning": gui.GetComponent<GUIText>().material.color = warning; break; case "error": gui.GetComponent<GUIText>().material.color = error; break; } //now set the text for this element gui.GetComponent<GUIText>().text = (string)messages[x]; //increment and loop x += 1; } } } } #endif }// End DebugConsole Class ~~~ #### 2.使用方法 ~~~ //DebugConsole.instance.AddMessage("this is instance AddMessage test by cartzhang", "warning"); //DebugConsole.Log("this is debug console log test cartzhang"); ~~~ #### 3.结果如图 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda8600847.jpg) ### 四、这还不是我想要的,我要显示在控制台上,就是CMD出来的那样。 好吧,你赢了!! 你往下看吧! [就是这个,你要的控制台《二》](http://blog.csdn.net/cartzhang/article/details/49884507) -----------THE END --------------- 若有问题,请随时联系! 非常感谢! -------- 由于担心篇幅过长,写成下一篇吧。 再次感谢各位!
';

Unity和虚幻的比较

最后更新于:2022-04-01 09:50:00

本文章由cartzhang编写,转载请注明出处。 所有权利保留。  文章链接:http://blog.csdn.net/cartzhang/article/details/49755819 作者:cartzhang 很多人从Unity开始转向虚幻4了,我目前则相反,从研究使用虚幻4,回到了Unity 5上。 前端总结的Unity和Unreal 4的一些优缺点,自己做的对比图。就先放这里了。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda85bf2d0.jpg) 其实,作为引擎,各有优缺。就是工具,放你手里怎么用了。 若你工作是杀鸡,就不要去用大炮,浪费子弹,有个说法,杀鸡焉用宰牛刀。 一点建议: 要是PC,追求画质,写实路线,酷炫,unreal 4能全面满足你的。 如要考虑到移动端,还是老实的Unity。Unity强大的移动支持能力,不的不说,各种平台支持,Mono功不可没。 Unity总要考虑旧版本的渲染支持,官方优化策略是:你要少用动态贴图,动态阴影,实时光照,这些动的基本就越少越好,最好不用。场景越静态越好,都不动最好。(带吐槽的意味了)。 总之为:**各种限制,少用**。 吐槽一下:之前翻Untiy5的官方,我当时都很诧异,Unity这么多年来,居然各向异性都没有实现。不说了,各有各自难处。 不过,Unity入门容易,跟相声一样,台阶都在门里头呢。 Unreal就来了,说光照很牛,实时阴影,粒子反射,你甭管了,都行。有限制么?有,那就是买买买! 官方回答是:**升级硬件**。 当然官方也在优化和实现移动端的功能,暂时支持肯定差点。 虚幻引擎4还有个问题,底层纯C++写的,当然也可以实现蓝图来进行各种编写。 虚幻的C ++不是普通的C++,是自定义下的各种宏定义的写,各种解析映射才搞定的蓝图来实现调用功能的。 若有问题,请随时联系 非常感谢!!!
';

Unity5中的粒子缩放(附测试源码)

最后更新于:2022-04-01 09:49:57

本文章由cartzhang编写,转载请注明出处。 所有权利保留。  文章链接:http://blog.csdn.net/cartzhang/article/details/49363241 作者:cartzhang ### 开始: 关于Unity 5 中的例子缩放,搜索了半天竟然还有人说: As far as I know that is not possible to do from code.  然后到官方找来了插件 https://www.assetstore.unity3d.com/cn/#!/content/4400 [Particle Scaler](https://www.assetstore.unity3d.com/cn/#!/content/4400) 这货居然还需要10刀。我表示很不满啊! BTW: 官方下载10美刀的居然只能在编辑器中使用,在运行中然并卵的节奏还是让人疼啊! ### 方法: 然后功夫不负有心人!!!找到了解决方案。 之前代码上有个public void UpdateScale()  我不了解是不是之前的版本的函数。反正是现在没戏了。 做了简单修改,然后就大功告成了。 还是代码啊! ~~~ using UnityEngine; using System.Collections; using System.Collections.Generic; public class ScaleParticles : MonoBehaviour { // @zpj default scale size; public float ScaleSize = 1.0f; private List<float> initialSizes = new List<float>(); void Awake() { // Save off all the initial scale values at start. ParticleSystem[] particles = gameObject.GetComponentsInChildren<ParticleSystem>(); foreach (ParticleSystem particle in particles) { initialSizes.Add(particle.startSize); ParticleSystemRenderer renderer = particle.GetComponent<ParticleSystemRenderer>(); if (renderer) { initialSizes.Add(renderer.lengthScale); initialSizes.Add(renderer.velocityScale); } } } void Start() { gameObject.transform.localScale = new Vector3(ScaleSize, ScaleSize, ScaleSize); // Scale all the particle components based on parent. int arrayIndex = 0; ParticleSystem[] particles = gameObject.GetComponentsInChildren<ParticleSystem>(); foreach (ParticleSystem particle in particles) { particle.startSize = initialSizes[arrayIndex++] * gameObject.transform.localScale.magnitude; ParticleSystemRenderer renderer = particle.GetComponent<ParticleSystemRenderer>(); if (renderer) { renderer.lengthScale = initialSizes[arrayIndex++] * gameObject.transform.localScale.magnitude; renderer.velocityScale = initialSizes[arrayIndex++] * gameObject.transform.localScale.magnitude; } } } } ~~~ ### 使用: 建立一个空对象,把上面的名字为ScaleParticles.cs的拖拽到空对象上。把你需要的粒子效果作为一个子对象挂载到空对象上。 如下所示; ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda859b617.jpg) 修改检视板中的scale size 大小,来修改粒子大小。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda85aaa40.jpg) 是不是很简单实用呢。 ### 源码呢: 免分下载地址如下: 源码地址:http://download.csdn.net/detail/cartzhang/9207203 连接:[粒子缩放源码工程免分下载](http://download.csdn.net/detail/cartzhang/9207203) ------------------------------------- ### 就是这样。 若有问题,请随时联系! 非常感谢!!!
';

Unity导入FBX自动进行动画切分

最后更新于:2022-04-01 09:49:55

本文章由cartzhang编写,转载请注明出处。 所有权利保留。  文章链接:http://blog.csdn.net/cartzhang/article/details/48678217 作者:cartzhang 本文内容关于Unity导入带动画模型的动画切分 ### 手动处理动画分割 在导入FBX模型过程中,若带有动画呢,需要对它进行切分。 当然这个工作可以在Unity中完成。 比如: 这样手动来分割进行。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda857390b.jpg) ### 自动动画切分 这就需要代码了。 把代码保存成cs文件,然后放在Editor文件夹中。若没有此文件夹,就自己创建一个! 代码如下: ~~~ // FbxAnimListPostprocessor.cs : Use an external text file to import a list of // splitted animations for FBX 3D models. // // Put this script in your "Assets/Editor" directory. When Importing or // Reimporting a FBX file, the script will search a text file with the // same name and the ".txt" extension. // File format: one line per animation clip "firstFrame-lastFrame loopFlag animationName" // The keyworks "loop" or "noloop" are optional. // Example: // 0-50 loop Move forward // 100-190 die using UnityEngine; using UnityEditor; using System.Collections; using System.IO; using System.Text.RegularExpressions; using System; using System.IO; public class FbxAnimListPostprocessor : AssetPostprocessor { public void OnPreprocessModel() { if (Path.GetExtension(assetPath).ToLower() == ".fbx" && !assetPath.Contains("@")) { try { string fileAnim; if (DragAndDrop.paths.Length <= 0) { return; } fileAnim = DragAndDrop.paths[0]; string ClipText = Path.ChangeExtension(fileAnim, ".txt"); StreamReader file = new StreamReader(ClipText); string sAnimList = file.ReadToEnd(); file.Close(); // if (EditorUtility.DisplayDialog("FBX Animation Import from file", fileAnim, "Import", "Cancel")) { System.Collections.ArrayList List = new ArrayList(); ParseAnimFile(sAnimList, ref List); ModelImporter modelImporter = assetImporter as ModelImporter; //modelImporter.clipAnimations. = true; modelImporter.clipAnimations = (ModelImporterClipAnimation[]) List.ToArray(typeof(ModelImporterClipAnimation)); EditorUtility.DisplayDialog("Imported animations", "Number of imported clips: " + modelImporter.clipAnimations.GetLength(0).ToString(), "OK"); } } catch { } // (Exception e) { EditorUtility.DisplayDialog("Imported animations", e.Message, "OK"); } } } void ParseAnimFile(string sAnimList, ref System.Collections.ArrayList List) { Regex regexString = new Regex(" *(?<firstFrame>[0-9]+) *- *(?<lastFrame>[0-9]+) *(?<loop>(loop|noloop| )) *(?<name>[^\r^\n]*[^\r^\n^ ])", RegexOptions.Compiled | RegexOptions.ExplicitCapture); Match match = regexString.Match(sAnimList, 0); while (match.Success) { ModelImporterClipAnimation clip = new ModelImporterClipAnimation(); if (match.Groups["firstFrame"].Success) { clip.firstFrame = System.Convert.ToInt32(match.Groups["firstFrame"].Value, 10); } if (match.Groups["lastFrame"].Success) { clip.lastFrame = System.Convert.ToInt32(match.Groups["lastFrame"].Value, 10); } if (match.Groups["loop"].Success) { clip.loop = match.Groups["loop"].Value == "loop"; } if (match.Groups["name"].Success) { clip.name = match.Groups["name"].Value; } List.Add(clip); match = regexString.Match(sAnimList, match.Index + match.Length); } } } ~~~ 怎么使用呢? 在你的FBX同目录文件夹下,创建一个txt文件,名字与FBX文件同名即可。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda85871d0.jpg) txt内容,为每个动画的起始帧和结束帧,是否循环播放,和帧名。 CowGirl_Ani.txt ~~~ 0-50 loop Move forward 100-190 die ~~~ 把FBX文件拖入到Unity的资源中,可以看到弹出对话框。选择Import导入,就会自动弹出分割动画的数量。 若点击cancle ,就会直接导入动画,而不会分割动画。 引用网址:http://wiki.unity3d.com/index.php/FbxAnimListPostprocessor thx! ----------------------- 若有问题,请随时联系! 非常感谢各位浏览!
';

Unity随机Prefab,自动前往某点处理

最后更新于:2022-04-01 09:49:53

本文章由cartzhang编写,转载请注明出处。 所有权利保留。 文章链接: http://blog.csdn.net/cartzhang/article/details/47337029 作者:cartzhang 对与U3D  AI,看了下,自己做了小功能,以备后用啊! ### 一,在某区域随机产生某个对象 C# 文件名称为RadomAPoint.cs ~~~ using UnityEngine; using System.Collections; public class RadomAPoint : MonoBehaviour { public GameObject mObjArea; // 随机区域 public GameObject prefabObj; // 对象prefab public string mytag; // 对象标签 public string targetTag; // 目标对象标签 public int ObjectNumber; // 场景中整体prefab 个数。 private Bounds mbouds; private Vector3 tmp; // Use this for initialization void Start () { mbouds = mObjArea.GetComponent<Collider>().bounds; InvokeRepeating("NewPrefabInstance", 1, 5);//1秒后调用LaunchProjectile () 函数,之后每5秒调用一次 } // Update is called once per frame void Update () { } void NewPrefabInstance() { GameObject[] root = GameObject.FindGameObjectsWithTag(mytag); if (root.Length <= ObjectNumber) { Vector3 randomPos = RadomVector3(mbouds.min, mbouds.max); //GameObject tmpGameObj = Resources.Load(prefabName) as GameObject; //tmpGameObj.transform.position = randomPos; Quaternion q = Quaternion.identity; GameObject tmpGameObj = GameObject.Instantiate(prefabObj, randomPos, q) as GameObject; tmpGameObj.GetComponent<AIBehaviourScript>().TargetObject = GameObject.FindWithTag(targetTag).transform; } } Vector3 RadomVector3(Vector3 min, Vector3 max) { tmp.x = Random.Range(min.x, max.x); tmp.y= Random.Range(min.y, max.y); return tmp; } } ~~~ ### 二、自己做了个prefab,添加了自动找到目标的功能。 特别简单的代码: ~~~ using UnityEngine; using System.Collections; public class AIBehaviourScript : MonoBehaviour { public Transform TargetObject = null; void Start() { if (TargetObject != null) { GetComponent<NavMeshAgent>().destination = TargetObject.position; } } void Update() { } } ~~~ ### 三,遇到目标后,自动销毁 代码: ~~~ using UnityEngine; using System.Collections; public class BoxCollisionDestory : MonoBehaviour { public string tagName; // Use this for initialization void Start () { } // Update is called once per frame void Update () { } void OnTriggerEnter(Collider other) { if (other.gameObject.tag == tagName) { GameObject.Destroy(other.gameObject); } } } ~~~ ### 四,说明 这个过程中,要设置目标点为的属性如下: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda817c4f3.jpg) 而prefab对象也需要给它一个rigidbody,否则他们的碰撞不起作用。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-09_56dfda8522543.jpg) 基本上做了一个能随机位置产生一个对象,然后对象自动寻找目的,到达目的地的小功能! --------- 若有问题,请随时联系! 非常感谢!!
';

前言

最后更新于:2022-04-01 09:49:50

> 原文出处:[Unity5学习记录](http://blog.csdn.net/column/details/unity5-star.html) 作者:[cartzhang](http://blog.csdn.net/cartzhang) **本系列文章经作者授权在看云整理发布,未经作者允许,请勿转载!** # Unity5学习记录 > Unity 5 学习记录,VR相关,小便利工具,测试工程等
';