赞
踩
延迟函数的使用:Invoke,参数1:函数名,字符串;参数2:延迟时间,秒为单位。
eg:Invoke(“函数名” ,秒);调用的函数一定要存在,如果调用的函数名不存在,那么因为调用不到会进行警告。
传入的第一个参数是函数的字符串,而且传入的函数没法传入参数,只能包裹一层。虽然直接传入带参函数不行,但是可以将它封装一下,然后在用延时函数是可以的。
使用:invokeRepeating
参数1:函数名字符串;参数2:第一次执行的延时函数;参数3:之后每次执行的间隔;时间以秒为单位。
CancelInvoke();取消所有演示函数。
CancelInvoke(“函数名”);取消指定的函数的延时函数。
IsInvoking()/ IsInvoking(“函数”);判断是否有延时函数/是否有指定的函数。
在unity中,脚本依附的对象失活或脚本失活,延时函数可以继续进行。但是脚本依附的对象销毁或脚本移除,延时函数就无法执行了。
unity中允许多线程,只是新开的线程无法访问unity中相关的内容。unity中的多线程要记得关闭。
命名空间:using System.Threading
方法:Thread
协程不是多线程,主要作用就是将代码分段分时执行,不卡主线程。主要运用于异步加载文件、场景、异步下载文件、批量创建等场合。
继承mono类的可以开协程;先申明一个协程的关键:返回值为IEnumerator类型及其子类。函数通过yield return进行返回。协程可见本质是个迭代器。
unity中引入了StartCoroutine()方法来开启协程,在()中传入协程函数就行了。
也引入了StopAllCoroutine()方法来关闭所有协程,而关闭指定的协程,也是传入指定的协程。
1、下一帧执行:yield return+数字/null ;在update和lateupdate之间执行。
2、等待指定秒后执行:yield return + new waitForSeconds(数字);在update和lateupdate之间执行。
3、等待下一个物理帧更新时候执行:yield return + new waitForFixedUpdate() ;在fixedupdate和碰撞检测相关函数后执行。
4、等待相机和GUI渲染后执行:yield return + new waitForEndOfFrame ;在lateupdate之后渲染处理完毕后执行。
5、一些特殊类型的对象,如异步加载相关函数返回的对象;在update和lateupdate之间执行。
6、跳出协程。yield break
协程开启后组件和物体销毁,协程不执行,物体失活协程不执行,相关组件失活协程执行。
Application.dataPath 工程路径获取,该方式 获取到的路径 一般情况下 只在 编辑模式下使用。
Resources 资源文件夹
路径获取:
一般不获取
只能使用Resources相关API进行加载:Application.dataPath + "/Resources"
需要我们自己将创建
作用:
资源文件夹
1.需要通过Resources相关API动态加载的资源需要放在其中
2.该文件夹下所有文件都会被打包出去
3.打包时Unity会对其压缩加密
4.该文件夹打包后只读 只能通过Resources相关API加载
StreamingAssets 流动资源文件夹
路径获取:Application.streamingAssetsPath
需要我们自己将创建
作用:
流文件夹
1.打包出去不会被压缩加密,可以任由我们摆布
2.移动平台只读,PC平台可读可写
3.可以放入一些需要自定义动态加载的初始资源
persistentDataPath 持久数据文件夹
路径获取:Application.persistentDataPath
不需要我们自己将创建
作用:
固定数据文件夹
1.所有平台都可读可写
2.一般用于放置动态下载或者动态创建的文件,游戏中创建或者获取的文件都放在其中
Plugins 插件文件夹
路径获取:
一般不获取
需要我们自己将创建
作用:
插件文件夹
不同平台的插件相关文件放在其中,比如IOS和Android平台
Editor 编辑器文件夹
路径获取:
一般不获取:Application.dataPath + "/Editor"
需要我们自己将创建
作用:
编辑器文件夹
1.开发Unity编辑器时,编辑器相关脚本放在该文件夹中
2.该文件夹中内容不会被打包出去
Standard Assets 默认资源文件夹
路径获取:
一般不获取
需要我们自己将创建
作用:
默认资源文件夹
一般Unity自带资源都放在这个文件夹下
代码和资源优先被编译
作用:1.通过代码动态加载Resources文件夹下指定路径资源
2.避免繁琐的拖曳操作
常用资源类型:
1.预设体对象——GameObject
2.音效文件——AudioClip
3.文本文件——TextAsset
4.图片文件——Texture
5.其它类型——需要什么用什么类型
注意:
预设体对象加载需要实例化
其它资源加载一般直接用
资源同步加载 普通方法:
1.预设体对象 :
第一步:要去加载预设体的资源文件(本质上 就是加载 配置数据 在内存中)
eg:Object obj = Resources.Load("Cube");
第二步:如果想要在场景上 创建预设体 一定是加载配置文件过后 然后实例化
eg:Instantiate(obj);
2.音效资源
第一步:就是加载数据
eg:Object obj= Resources.Load("Music/BKMusic");
第二步:使用数据 我们不需要实例化 音效切片 我们只需要把数据 赋值到正确的脚本上即可
eg: public AudioSource audioS;
audioS.clip = obj as AudioClip;
audioS.Play();
3.文本资源
文本资源支持的格式:.txt / .xml / .bytes / .json / .html / .csv
eg:TextAsset ta = Resources.Load("Txt/Test") as TextAsset;
对于资源同名,resource可以使用其他的API进行加载
eg:TextAsset ta = Resources.Load("Tex/TestJPG", typeof(TextAsset)) as TextAsset;
资源同步加载 泛型方法
用as太麻烦,所以常用这个方法。
eg:TextAsset ta2 = Resources.Load<TextAsset>("Tex/TestJPG");
加载过大的资源可能会造成程序卡顿 ,Resources异步加载 就是内部新开一个线程进行资源加载 不会造成主线程卡顿。
Resources异步加载方法:
异步加载 不能马上得到加载的资源 至少要等一帧
- eg: private Texture tex;
- void Start()
- {
- ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG");
-
- rq.completed += LoadOver;
-
- }
- private void LoadOver( AsyncOperation rq)
- {
- print("加载结束");
- //asset 是资源对象 加载完毕过后 就能够得到它
- tex = (rq as ResourceRequest).asset as Texture;
- print(Time.frameCount);
- }
这里通过异步加载中的完成事件监听 使用加载的资源,也是第一种方法。
注意:一定要等加载结束过后 才能使用
另一种就是采用协程异步加载
- IEnumerator Load()
- {
- //迭代器函数 当遇到yield return时 就会 停止执行之后的代码
- //然后 协程协调器 通过得到 返回的值 去判断 下一次执行后面的步骤 将会是何时
- ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG");
-
- //第一部分
- //Unity 自己知道 该返回值 意味着你在异步加载资源
- //yield return rq;
- //Unity 会自己判断 该资源是否加载完毕了 加载完毕过后 才会继续执行后面的代码
-
-
- //判断资源是否加载结束
- while(!rq.isDone)
- {
- //打印当前的 加载进度
- //该进度 不会特别准确 过渡也不是特别明显
- print(rq.progress);
- yield return null;
- }
- tex = rq.asset as Texture;
-
- //yield return null;
- 第二部分
- //yield return new WaitForSeconds(2f);
- 第三部分
- }

两者异同:
1.完成事件监听异步加载
好处:写法简单
坏处:只能在资源加载结束后 进行处理
“线性加载”
2.协程异步加载
好处:可以在协程中处理复杂逻辑,比如同时加载多个资源,比如进度条更新
坏处:写法稍麻烦
“并行加载“
Resources重复加载资源会浪费内存吗?
答:Resources加载一次资源过后,该资源就一直存放在内存中作为缓存,第二次加载时发现缓存中存在该资源会直接取出来进行使用,但是 会浪费性能(每次加载都会去查找取出,始终伴随一些性能消耗)
如何手动释放掉缓存中的资源?
答:1.卸载指定资源:可以用Resources.UnloadAsset() 方法 ,但最好不要用在GameObject对象上,会作用于实例化的对象,一般用于不需要实例化的内容。
2、卸载未使用的资源:可以用Resources.UnloadUnusedAssets()方法,一般用于过场景和GC时使用
场景同步加载: SceneManager.LoadScene()方法。
同步场景加载缺陷:
在切换场景时,Unity会删除当前场景上所有对象,并且去加载下一个场景的相关信息,如果当前场景对象过多或者下一个场景对象过多,这个过程会非常的耗时, 会让玩家感受到卡顿,所以异步切换就是来解决该问题的。
场景异步加载方法:
1、通过事件回调函数,异步加载。
例如:
- void start()
- {
- AsyncOperation ao = SceneManager.LoadSceneAsync("Test");
- //当场景异步加载结束后 就会自动调用该事件函数
- //我们如果希望在加载结束后 做一些事情 那么就可以在该函数中写处理逻辑
- ao.completed += (a) =>
- {
- print("加载结束");
- };
-
- ao.completed += LoadOver;
- }
-
- private void LoadOver(AsyncOperation ao)
- {
- print("LoadOver");
- }

2、通过协程 ,异步加载。
这个方法需要注意的是,加载场景会把当前场景上,没有特别处理的对象都删除了,从而导致在协程中的部分逻辑无法执行,因为找不到了。。为了解决这个问题,让处理场景加载的脚本依附的对象,在过场景时不被删除即可。
- void start()
- {
- DontDestroyOnLoad(this.gameObject);
-
- StartCoroutine(LoadScene("Test"));
- }
- IEnumerator LoadScene(string name)
- {
- AsyncOperation ao = SceneManager.LoadSceneAsync(name);
-
- //协程的好处 是异步加载场景时 可以在加载的同时 做一些别的逻辑
- print("异步加载过程中 打印的信息");
-
- yield return ao;
-
- print("异步加载结束后 打印的信息");
-
- }

LineRenderer是Unity提供的一个用于画线的组件,使用它我们可以在场景中绘制线段,一般可以用于: 1绘制攻击范围 2武器红外线3辅助功能 4其它画线功能。
LineRender参数相关:
LineRender代码相关:
- GameObject line = new GameObject();
- line.name = "Line";
- LineRenderer lineRenderer = line.AddComponent<LineRenderer>();
-
- //首尾相连
- lineRenderer.loop = true;
-
- //开始结束宽
- lineRenderer.startWidth = 0.02f;
- lineRenderer.endWidth = 0.02f;
-
- //开始结束颜色
- lineRenderer.startColor = Color.white;
- lineRenderer.endColor = Color.red;
-
- //设置材质
- m = Resources.Load<Material>("M");
- lineRenderer.material = m;
-
- //设置点
- //一定注意 设置点 要 先设置点的个数
- lineRenderer.positionCount = 4;
- //接着就设置 对应每个点的位置
- lineRenderer.SetPositions(new Vector3[] { new Vector3(0,0,0),
- new Vector3(0,0,5),
- new Vector3(5,0,5)});
- lineRenderer.SetPosition(3, new Vector3(5, 0, 0));
-
- //是否使用世界坐标系
- //决定了 是否随对象移动而移动
- lineRenderer.useWorldSpace = false;
-
- //让线段受光影响 会接受光数据 进行着色器计算
- lineRenderer.generateLightingData = true;

物理系统之碰撞检测:
碰撞产生的必要条件:
1.至少一个物体有刚体
2.两个物体都必须有碰撞器
碰撞和触发:
碰撞会产生实际的物理效果
触发看起来不会产生碰撞但是可以通过函数监听触发
碰撞检测主要用于实体物体之间产生物理效果时使用
什么是范围检测?
在指定位置进行范围判断,从而得到处于指定范围内的对象
如何进行范围检测?
必备条件:想要被范围检测到的对象 ,必须具备碰撞器
注意点:
1.范围检测相关API 只有当执行该句代码时 进行一次范围检测 它是瞬时的
2.范围检测相关API 并不会真正产生一个碰撞器 只是碰撞判断计算而已
范围检测API:
1.盒状范围检测Physics.OverlapBox()
参数一:立方体中心点
参数二:立方体三边大小
参数三:立方体角度
参数四:检测指定层级(不填检测所有层)
参数五:是否忽略触发器 UseGlobal-使用全局设置 Collide-检测触发器 Ignore-忽略触发器 不填使用UseGlobal
返回值:在该范围内的触发器(得到了对象触发器就可以得到对象的所有信息)
这里需要注意,参数四里的指定层级不是指的是某一层的数,也不是直接使用LayerMask.NameToLayer("UI")作为参数进行传入,而是需要对其进行二进制转换的,也就是需要通过编号左移构建二进制数,这样每一个编号的层级 都是 对应位为1的2进制数,我们通过位运算 可以选择想要检测层级。
另一个API是Physics.OverlapBoxNonAlloc(),用法和上面类似,只是多要传入一个数组进行储存。
2、球形范围检测Physics.OverlapSphere()
参数一:中心点
参数二:球半径
参数三:检测指定层级(不填检测所有层)
参数四:是否忽略触发器 UseGlobal-使用全局设置 Collide-检测触发器 Ignore-忽略触发器 不填使用UseGlobal
返回值:在该范围内的触发器(得到了对象触发器就可以得到对象的所有信息)
另一个API是Physics.OverlapSphereNonAlloc(),用法和上面类似,只是多要传入一个数组进行储存。
3.胶囊范围检测Physics.OverlapCapsule
参数一:半圆一中心点
参数二:半圆二中心点
参数三:半圆半径
参数四:检测指定层级(不填检测所有层)
参数五:是否忽略触发器 UseGlobal-使用全局设置 Collide-检测触发器 Ignore-忽略触发器 不填使用UseGlobal
返回值:在该范围内的触发器(得到了对象触发器就可以得到对象的所有信息)
另一个API是Physics.OverlapCapsuleNonAlloc(),用法和上面类似,只是多要传入一个数组进行储存。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。