个人主页:@元宇宙-秩沅
hallo 欢迎 点赞 收藏⭐ 留言 加关注✅!
本文由 秩沅 原创
收录于专栏:unity每日一记
⭐【软件设计师高频考点暴击】
⭐【Unityc#专题篇】之c#系统化大礼包】
⭐【unity数据持久化】数据管理类_PlayerPrfs
⭐【unity本站最全系列】unity常用API大全一篇文章足以
###同步加载**———————
5种资源加载的方式,Resource加载介绍
资源加载适用于需要加载资源较多的 情况就不用一个一个的拖拽进去
关键字:@ ,as
卸载AB包的方法: Resource. UnLoadAsset
void Start()
{
Object obj= Resources.Load("sound");
//AudioClip ac = obj as AudioClip;
AudioClip ac = (AudioClip)obj;
AudioSource.PlayClipAtPoint(ac, transform.position);
//Resources.LoadAll("Prefabs");
AudioClip[] audioClips= Resources.LoadAll<AudioClip>("");
foreach (var item in audioClips)
{
Debug.Log(item);
}
//Resources.UnloadAsset
}
C#中的回收机制是系统自动回收的,有多种回收机制,不像其他语言需要手动回收
注意:
//预设体对象加载需要实例化
//其它资源加载一般直接用
#endregion
Resource资源加载操作
加载资源前首先需要在project面板中创建Resource名字的文件夹,为固定文件夹用于资源加载
以加载AudioClip类型的资源为例:
Object obj = Resources.Load("Cube");
Instantiate(obj);
Object obj3 = Resources.Load("Music/BKMusic");
//我们不需要实例化 音效切片 我们只需要把数据 赋值到正确的脚本上即可
audioS.clip = obj3 as AudioClip;
audioS.Play();
文本资源支持的格式——.txt .xml .bytes .json .html .csv …
TextAsset ta = Resources.Load("Txt/Test") as TextAsset;
//文本内容
ta.text
//字节数据组
ta.bytes);
tex = Resources.Load("Tex/TestJPG") as Texture;
——————— 异步加载———————
如果我们加载过大的资源可能会造成程序卡顿
异步加载 就是内部新开一个线程进行资源加载 不会造成主线程卡顿
异步加载 不能马上得到加载的资源 至少要等待一帧
直接异步加载——适用于加载单个资源
//通过事件监听
ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG")
rq.completed += LoadOver;
//completed 是 ResourceRequest 中的委托
// AsyncOperation 是 ResourceRequest 的父类
private void LoadOver( AsyncOperation rq)
{
//在事件中添加结束标识逻辑,这样我们就知道异步加载完成了
print("加载结束");
//加载完成后 会保存在 ResourceRequest类中的 asset Object类型成员里
//此时实现赋值
picture = (rq as ResourceRequest).asset as Texture;
}
配套协程异步加载——适用于加载多个资源
//通过协程的调度器自己判断是否加载结束
StartCoroutine(Load());
IEnumerator Load()
{
ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG");
yield return rq;
// yield return rq会自己判断 该资源是否加载完毕了,加载完毕过后才继续执行后面的代码 ,因为ResourceRequest 也是YieldInstruction的子类
//-------------------------------
//isDone 和 progress API的应用
while(!rq.isDone)
{
//打印当前的 加载进度
print(rq.progress);
yield return null;
}
//--------------------------------
picture = rq.asset as Texture;
}
———————资源加载器———————
利用异步直接加载和委托的使用构成简单的资源加载器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
//-------------------------------------
//—————————————————————————————————————
//___________项目: ______________
//___________功能: 简单的资源管理器
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class ResourcesControl
{
static private ResourcesControl control;
static public ResourcesControl Control => control;
private ResourcesControl()
{
}
public void AddResources<T>(string name ,UnityAction<T> source ) where T : Object
{
ResourceRequest yb = Resources.LoadAsync<T>(name);
yb.completed += (reO) =>
{
source( (reO as ResourceRequest).asset as T );
};
}
}
//外部调用
private void Start()
{
GameObject shootball;
ResourcesControl.Control.AddResources<GameObject>("Profabs/ball",(sphere)=> {
shootball = sphere;
} );
}
———————卸载资源———————
Resources多次重复加载不会浪费内存
但是 会浪费性能(每次加载都会去查找取出,始终伴随一些性能消耗)
1.卸载指定资源
Resources.UnloadAsset 方法
注意:
它只能用于一些 不需要实例化的内容 比如 图片 和 音效 文本等
一般情况下很少单独使用它
2.卸载未使用的资源
一般在过场景时和GC一起使用
Resources.UnloadUnusedAssets();
GC.Collect();
加载场景的方法
SceneManasger的操作
首先添加场景加载的命名空间Using UnityEngine.SceneManagement ;
而后把游戏场景都保存(拖拽)在 Buid setting 里面,相当于存储场景的目录
1.同步加载
SceneManager.Load( 序列号) ;
SceneManager.Load( “场景名”) ;
void Start()
{
//SceneManager.LoadScene(1);
//SceneManager.LoadScene("TriggerTest");
}
缺点:加载时造成画面卡帧,因为,在未加载完成前画面是停止的,所以是卡帧现象
2.异步加载
如果当前场景 对象过多或者下一个场景对象过多
这个过程会非常的耗时 会让玩家感受到卡顿
所以异步切换就是来解决该问题的
通常我们和协程一起使用:
SceneManager.LoadAsync(序列号)
SceneManager.LoadAsync(“场景名”)
StartCoroutine(协程迭代器方法() ); //调用协程
AsyncOperation 该类型翻译为异步操作 ,为下面获得异步场景的返回值
AsyncOperation ao= SceneManager.LoadSceneAsync(2);
ao.allowSceneActivation = true 激活场景
ao.progress 场景加载的进度
//-----1.通过事件回调函数 异步加载------
AsyncOperation SS = SceneManager.LoadSceneAsync("XXXX");
SS.completed += (a) =>
{
print("加载结束");
};
SS.completed += LoadOver;
private void LoadOver(AsyncOperation ao)
{
print("LoadOver");
}
//---------2.通过协程异步加载--------
void Start()
{
//由于场景加载后就不会执行加载后的逻辑了,如果要保存就使用 DontDestroyOnLoad(保留场景加载上个场景的东西)第一个异步方法不会出现该情况
DontDestroyOnLoad(this.gameObject);
StartCoroutine(LoadScene("XXXX"));
}
IEnumerator LoadScene(string name)
{
AsyncOperation SS= SceneManager.LoadSceneAsync(name);
//根据游戏规则 自定义进度条变化的条件
yield return SS;
//1.场景加载结束 更新20%
//2.动态加载怪物再更新20%
//3.动态加载场景模型进度条顶满
//4.加载结束隐藏进度条
}
总结
场景异步加载 和 资源异步加载 一样
1.通过事件回调函数
2.协程异步加载
1.事件回调函数
优点:写法简单,逻辑清晰
缺点:只能加载完场景做一些事情 不能在加载过程中处理逻辑
2.协程异步加载
优点:可以在加载过程中处理逻辑,比如进度条更新等
缺点:写法较为麻烦,要通过协程
场景管理器
public class SceneControl
{
private static SceneControl instance = new SceneControl();
public static SceneControl Instance => instance;
private SceneControl() { }
public void LoadScene(string name, UnityAction action)
{
AsyncOperation SS = SceneControl.LoadSceneAsync(name);
SS.completed += (Scene) =>
{
action();
};
}
}
1.LineRenderer是什么
线渲染器 (Line Renderer)官方文档
LineRenderer是Unity提供的一个用于画线的组件来在场景中绘制线段
一般可以用于
2.LineRenderer相关API
代码动态添加一个线段
GameObject line = new GameObject();
line.name = "Line";
LineRenderer lineRenderer = line.AddComponent();
首尾相连
lineRenderer.loop = true;
开始结束宽
lineRenderer.startWidth = 0.02f;
lineRenderer.endWidth = 0.02f;
开始结束颜色
lineRenderer.startColor = Color.white;
lineRenderer.endColor = Color.red;
设置材质
m = Resources.Load<Material>("XXX");
lineRenderer.material = m;
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;
特点:
共同参数:
UseGlobal-使用全局设置在该界面中已默认
1.方块状范围检测
Collider[] colliders = Physics.OverlapBox( Vector3.zero, Vector3.one,
Quaternion.AngleAxis(45, Vector3.up),
1 << LayerMask.NameToLayer("UI") |
1 << LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal);
if(Physics.OverlapBoxNonAlloc(Vector3.zero, Vector3.one, 自定义数组名) != 0)
2.球形状范围检测
无角度参数
参数二为球半径
colliders = Physics.OverlapSphere(Vector3.zero, 5, 1 << LayerMask.NameToLayer("Default"));
if( Physics.OverlapSphereNonAlloc(Vector3.zero, 5, colliders) != 0 )
.3.胶囊体范围检测
参数一:半圆一中心点
参数二:半圆二中心点
参数三:半圆半径
colliders = Physics.OverlapCapsule(Vector3.zero, Vector3.up, 1, 1 << LayerMask.NameToLayer("UI"), QueryTriggerInteraction.UseGlobal);
if ( Physics.OverlapCapsuleNonAlloc(Vector3.zero, Vector3.up, 1, colliders ) != 0 )
特点
只需要判断一条线和物体的碰撞情况
可以在指定点发射一个指定方向的射线
判断该射线与哪些碰撞器相交,得到对应对象
瞬时
应用场景
1.鼠标选择场景上一物体
2.FPS射击游戏(无弹道-不产生实际的子弹对象进行移动)等
API
参数一 | 参数二 |
---|---|
起点 | 方向 |
X.origin | X.direction |
Ray XX = Camera.main.ScreenPointToRay(Input.mousePosition);
屏幕视口坐标转成射线——鼠标点击的地方变成射线
Physics.Raycast 无法检测碰到了谁,只会检测碰到了没有
最多有16个重载
Physics.Raycast常用参数 | 作用 |
---|---|
参数一 | 射线 |
参数二 | 检测的最大距离 超出这个距离不检测 |
参数三 | 检测指定层级(不填检测所有层) |
参数四 | 是否忽略触发器 UseGlobal-使用全局设置 Collide-检测触发器 Ignore-忽略触发器 不填使用UseGlobal |
返回值 | bool 当碰撞到对象时 返回 true 没有 返回false |
//第一种写法
Physics.Raycast(XX, 1000,
1 << LayerMask.NameToLayer("层级名字"),
QueryTriggerInteraction.UseGlobal )
//第二种写法
Physics.Raycast(Vector3.right, Vector3.forward,
1 << LayerMask.NameToLayer("层级名字"),
QueryTriggerInteraction.UseGlobal )
RaycastHit 在Physics.Raycast的应用 | 作用 |
---|---|
参数一 | 射线 |
参数二 | out RaycastHit 为什么是out ?RaycastHit是结构体 是值类型 out加上去就变成了引用类型,而RaycastHit没有复制所以不用ref |
参数三 | 检测的最大距离 超出这个距离不检测 |
参数四 | 检测指定层级(不填检测所有层) |
参数五 | 是否忽略触发器 UseGlobal-使用全局设置 Collide-检测触发器 Ignore-忽略触发器 不填使用UseGlobal |
返回值 | bool 当碰撞到对象时 返回 true 没有 返回false |
//写法一
RaycastHit YY;
if( Physics.Raycast(XX, out YY, 1000,
1<<LayerMask.NameToLayer("层级名字"),
QueryTriggerInteraction.UseGlobal) )
//写法二
if( Physics.Raycast(Vector3.right, Vector3.forward, out YY, 1000,
1<<LayerMask.NameToLayer("层级名字"),
QueryTriggerInteraction.UseGlobal) )
特点: 先碰到的在数组的后面
if((r3, XX, 1000, 1 << LayerMask.NameToLayer("Monster"),
QueryTriggerInteraction.UseGlobal) > 0 )
{
}
⭐【Unityc#专题篇】之c#进阶篇】
⭐【Unityc#专题篇】之c#核心篇】
⭐【Unityc#专题篇】之c#基础篇】
⭐【Unity-c#专题篇】之c#入门篇】
⭐【Unityc#专题篇】—进阶章题单实践练习
⭐【Unityc#专题篇】—基础章题单实践练习
⭐【Unityc#专题篇】—核心章题单实践练习
你们的点赞 收藏⭐ 留言 关注✅是我持续创作,输出优质内容的最大动力!、