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实时输出到屏幕或控制台上<二>
最后更新于: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实时输出到屏幕或控制台上<一>
最后更新于: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相关,小便利工具,测试工程等