注意:不要使用这些类来编写应用程序对网络文件进行的操作。因为Internet默认的安全政策是不允许对文件直接访问。可以使用IsolatedStroage类来处理网络文件。
--------------------------------------------------------------------------------------------
new2
c#封装下的各个操作系统都可用的读写文件功能。
using System.IO;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
1.FileMode.Create//指定操作系统应创建新文件。 如果文件已存在,它将被覆盖。 这需要 FileIOPermissionAccess.Write 权限。
2.创建文件:
FileStream file=new FileStream("Assets/text.txt", FileMode.Create);/FileMode.Append 是增加新内容,不删旧内容。
byte[]data=Encoding.UTF8.GetByte("aaa");//need using System.Text
byte[]data=new byte[]{0xef,0xbb,0xbf};//之前写这个是csv的utf8格式。
file.Write(data,0,data.Length);//byte,offset,count
file.Close();关闭当前流并释放与之关联的所有资源(如套接字和文件句柄)。
3.文件的读写xml csv 序列化,csv自己解析 比较好 但是大量数据内存大 效率不好。最好的是序列化。序列化有2种方式:1.是保存成prefab模式,直观 好看 参考fbd.cs。2.是保存成byte文件:效率更高。因为unity的prefab序列化过程可能还需要申请临时内存 保存临时数据。不过我觉得差不多吧。
[Serializable]
public class People
{
public string Name { get; set; }
public int Age { get; set; }
}//prefab 模式就是在mono里定义public的 People对象,把数据写进去,存成prefab。unity编辑器方便的查看修改序列化内容。
void Write(){//序列化写byte文件
FileStream fs = new FileStream("Asset\test.byte", FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
List
ps.Add(new People() { Name = "gg", Age = 24 });
ps.Add(new People() { Name = "yy", Age = 23 });
bf.Serialize(fs, ps);
fs.Close();
}
void Read(){//读byte文件
FileStream fs = new FileStream("Asset\test.byte", FileMode.Open);
BinaryFormatter bf = new BinaryFormatter();
List
debug.log(ps[0].name)
//http://www.cnblogs.com/ustcwhc/archive/2011/11/01/2232195.html
}
4.文件读写:string[] allline = File.ReadAllLines(path);File.Datele(path),File.Exist(path),StreamReader r=File.OpenText(path)
4.2在java中FileInputStream用来读文件;FileOutputStream用来写文件。
4.3 DirectoryInfo.GetFiles():获取目录中(不包含子目录)的文件,返回类型为FileInfo[],支持通配符查找;
DirectoryInfo.GetDirectories():获取目录(不包含子目录)的子目录,返回类型为DirectoryInfo[],支持通配符查找;
文章来源于易贤网http://www.ynpxrz.com/n753640c2023.aspx
5.关于内存优化,进入退出战斗关卡把所有资源释放,保证每次进同一关卡的时候内存值是一样的。
如果内存值波动太大,说明有东西没有释放 需要优化。
关于主页内存优化:主页需要加载大量的UIprefab到场景中,玩家每多进入一个功能,加载了一个prefab 内存都会变大。
1.建议内存大于512的时候把前边加载不用的prefab释放掉。
2.建议切换场景的时候释放所有资源内存。把引用obj=null;Destroy(obj)再调用Resources.UnloadUnusedAssets();
3 优化最重要的还是分析unity的profile,当运行在某个地方卡的时候,profile都会显示哪些东西耗cpu最高,然后根据对应的函数地方去修改哪些不对的逻辑内容。
6.关于版本更新,以前的思路是服务器资源只留一个最新版本,容易出问题。最好的方法是 每打一个版本apk CDN上就多保留一套资源目录。
然后以后的服务器任何修改都只在该版本资源文件内,不同版本不会相互牵扯和升级。要升级的话 就强制客户端apk升级,才能用服务器新版本的资源。
7. object lockd = new object(); void common (){ lock(object ){ }}//锁定内容,防止多线程调用函数里边内容。用在通用模块的通用功能上,防止多处代码同时调用该处代码,有了lock后 会按先后排队执行。
8.关于内存优化写法:
以前:obj.mainTexture=Resources.load(" ") as Texture或实例出来。
以后: Texture tex = obj.mainTexture;
obj.mainTexture = image.texture;
Resources.UnloadAsset(tex);
9.注意脚本中对资源的引用。大部分脚本将在场景转换时随之失效并被回收,但是,在场景之间被保持的脚本不在此列(通常情况是被附 着在DontDestroyOnLoad的GameObject上了)。
而这些脚本很可能含有对其他物体的Component或者资源的引用,这样相关的 资源就都得不到释放,
这绝对是不想要的情况。另外,static的单例(singleton)在场景切换时也不会被摧毁,同样地,如果这种单例含有大量的对资源的引用,也会成为大问题。
因此,尽量减少代码的耦合和对其他脚本的依赖是十分有必要的。如果确实无法避免这种情况,那应当手动地对这些不再使用的引用对象调用Destroy()
或者将其设置为null。这样在Resources.UnloadUnusedAssets()垃圾回收的时候,这些内存将被认为已经无用而被回收。
10 .ref的作用应该是把参数传过去 修改后,代表直接修改的原值。不然传过去的只是临时变量。
11.Stopwatch可以检测程序运行时间,System.Diagnostic.Stopwatch watch=new System.Diagnostic.Stopwatch()
watch.Start()
...
watch.Stop
long velocity=watch.ElapsedTicks;可以用来计算下载时间.测算哪组cdn服务器时间小,就用哪组。
12.Caching.CleanCache(); 可以删除LoadFromCacheOrDownload不能自动删除磁盘的内容,不然需要等磁盘满了才自动删。
新版本的Caching可以设置包的最大caching大小,超过了就自动释放。这个可以解决他们项目组包大的问题了。
Caching.IsVersionCached(url,int)检测该资源是否存在
13.CSV格式的文件比xml效率好,比单纯的text方便易用。但是要注意编码格式,utf8编码前先写(0xEF).(0xBB).(0xBF)这3个byte到byte数组里边。
14内存优化看我的csdn博客
15StringBuilder:如果我们的程序是在单线程下运行,或者是不必考虑到线程同步问题,我们应该优先使用StringBuilder类;
StringBuffer如果要保证线程安全,自然非StringBuffer莫属了。
单纯的string进行字符串连接的时候效率极低。
内存冗余最多的同一个功能,当刷新的界面时候,生产了很多的临时list,每刷新一次内存增加一次。这样的东西只能一个个慢慢改了。
16关于内存动态变化:总内存=分配内存+临时内存。当一个新的ui加载后,分配内存会增加,临时内存可能减少 总内存不变,也可能临时内存增加 总内存增加很多。
当加载很多UI后,分配内存需要增加,临时内存慢慢被耗完,那么就会去申请一些临时内存,那么总内存就增加了。当场景内切换,所有分配内存被释放到临时内存,但是总内存几乎不会变化。
所以内存越来越大的原因是东西多后,临时内存被撑大,释放的时候又不能释放临时内存,这是系统管的。不能释放是因为内存被碎片化了,比如一块整的100k内存,可能里边的1k还在用,就释放不了,另外碎片化后,新申请的内存如果大于碎片内存,就无法使用,只能申请新的了。
最好的做法是 在主页ui多的地方 加大优化力度,gc和unload。关闭一个ui就优化一次,或者定时优化,或者是当加载过多的prefab后,把之前加载的ui destroy掉。
少产生临时内存的写法:少用string的字符串连接,少用临时变量,在for循环下的临时变量最好都在for外声明一个,然后用完置为null、
分析内存用profiler的 Deep Profile模式,跑一遍看是哪cpu和内存增加得多,然后可以直接看出是哪些代码造成的。
17 Android遇到bug就用logcat调试。控制台输 adb logcat 然后插入手机就可以调试了。IOS遇到bug就用xcode调试或者pp助手实时同步日志。PC平台就用process explorer或者VS的进程工具Ctrl+Alt+P。
-----log:可以查看bluestack
adb kill-server
adb devices
adb logcat
adb logcat > d:\log2.txt
18 移动平台的播放视频: Handheld.PlayFullScreenMovie("test.mp4", Color.black, FullScreenMovieControlMode.CancelOnInput);PC平台可以直接MovieTexture 纹理播放。
对于IOS平台一定需要转换为H264编码的格式才能播放,可以用格式工厂转换成该编码的mp4文件。H.264 Baseline Profile Level 3.0 video, up to 640 x 480 at 30 fps. Note that B frames are not supported in the Baseline profile.
19 对于服务器定义的发送数据函数,一般最好都定义为static类型,随时可以调到。如果只是普通类型的话,数据过来也是能调用到该函数,但是函数内部所有的普通变量都是空的,一旦使用就会崩溃。
所以最好的是static,判断当instance!=null的时候处理一些实例。当然普通的这么判断也可以,但是这个写法不好,容易忘记或者弄错,因为普通类型不需要通过实例去访问变量。static才需要。
20关于通讯,底层socket会把数据都转换为byte流进行发送。零世界之前的服务器是有key优化的,key转换为id发送。
21 对于继承类 要调用基类的函数可用:base.Start();用于需要基类先初始化。
22 关于Resources.load和实例化与内存的关系:
1.加载,单纯的Resources.load后消耗的内存很低,可能只是基础的引用预载、当对象被实例化后才会占用大量内存,当实例化多个对象后和实例化一个相差不大,可能后边实例的对象引用了第一个。
2.卸载,单纯的把所有实例的obj给destroy后,内存不会释放,但是再次实例也不会耗内存,若Object b = Resources.Load("Canvas");这样写,还需要把b=null后再调用Resources.UnloadUnusedAssets()后整个内存才会被释放。
///最好不要给Resources.Load("Canvas");单独定义变量,如果忘记清除变量引用后,内存就释放不了、清除引用是指Resources.Load的引用而不是实例化对象的引用。
所以建议GameObject a = GameObject.Instantiate (Resources.Load("Canvas") as GameObject这样直接写,然后destroy 这个实例对象后,调用unload 就可以释放内存。
23 关于assetbundle的加载和实例化与内存的关系:
1.对于WWW.LoadFromCacheOrDownload方式加载,单纯的load进来也不耗什么内存,实例化后会耗很多内存,destroy实例对象后,不释放内存。调用Resources.UnloadUnusedAssets()或www.assetBundle.Unload (true);才能完全释放Unload (false)后似乎没有释放或者可能释放量极小。
结论:建议使用assetbundle.Unload (false),实例对象销毁后需要调用Resources.UnloadUnusedAssets()
2.对于WWW www = new WWW()方式加载,单纯的load需要消耗一份内存,实例化后再消耗一份内存。实例destroy后需要调用Resources.UnloadUnusedAssets()或www.assetBundle.Unload (true);才能释放实例对象内存,不能释放load的内存。Unload (false)后似乎没有释放或者可能释放量极小。
结论:一般最好不要使用该方法加载,会消耗双倍内存,可以用Resources.UnloadUnusedAssets()回收实例对象内存,本身load的内存无法手动回收。
3.对于AssetBundle.CreateFromFile():应该和1的情况类似。卸载资源只要引用没有了调用unload是有效的。
24 打bundle:
Application.persistentDataPath::C:/Users/guoyuan02/AppData/LocalLow/DefaultCompany/test
Application.dataPath::C:/Users/Public/Documents/Unity Projects/test/Assets
BuildAssetBundleOptions.CollectDependencies会去查找依赖,
BuildAssetBundleOptions.CompleteAssets会强制包含整个资源,
BuildAssetBundleOptions.DeterministicAssetBundle会确保生成唯一ID,在打包依赖时会有用到,其他选项没什么意义
BuildAssetBundleOptions.DisableWriteTypeTree 禁用写入类型树
BuildAssetBundleOptions.DeterministicAssetBundle 编译资源包使用一个哈希表储存对象ID在资源包中。
25 windows 查看堆栈,用process explorer工具,这个只能看到win层次的堆栈。另外用VS的进程工具Ctrl+Alt+P打开。附到某个进程,然后点暂停就可以看到该时刻的调用堆栈了。
26 splash:作为splash的图片不能用ToNearest来压缩,一定要用原大小。
Center (only scale down) 居中(只是缩小),以正确的像素显示图片,不会缩放图片除非需要。
Scale to fit (letter-boxed)自适应缩放大小(高宽比不变)尝试满屏显示,但不会裁剪,并用黑色填充空白的地方。
Scale to fill (cropped) 自适应填充(裁切不正的)满屏显示,屏幕外的部分将不显示.。
27.关于主城性能的优化:
1.在IOS平台有最大句柄的限制,当句柄达到最高的时候部分资源出错,新的资源加载不进来,解决方法:合并bundle资源,减少句柄。
2.主城玩家的名字Bar优化,主页UI过多,当玩家的bar跟随玩家移动的时候,只要x,y轴有变化会触发NGUI的排序功能,过多的bar和过快的移动会导致性能低下、解决方法:对于玩家的血条bar还是放在3d场景中 用3dText 来显示比较好。放UI层太耗了、
3.当出现了在好机子比在差机子上卡或者发热严重 耗电多的问题,一般都是显卡渲染引起的,好的机子开启了更好的效果所以负载大。所以建议所有机子的quality setting设置成一样。quality setting删后会出现bundle资源的显示不正常 各种uv错乱 黑块、应该修改Debug模式下的Second.
28.IOS自动打包设置用XUPorter工具:https://github.com/onevcat/XUPorter。。。http://www.xuanyusong.com/archives/2720/
29 在unity里边使用多线程做一些事情是非常好的,比如解压资源 更新资源等。因为单开线程的话 不会影响主线程卡顿,这样UI就不会卡了。但是开的线程里边不能执行unity主线程的mono代码。线程启动后,执行完毕自动结束该线程、可以同时启动多个线程做事。
代码如下: using System.Threading;
void Awake()
{
Thread athread = new Thread(new ThreadStart(goThread));
athread.Start();
}
object lockd = new object();
void goThread()
{
int index = 0;
while (true)
{
lock (lockd)//防止其他线程访问当前线程使用的数据
{
Debug.Log("in thread" + index);
index++;
if (index == 100)
{
Thread.Sleep(10000);// 将当前线程挂起指定的时间 毫秒 时间结束后 继续执行下一步 和yield类似
}
else if (index == 200)
{
break;//该函数执行完自动结束该线程
}
}
}
}
30 关于事件回调:
EventDelegate.Add(button.onClick, Click);//该委托无参数
EventDelegate.Add(button.onClick,delegate() { Click("click"); });//该委托无参数,但可把参数存在临时变量里边,相当于回调有参数
EventDelegate.Add(button.onClick,delegate() {Debug.Log(UIButton.current.name); });//直接处理
UIEventListener.Get(imageButton.gameObject).onClick=Click; void Click(GameObject go){ }//该委托带参数
UIEventListener.Get(imageButton.gameObject).onClick = delegate(GameObject go ) {Debug.Log(go.name);};//直接写里边 不用函数转换
31 unity资源路径标准情况是斜杠/ Windows资源路径标准是反斜杠\。c#中的反斜杠用转义符\\表示。单纯的反斜杠\被用来做\n换行等字符识别了。
32.
Unity常用目录对应的Android && iOS平台地址
IOS:
Application.dataPath : Application/xxxxx/xxx.app/Data //ipa安装目录
Application.streamingAssetsPath : Application/xxxxx/xxx.app/Data/Raw //ipa安装目录; 移动设备不可写 只可读,IOS和Windows用File.Read ,安卓用java代码读;安卓内属于压缩文件类型 读取比persistentDataPath慢
//然后路径问题IOS PC用File.Read路径需要全路径,安卓InputStream in = getResources().getAssets().open(fileName); 用这个读 只需要文件名就可以了。
Application.persistentDataPath : Application/xxxxx/Documents //文档目录 ;所有设备可写可读,可直接用File.Read读,有些接口读取全路径需要加 "file://" +Application.persistentDataPath,unity 的大部分接口不需要"file://"部分。
Application.temporaryCachePath : Application/xxxxx/Library/Caches //缓存目录 ;所有设备可写可读
IOS还有tmp目录Application/xxxxx/tmp //临时缓存目录
Android:
Application.dataPath : /data/app/xxx.xxx.xxx.apk //apk内
Application.streamingAssetsPath : jar:file:///data/app/xxx.xxx.xxx.apk/!/assets //apk内
Application.persistentDataPath : Android/data/data/xxx.xxx.xxx/files //文档目录
Application.temporaryCachePath : /data/data/xxx.xxx.xxx/cache //缓存目录
PC
Android:
Application.dataPath : C:/Users/guoyuan02.SNDA/Documents/New Notify/Assets //工程内
Application.streamingAssetsPath : C:/Users/guoyuan02.SNDA/Documents/New Notify/Assets/StreamingAssets //工程内
Application.persistentDataPath : C:/Users/guoyuan02.SNDA/AppData/LocalLow/DefaultCompany/New Notify //文档目录
Application.temporaryCachePath : C:/Users/GUOYUA~1.SND/AppData/Local/Temp/DefaultCompany/New Notify //缓存目录
当然PC下用File.ReadAllText可以读任意目录 移动也可以有其他方法读。
33 .关于Android里边的各个目录的获取方法:
Environment.getDataDirectory() = /data
Environment.getDownloadCacheDirectory() = /cache
Environment.getExternalStorageDirectory() = /mnt/sdcard
Environment.getExternalStoragePublicDirectory(“test”) = /mnt/sdcard/test
Environment.getRootDirectory() = /system
getPackageCodePath() = /data/app/com.my.app-1.apk
getPackageResourcePath() = /data/app/com.my.app-1.apk
getCacheDir() = /data/data/com.my.app/cache
getDatabasePath(“test”) = /data/data/com.my.app/databases/test
getDir(“test”, Context.MODE_PRIVATE) = /data/data/com.my.app/app_test
getExternalCacheDir() = /mnt/sdcard/Android/data/com.my.app/cache
getExternalFilesDir(“test”) = /mnt/sdcard/Android/data/com.my.app/files/test
getExternalFilesDir(null) = /mnt/sdcard/Android/data/com.my.app/files //对应Application.persistentDataPath的SD卡目录
getFilesDir() = /data/data/com.my.app/files //可能对应Application.persistentDataPath的本地目录
34排序用List的Sort函数挺好用的:List
35.IOS安装后会把安装文件直接解压到目录,所以包大小会变大,加载速度会变快。Android安装后仍然是用压缩的方式存在目录,所以包大小不会变太多,但是加载会慢些。
这还涉及安装的apk和ipa包里边本身是解压的还是压缩的,如果ipa打包前就是压缩的 在IOS/android下边安装后包变得不会很大。但是ipa打包前是没有经过压缩,而是完全靠ipa和apk本身来压缩大小的话,安装后ios包大小就会差很多。
36.移位问题 2<<1 这是2向左移动1位,2>>1这是2向右移动1位。
37.函数参数传object类型:
一个参数 void BuildA(object para){ List
多个参数 void BuildB(object para){ object[] ps= para as object[];List
38.stream:其中类Stream为抽象类。由此有三个派生类。 需要引入命名空间:using System.IO。一般调用完stream后 都需要调stream.close()来保证资源回收。
MemoryStream:对内存进行读取与写入
BufferedStream:对缓冲器进行读取/写入
FileStream:对文件执行读取与写入
TextReader/Writer为抽象类。由此派生类:
StreamReader/StreamWirter 分别用于对流的读取与写入。
File和Directory
File类支持对文件的基本操作,包括创建、拷贝、移动、删除和打开一个文件。Directory类则用于执行常见的各种目录操作,如创建、移动、浏览目录及其子目录。
File类和Directory类都是密封类。不象抽象类Stream,File类和Directory类可以被实例化,
Stream.Read(byte[] buffer, int offset, int count) 从当前流读取字节序列,表示从stream里边 buffer: 此方法返回时该缓冲区包含指定的字符数组,该数组的 offset 和 (offset + count -1) 之间的值由从当前源中读取的字节替换。for循环下返回值为0 代表读完了。每次读前要设Stream.position=offset;这样才能定位流里的位置。
Stream.Write(byte[] buffer, int offset, int count)表示写入该byte数组到流。
39.关于C#中 List和数组 GameObject 结构体等类型传递到函数或赋值给新参数的时候 是引用传递,一边修改数据另外一边也会变。int等数据是值传递,函数传递后就与原数据无关。
40.关于句柄限制 对于persistentDataPath目录 IOS有句柄限制最好不超过200,安卓没有,对于streamingAssetsPath目录IOS还是200个限制,但是安卓只能通过www异步加载或者ja另外va层面同步加载,异步加载有端口限制,同步加载有证据表明句柄数也不能太多。另外对于Http下载的文件流 端口也有数量限制 数量不能超6553个。所以除了可以用File.read方法以外的文件流 最好都及时关闭,若不关闭 一定要处理好引用关系 和防止句柄超。
41.yield return null 和Thread.Sleep(100)的区别 协成是等待一帧 再执行下边的内容;Thread.Sleep是当前线程阻塞0.1秒 然后继续执行,主线程使用会导致其他逻辑也阻塞。所以主线程一般不推荐使用。
----------------------------------------------------------------
new
1.在string中:equals方法对于字符串来说是比较内容的,“==”方法在字符串中比较的是首地址,对于值比较2者完全一样。
2.在c#中不支持中文的时候,要在visual中打开该文件,点文件-高级保存选项,保存为Unicode-1200格式。
3.访问其他脚本的方法,除了声明为static以外,还可以继承:public class FuLi_dailyClick : Fuli_dailyUI {}这样在这个脚本中的方法和变量就可以直接访问Fuli_dailyUI脚本了。继承一般不用,因为继承自己写的方法后,就不能用unity官方的功能了,update等都无效。
还可以采用在脚本中声明一个静态对象,然后其他脚本通过这个对象访问该脚本的其他方法。如:
public class JiusiUI : MonoBehaviour {//一定要保证这个脚本被active后 s_jiusiUI = this;才会生效
static JiusiUI s_jiusiUI = null;//那么其他脚本可以采用s_jiusiUI.init()的方法来调用这边的函数
void Awake()
{
s_jiusiUI = this;//这个很重要,必须有才能调用,不然不行。
}
public GameObject item1 = null;
void OnDestroy()
{
s_jiusiUI = null;
}
public static void init()
{//这里可是是实例化的东西
s_jiusiUI.item1.gameObject.SetActiveRecursively(bShow);//这样静态方法和实例化就结合了。
}//这儿是指在本脚本中可以将方法定义为静态,其他脚本可以调用该方法。而不是调用对象。
}
4.只有在主界面改变没有prefab的或者增加prefab的时候需要上传scenegame文件,其他的改变prefab的直接上次prefab就可以了。
5.想要自己的数据每次都更新,就不要把初始化数据放在start里边,而是自己定义一个init函数,没次进去都调用。
6.开始等待时间和终止等待
IEnumerator Start() {
StartCoroutine("DoSomething", 2.0F);//开始计时
yield return new WaitForSeconds(1);
StopCoroutine("DoSomething");//停止计时
}
IEnumerator DoSomething(float someParameter) {
while (true) {
print("DoSomething Loop");
yield return null;
}
}
7 position和localPosition的区别是position是世界坐标,localpositon是基于父物体的坐标。
8 时间的显示格式:lblWaitTime.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", waitTime.Hours, waitMinutes, waitSeconds);
9 关于叶签和内容最好的搭配方式参考福利。当需要打开第二页的时候,同时使第二页的叶签打开。但都得放在update后执行一次。尽量不要放在update后边,不然会导致显示闪一下。
10 关于等待时间的问题,最好少用协成yield waitforseconds,用updata下Time.time比较本次time和上次time的差值比较好。
11字体text必须要先等它处于active==true状态后再赋值,才能自动适应宽度。如果先赋值后使它active会导致它只会使用上次text数据的宽度显示出问题。
12所有系统要考虑场景切换后能否使用,所以最好存static数据,系统只是显示,每次回场景都要重新联网取数据不好
13对于字体设置 while 比for有效。for有时候根本不起用。
14.DragMove赋给图片,在加上collider后,就可以实现随意拖拽图片了。ngui中用。
15.关于摄像机设置显示的问题无论是否NGUI中,每个物体都有一个Layer层次,
在摄像机中有一个Culling mask可以选中需要渲染的层次,那么其他层次在game中就
不会显示了。
16active和enabled的区别:active是只针对物体的有效,enabled是只针对组件有效。
17.碰撞器和触发器要生效最好2个碰撞的物体都加上刚体。若只有一个是刚体,则用刚体去撞另外一个物体才触发事件,反之不触发。这个月layer无关。
18.Unity里边批量选择,鼠标点击一个,再按住SHIFT点另外一个就会批量选择他们之间所有东西。
19 出错时,在调试台打开open Editor Log,搜索Error的就知道哪错了,这是很重要的一个调试手段。
20 打包注意Resource和StreamingAssets目录,这2个目录都会打包,其他的按引用打包。
21.我们的零世界项目库只支持 xp系统的unity3.5.5版本。
22.动画animation的制作方法,在project中建造Animation文件,然后拖到场景中的物体上,然后用动画组件打开,才能编辑和保存。
23.正确的关卡加载做法是,1,showLoad(true),2用协成来异步加载,3.等级协成加载完自动showLoad(false),而不是在start里边showLoad(false),
24.协成最好是只在本地方法使用,不使用static类型。
25.使用多个camera的时候,只有Layer和Depth这2个参数影响各种渲染的内容效果,与各自的z轴无关。
正常camera:depth=2,layer="UI"//正常相机是先渲染depth小的,也就是depth越大显示越考前。
load的camera:depth=3,layer="UI"//load要遮住其他UI,所以layer必须和maincamera一样,layer相同的组件,前后关系和z轴有关,所以load的camera整体z=-1200。
特效的camera:depth=4:layer="Touch"//特效的只要出效果,与其他无关,可以共同显示,所以layer不一样。
layer由culling Mask来控制渲染。
26 关于回调函数 public delegate void ClickEventHandler();
public event ClickEventHandler DialogOver = null; 可以把函数名用init传过来赋值给DialogOver,结束了调用DialogOver()就可以回调了。
27 报System.IO.DirectoryInfo错误,是因为平台web上不行,换成 其他平台也许就好了。
28 做战斗节奏加速 或者减速,用Time.timeScale = 1.0F;
29 abstract override:
public setUUid(ID){ ...;setInfo(heroInfo) }//父类
abstract public void setInfo(RCardInfo heroInfo);//父类 用这个得时候 该父类 也得声明成abstract public abstract class HeroBaseDetail : BaseInfoObj{}
public override void setInfo(RCardInfo heroInfo){}//子类
这个的用法:多个子类都需要调用基类相同的数据部分setUUid,然后也有各自单独的实现部分setInfo就是单独抽象来的。不然setUUid的相同内容得写多遍。
30 设置帧频:先设置quality setting的(垂直同步)vsync count为dont sync,然后用Application.targetFrameRate = 300;就可以了
31 所有会卡的东西,都放在协成里边来做,等一帧执行下一个内容。
32 关于回调的delegate 和event:如果单是回调: public delegate void ClickEventComplete(); ClickEventHandler loadCompleteOnce=null;就可以了。调过来的方法让他等于loadCompleteOnce就可以了。
但很多时候可能会并行使用像msgBox一样:
用法: public delegate void Click();
public event Click yesClick = null;//event
调用的时候:用btnYes.yesClick += onYesClick; btnYes.yesClick += onYesClick2的形式才调用。+=和=的区别是:+= 的话会调用所有的方法1和2,等于只会调用最后一次覆盖的方法2。参考:http://www.cnblogs.com/haiyang1985/archive/2009/03/10/1407936.html
建议参考UIButtonClick方法:如果2次刷新的id不一样,第二次要调用ClearClick方法。//2者差不多,event更佳严谨。
33 将对象进行序列化 加:[System.Serializable]具体参考FBDtool 和fbddata和AutoHome
如:
[System.Serializable]//加了这句话 下边的public Data[] data = null;这个内容 才能在编辑器中显示出来。
public class Data
{
public Vector2 ContentRect = Vector2.zero;
public Transform content = null;
}
public class AutoHome : MonoBehaviour
{
public Data[] data = null;
}
34 常用 #region A #endregion A 将代码包裹开来。这样一个脚本里边 各种的功能分开,方便查看。
35.关于次数限制的问题,最好是初始化设为0 ,然后每用一次加1,当最大次数增加后,可以马上生效。
如果你的初始化设为最大值,一直减到0 ,如果最大次数变了 只能明天才能生效,马上生效就比较麻烦。
36 DestroyImmediate 同一帧内如果要destroy一些东西,然后又要生成该物体或要立即生效,就用这个,不要同一帧销毁的话就用Desroy
-----------------------------------------------------
1、 if(Input.GetKeyDown(KeyCode.W))//指按下W,下面的内容会执行一次,用来调用按钮。按一次执行一次。
if(Input.GetKey(KeyCode.W)) // 指按住W,下面的内容会一直执行,用于走路等。
if(Input.GetKey("1") ) //若是引用数字键要用("1")
Input.GetKeyUp //按下起来后有效一次和上面Down一样
2、 Vector3(x,y,z)既是:(right,up,forward)
Vector2(x,y) 做2d游戏用
3、鼠标的光标和滑轮只能监听 不能判断,只读。
4、鼠标键分别是Input.GetMouseButton(0) 左边
Input.GetMouseButton(2) 中间
Input.GetMouseButton(1)右边
5、GUIskin可以从 Assets-creat-gui skin创建
6 直接查找KeyCode可以得到所以键盘码
7 要想实现一个展示品,相机围绕物体旋转。
则把相机作为那个物体的子物体就可以了,再给物体加上mouselook,
最好做一个空物体放那个需要展示的物体里边。不过我的mouselook还不是很好用 用官方的吧.
8 Screen.width,Screen.height既是表示当前运行窗口的宽度与长度,不管是测试和正式运行都是如此。最好在函数中用 不要在定义里用。
9 、android屏幕的调用,就是相当于windows的鼠标光标的感应,意思就是直接用一个mouselook就可以满足了。
10 android横屏:Screen.orientation = ScreenOrientation.LandscapeLeft;放在function Start()函数下。
11导出fbx模型时 要在max里把位图路径设置一样的。fbx和位图在一个文件夹里导入unity
12 相机:Projection选项:Perspective:正常的个人视角
Orthographic:做2D游戏必备的视角,正交视角。
13 重载本关卡:Application.LoadLevel(Application.loadedLevel);
14 Rigidbody: Mass质量 Drag阻力,减慢速度 Angular Drag角阻力,减慢旋转。2D游戏还可以把Freeze Position 的z选中,Freeze Rotation 的X Y选中,只能饶z旋转,x y面可移动。
15 function Start () 用来初始化的,重载场景后,只要初始化就好了,不需要赋值了。
16 在android上设置开始欢迎界面:Player Settings(Splash Image section)中选择为启动画面准备好的素材
17 要显示2D效果除了用2d tooltit外还可以用讲cube的scale 调为0,为保持碰撞效果可设为0.1很小(大点好)。
18 设计蹦床的效果:把2个刚体部分重合,然后固定rigidbody position xyz,那么其他物体来碰撞都有自动弹性效果。质量来调节效果。刚体只是一种效果,要碰撞还是得collider。
19摩擦力:collider.material.dynamicFriction = 0;//静摩擦与动摩擦 0为摩擦小,1为摩擦大。
collider.material.staticFriction = 0;
反弹力:collider.material.bounciness = 0;//反弹力 0为无反弹力 1为大 摩擦和反弹力值越大力越大 值越小力越小
20 在函数里边定义变量的时候不要var,如 function Explosion(explode: Transform){}就可以了。
21 截屏代码function OnMouseDown(t:Collider) { if(t.gameObject.tag=="") Application.CaptureScreenshot("Screenshot.png");}
22 做绳的效果 :用很多个固定结点fixed joint,用很多cylinder模型,不能要重力,不然力大了会乱反弹。
23 判断物体不在当前相机(屏幕)显示下就摧毁之:function OnBecameInvisible () { Destroy(this.gameObject);}//同样还有function OnBecameVisible () { }//相机可见函数
24 //定义鼠标有效区域:
Rect screenRect = new Rect(0,0,Screen.width,Screen.height);
if( !screenRect.Contains(Input.mousePosition)) return;
26 关于物体材质颜色和透明度:用这个的前提是把材质设为Transparent。透明度改变很容易卡,所以间隔时间要长点:1s。
transform.renderer.material.color = Color.clear;//完全透明; RGB(0,0,0)为黑 (1,1,1)原色,Color32(255,255,255)白色
transform.renderer.material.color = Color(1, 1, 1, 1);//分别代表RGBA,A代表alpha通道 从0完全透明--- 1不透明;
在做GUI或者2d时要想透明部分不显示成白色也要将材质设为Transparent就可以显示透明色了,前提在ps里面用透明背景。c#要用new Color()
27 在android上调用退出: if (Input.GetKey("escape"))
{ Application.Quit(); }
28 GUI的数组function OnGUI () {
GUI.BeginGroup (new Rect (Screen.width / 2 - 400, Screen.height / 2 - 300, 800, 600));
GUI.Box (new Rect (0,0,800,600),"");
GUI.EndGroup ();}
29 GUIText显示参数: GameObject.Find("PETGUI").guiText.text ="收服蚂蚁:"+ PetNum;//放在Update下,""为新建的GUI Text的名字,PetNum为参数。
30 要在别的脚本里调用其他脚本的变量用static var qq = 0; ///用public var qq =0;也可以在别的脚本调用,但不安全。
在别人脚本里调用其他的脚本的函数也是static function qq(){} //调用当然都得用Pet.qq 或者Pet.qq();Pet为脚本名。
31 为保证效率在用while循环时一定要用yield,效率会提高N多倍。不卡
32 Application.OpenURL(http://www.baidu.com);//打开网页
33 Destroy (this);删除脚步Destroy (this.gameObject);删除物体或者Destroy (other);//摧毁的物体放在括号内,不是前面,this也不行。Instantiate
34要想判断鼠标在屏幕哪一个区域,就在这个区域放一个GUITexture,然后在GUITexture里边放上function OnMouseEnter()就可以判断了,之前怎么没想到了靠!
-----------------------------------------------------
1、获取对象:a = GamoObject.Find("cube");
b = GamoObject.Find("a/cube");
c = GamoObject.FindWithTag("cube");
d = GamoObject.FindGameObjectsWithTag("cube");//获得tag为cube的所有对象
d[2].tag = "box";//d.length获得数组长度;
2、广播:gameObject.BroadcastMessage ("ApplyDamage", 5.0);向子对象的函数ApplyDamage发送消息5.0
gameObject.SendMessage ("ApplyDamage", 5.0);//给自己发送消息;
gameObject.SendMessageUpwards ("ApplyDamage", 5.0);给父对象发送消息
function ApplyDamage (damage : float) {
print (damage);
}
3、四元素:transform.rotation =Quaternion.Slerp (from.rotation, to.rotation, Time.time * speed);
//插值旋转,就是慢慢旋转到to.rotation;//Quaternion.Lerp 比Slerp快而且效果没它好
transform.rotation = Quaternion.Euler(Vector3(0, 30, 0));//立即旋转到这个角度
var t=transform.eulerAngles.y;
//返回绕z轴旋转的度数 ,既是读取当前z轴度数
var angle : float = Quaternion.Angle(transform.rotation, target.rotation);//返回2物体间的角度
transform.rotation = Quaternion.AngleAxis(30, Vector3.up);//绕y轴旋转30度
4 Mathf函数里边的角度是π方式表示的,欧拉角要转换过来。
5 获得物体的位置,旋转值,缩放值:
var quare = room.transform.position;
var rotationQ = room.transform.eulerAngles;
var ScaleQ = room.transform.localScale;
transform.rotation = Quaternion.identity;//设置旋转角度为(0,0,0)
设置位置和缩放倍数就用=Vector3(2,2,2);就可以了。在c#中是= new Vector3(1f,2f,3f);
设置人物旋转一般用 transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);//不要用Rotate了
6. Mathf.Clamp (value, min, max);
限制value的值在min和max之间, 如果value小于min,返回min。 如果value大于max,返回max,否则返回value
7 C#中的等待: StartCoroutine(WAIT()); 这个是接口开始计时,否则直接调用不计时。 IEnumerator WAIT() {yield return new WaitForSeconds(5);}
8 驱动官方角色行走的脚本在animation里边,都是修改Input.GetAxis ("Mouse X");y旋转 Input.GetAxis ("Horizontal");Vertical移动Input.GetAxis (Fire1");开火等
9 颜色问题:Color是0-1范围,Color32范围是0-255;c#用transform.renderer.material.color = new color(,,,);
10 在用官方guitext字体的时候,把Pixel correct 选中,再放大Font Size就可以有最好的效果了。设置颜色: GameObject.Find("PETGUI").guiText.material.color = Color.red;
11,UIAtlas item1 =Resources.Load("head",typeof(UIAtlas) as UIAtlas;如果没有typeof则默认的Resources.Load()只能加载物体(Object)类型的东西。