【Unity每日一记】资源加载相关和检测相关

2023-09-15 22:27:57

在这里插入图片描述


👨‍💻个人主页@元宇宙-秩沅

👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!

👨‍💻 本文由 秩沅 原创

👨‍💻 收录于专栏unity每日一记

🅰️推荐文章


【软件设计师高频考点暴击】

【Unityc#专题篇】之c#系统化大礼包】

【unity数据持久化】数据管理类_PlayerPrfs

【unity本站最全系列】unity常用API大全一篇文章足以
在这里插入图片描述






🎶(AResources资源动态加载


在这里插入图片描述

###同步加载**———————


5种资源加载的方式,Resource加载介绍


  • Resources(只能加载Resources目录中的资源)
  • AssetBundle(只能加载AB资源,当前设备允许访问的路径都可以)
  • WWW(可以加载任意处资源,包括项目外资源(如远程服务器))
  • AssetDatabase(只能加载Assets目录下的资源,但只能用于Editor)
  • UnityWebRequest(可以加载任意处资源,是WWW的升级版本)

资源加载适用于需要加载资源较多的 情况就不用一个一个的拖拽进去



关键字:@ ,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<AudioClip>("Prefabs");
        AudioClip[] audioClips= Resources.LoadAll<AudioClip>("");
        foreach (var item in audioClips)
        {
            Debug.Log(item);
        }

        //Resources.UnloadAsset
    }
  • C#中的回收机制是系统自动回收的,有多种回收机制,不像其他语言需要手动回收

    注意:
    //预设体对象加载需要实例化
    //其它资源加载一般直接用
    #endregion

Resource资源加载操作


加载资源前首先需要在project面板中创建Resource名字的文件夹,为固定文件夹用于资源加载

以加载AudioClip类型的资源为例:

  • 根目录加载 Resource.Load< AudioClip>(“voice”);
  • 子目录加载 Resource.Load ( @ " 子目录名/ voice") ;
  • 另一种形式:
    Object xx = Resource.Load(“voice”);
    AudioClip yy as xx ; // 显性类型转换 ,前提是二者兼容
  • 加载同类型所有资源的方法:
    ①根目录加载: AudioClip [] xx = Resource.AllLoad(" “) ;
    ②子目录加载:AudioClip [] yy = Resource.AllLoad(” 子目录名");

  • 1.预设体对象
        Object obj = Resources.Load("Cube");
        Instantiate(obj);
  • 2.音效资源
        Object obj3 = Resources.Load("Music/BKMusic");
        //我们不需要实例化 音效切片 我们只需要把数据 赋值到正确的脚本上即可
        audioS.clip = obj3 as AudioClip;
        audioS.Play();
  • 3.文本资源

文本资源支持的格式——.txt .xml .bytes .json .html .csv …

        TextAsset ta = Resources.Load("Txt/Test") as TextAsset;
        //文本内容
         ta.text
        //字节数据组 
         ta.bytes);
  • 4.图片
        tex = Resources.Load("Tex/TestJPG") as Texture;

——————— 异步加载———————


如果我们加载过大的资源可能会造成程序卡顿
异步加载 就是内部新开一个线程进行资源加载 不会造成主线程卡顿

  • Resources.LoadAsync(“XXX”);
  • 注意:

异步加载 不能马上得到加载的资源 至少要等待一帧

直接异步加载——适用于加载单个资源

//通过事件监听
    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();



🎶(BSceneManager场景资源动态加载



👨‍💻👍加载场景的方法


  • SceneManager.LoadScene() ; 场景同步加载
  • SceneManager.LoadSceneSAsyn(); 场景异步加载
  • SceneManage。GetActiveScene().name判断当前场景
  • Application.LoadLevel():同步加载
  • Application.LoadLevelAsync():异步加载
  • Application.LoadLevelAddictive():同步附加式加载
  • Application.LoadLevelAddictiveAsync():异步附加式加载

👨‍💻👍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();
        };
    }
}


🎶(C线渲染器 LineRenderer


1.LineRenderer是什么

线渲染器 (Line Renderer)官方文档

LineRenderer是Unity提供的一个用于画线的组件来在场景中绘制线段
一般可以用于

  • 绘制攻击范围
  • 武器红外线
  • 辅助功能其它画线功能

2.LineRenderer相关API

  • 代码动态添加一个线段

      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>("XXX");
        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;
    

🎶(D手动范围检测


在这里插入图片描述

特点:

  • 1.执行该句代码时 进行一次范围检测 它是瞬时的
  • 2.范围检测相关API 并不会真正产生一个碰撞器 只是碰撞判断计算而已

共同参数:

  • 参数一:物体中心点
  • 参数二:物体的边长大小
  • 参数三:物体的角度
  • 参数四:检测指定层级(不填检测所有层)
  • 参数五:是否忽略触发器 UseGlobal-使用全局设置 Collide-检测触发器 Ignore-忽略触发器 (不填使用UseGlobal)
  • 返回值:在该范围内的触发器(得到了对象触发器就可以得到对象的所有信息)

UseGlobal-使用全局设置在该界面中已默认

在这里插入图片描述

1.方块状范围检测

  • Physics.OverlapBox ——返回值为数组,存储检测到的碰撞器
 Collider[] colliders = Physics.OverlapBox( Vector3.zero, Vector3.one, 
 Quaternion.AngleAxis(45, Vector3.up), 
        1 << LayerMask.NameToLayer("UI") |
        1 << LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal);
  • Physics.OverlapBoxNonAlloc——返回值为Int 表示检测的数量(最多6个参数)
if(Physics.OverlapBoxNonAlloc(Vector3.zero, Vector3.one, 自定义数组名) != 0)


2.球形状范围检测

无角度参数
参数二为球半径

  • Physics.OverlapSphere
    colliders = Physics.OverlapSphere(Vector3.zero, 5, 1 << LayerMask.NameToLayer("Default"));
  • Physics.OverlapSphereNonAlloc——同BOX
   if( Physics.OverlapSphereNonAlloc(Vector3.zero, 5, colliders) != 0 )

.3.胶囊体范围检测

参数一:半圆一中心点
参数二:半圆二中心点
参数三:半圆半径

  • Physics.OverlapCapsule
        colliders = Physics.OverlapCapsule(Vector3.zero, Vector3.up, 1, 1 << LayerMask.NameToLayer("UI"), QueryTriggerInteraction.UseGlobal);
  • Physics.OverlapCapsuleNonAlloc

if ( Physics.OverlapCapsuleNonAlloc(Vector3.zero, Vector3.up, 1, colliders ) != 0 )



🎶(GRay射线检测


  • 特点
    只需要判断一条线和物体的碰撞情况
    可以在指定点发射一个指定方向的射线
    判断该射线与哪些碰撞器相交,得到对应对象
    瞬时

  • 应用场景
    1.鼠标选择场景上一物体
    2.FPS射击游戏(无弹道-不产生实际的子弹对象进行移动)等

API

  • Ray X = new Ray(Vector3.right, Vector3.forward);
参数一参数二
起点方向
X.originX.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 物体信息类——得到相交的单个物体物理信息
    在这里插入图片描述
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) )
  • 碰撞到物体的名字 YY.collider.gameObject.name;
  • 碰撞到的点 YY.point
  • 法线信息 YY.normal
  • 碰撞到对象的位置 YY.transform.position
  • 碰撞到对象 离自己的距离 YY.distance等等

  • RaycastHit[] XX= Physics.RaycastAll——得到相交的多个物体物理信息

在这里插入图片描述
特点: 先碰到的在数组的后面

  • Physics.RaycastNonAlloc——返回的碰撞的数量 通过out得到数据
  if((r3, XX, 1000, 1 << LayerMask.NameToLayer("Monster"), 
  QueryTriggerInteraction.UseGlobal) > 0 )
 
        {
        }


🅰️系统路线学习点击跳转


【Unityc#专题篇】之c#进阶篇】

【Unityc#专题篇】之c#核心篇】

【Unityc#专题篇】之c#基础篇】

【Unity-c#专题篇】之c#入门篇】

【Unityc#专题篇】—进阶章题单实践练习

【Unityc#专题篇】—基础章题单实践练习

【Unityc#专题篇】—核心章题单实践练习


你们的点赞👍 收藏⭐ 留言📝 关注✅是我持续创作,输出优质内容的最大动力!


在这里插入图片描述


更多推荐

节能改造效果检测计算方法

声明本文是学习GB-T29314-2023电动机系统节能改造规范.而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们7综合评估7.1一般规定7.1.1电动机系统节能改造后,应对设备运行效果进行评估,改造后系统的生产效率和系统分界点指标应达到改造设计要求。7.1.2电动机系统改造后,应对与改造设备相关的

商城免费搭建之java商城 开源java电子商务Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c

1.涉及平台平台管理、商家端(PC端、手机端)、买家平台(H5/公众号、小程序、APP端(IOS/Android)、微服务平台(业务服务)2.核心架构SpringCloud、SpringBoot、Mybatis、Redis3.前端框架VUE、Uniapp、Bootstrap/H5/CSS3、IOS、Android、小程

Labelme分割标注软件

Labelme分割标注软件1、环境配置与安装1.1创建conda虚拟环境(建议)1.2安装Labelme2、简单使用2.1创建label标签文件2.2启动labelme2.3打开文件/文件夹2.4设置保存结果路径2.5标注目标2.6保存json文件格式3格式转换3.1转换语义分割标签3.2转换实例分割标签相关重要博文链

工单管理系统如何赋能售后服务?

当前时代,产品是企业发展的硬道理,但是想要留住客户,就必须提供更好的客户服务。而想要优化客户服务并不是一件简单的事情,企业可以借助工单管理系统来保证售后服务质量,为客户提供及时的帮助,从而达到为企业带来长期稳定的收益。怎么做呢?接下来我们就聊聊如何利用工单管理系统进行服务升级?一、精准关注客户需求客户在遇到问题的时候,

Linux中swap几乎耗尽,但物理内存还有空余的现象

故障现象:产生此现象的原因:swappiness配额设置了偏高的值。还有一个潜在的因素是某个程序因其自身对内存管理的缺陷,形成了zombie进程、且为及时关闭的处理任务还在持续消耗Mem及swap。解决办法:调低swappiness配额值,或者直接将swappiness配额设定为0。查看当前OS中的swappiness

iPhone辐射超标,发布三年突然禁售了

昨晚iPhone15预售大家抢到了吗?虽然13日发布会后大家的反应十分冷静,但身体还是很诚实,官网都排到6-7周以后了...在大伙都争着第一波尝鲜的时候,有一个地方正准备禁售iPhone。不用想肯定是欧盟某个国家啦,这两年的Type-C、应用侧载、可拆卸电池...搞事就没停过。法国数字经济部部长在本周发表的《巴黎人报》

前端用JavaScript实现桑基图(Sankey图)

前端用JavaScript实现桑基图(Sankey图)桑基图(Sankey图),是流图的一种,常用来展示事物的数量、发展方向、数据量大小等,在可视化分析中经常使用。本文,演示如何在前端用JavaScript绘制桑基图。注:本例使用JShaman数据展示JS代码混淆加密流程。先看效果:因为已有成熟的库可用,比如,可以使用

苹果给国内用户提供了最好的5G手机,一机在手畅通全球

在某专家不断胡扯苹果的假5G之时,其实是苹果给国内消费者提供了最好的5G手机,真正实现了一机在手畅通全球,技术永不过时,也不会因此花了冤枉钱,那么iPhone为何是最好的5G手机呢?一、5G技术一直在升级运营商在建设5G的过程中不断发现问题,首先是NSA和SA之争,当初业界认为SA才能完整实现5G的技术特征,NSA则降

SpringBoot接口中如何直接返回图片数据

SpringBoot接口中如何直接返回图片数据目录接口直接返回图片数据起因类似这种根据个人经验优雅的实现图片返回接口直接返回图片数据起因最近在做涉及到分享推广的业务,需要由业务员分享二维码进入推广页面,由于是新项目,前期预算和用量都有限,没有搭建对象存储服务,所以决定使用后台服务动态生成二维码图片直接图片数据并返回。首

Kubernetes学习大纲

Kubernetes(通常缩写为K8s)是一个用于自动化部署、扩展和管理容器化(通常是Docker容器)应用程序的开源平台。以下是一些Kubernetes的核心概念和相关的命令。1.集群(Cluster)和节点(Nodes)集群是Kubernetes的基础单元,由一组节点(物理或虚拟机)组成。命令:kubectlget

外滩大会观察|重估蚂蚁!

点击关注文丨刘雨琦,编丨王一粟“不同品种的小狗排队通过‘实名认证’、刷脸识别不仅能识别人,还能识别狗”。“人脸、虹膜、掌纹都已经不算黑科技,脑纹识别才是真的不可替代。”2023年上海外滩大会上,6G、无人安全检测实验室、脑纹核身、蚁鉴2.0、城市链、AI大脑训练、支付芯......改变未来的十大黑科技在会上齐亮相,充满

热文推荐