【Unity自制手册】游戏基础API大全

news2024/12/23 15:30:56

在这里插入图片描述


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

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

👨‍💻 本文由 秩沅 原创

👨‍💻 收录于专栏:UnityUI篇实战

🅰️基础


相关专栏:

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


文章目录

    • 🅰️基础
    • 前言
    • 🎶(==A==) MathF类
    • 🎶(==B==) 坐标系
    • 🎶(==C==) 三角函数
    • 🎶(==D==) 向量
    • 🎶(==E==) 四元数
    • 🎶(==F==) 延时函数
    • 🎶(==G==) Unity协程
    • 🎶(==H==)特殊文件夹
    • 🎶(==K==)Resources资源动态加载
    • 🎶(==L==)SceneManager场景资源动态加载
    • 🎶(==M==)线渲染器 LineRenderer
    • 🎶(==N==)手动范围检测
    • 🎶(==O==)Ray射线检测
    • 🅰️


前言


🎶(A MathF类


在这里插入图片描述

####👨‍💻👍1,MathF类的静态变量

Math和MathF的区别
mathf是unity封装的类它在基于math数学类的基础上添加了适合unity游相关的方法

强制类型转换和向下取整&向下取整
除去c#中常用的三个强转 —ceilToInt() 和 FloorInt()

钳制函数MathF.clamp(min ,xx ,max)
超过max取最大,小于min 取最小

Mathf.sigh()-判断正负

Mathf.MoveTowords()——无限接近但不完全相等

     //1.π - PI
    //2.取绝对值 - Abs
    //3.向上取整 - CeilToInt
    //4.向下取整 - FloorToInt
    //5.钳制函数 - Clamp
    //6.获取最大值 - Max
    //7.获取最小值 - Min
    //8.一个数的n次幂 - Pow
    //9.四舍五入 - RoundToInt
    //10.返回一个数的平方根 - Sqrt
    //11.判断一个数是否是2的n次 - IsPowerOfTwo
    //12.判断正负数 - Sign

👨‍💻👍1,MathF类的静态变量


  • print(Mathf.Deg2Rad+“,度到弧度换算常量”);
  • print(Mathf.Rad2Deg+ “,弧度到度换算常量”);
  • print(Mathf.Infinity+“正无穷大的表示形式”);
  • print(Mathf.NegativeInfinity + “负无穷大的表示形式”);
  • print(Mathf.PI);

👨‍💻👍2,MathF类的静态函数


  • print(Mathf.Abs(-1.2f)+ “,-1.2的绝对值”);

  • print(Mathf.Acos(1)+“,1(以弧度为单位)的反余弦”);

  • print(Mathf.Floor(2.74f)+“,小于或等于2.74的最大整数”);

  • print(Mathf.FloorToInt(2.74f)+“,小于或等于2.74的最大整数”);


  • Mathf.Lerp(1,2,0.5f) ——,a和b按参数t进行线性插值

  • Mathf.LerpUnclamped(1, 2, -0.5f)——,a和b按参数t进行线性插值

  • float start = 0;
    float result = 0;
    float time = 0;
    //Lerp函数公式
    //result = Mathf.Lerp(start, end, t);
    //t为插值系数,取值范围为 0~1
    //result = start + (end - start)*t

  • 插值运算用法一
    每帧改变start的值——变化速度先快后慢,位置无限接近,但是不会得到end位置
    start = Mathf.Lerp(start, 10, Time.deltaTime);

  • 插值运算用法二
    每帧改变t的值——变化速度匀速,位置每帧接近,当t>=1时,得到结果
    time += Time.deltaTime;
    result = Mathf.Lerp(start, 10, time);


👨‍💻👍3,MathF类中的 倒计时 函数


Math.MoveTowards()

   void Update()
    {
        print("游戏倒计时:" + endTime);
        endTime = Mathf.MoveTowards(endTime,0,0.1f); //每次减0.01 直到endTime为0     
    } 

🎶(B 坐标系


在这里插入图片描述

①世界坐标系——transform…
②物体坐标系——transform.Local…
③屏幕坐标系
④视口坐标系——用的较少,主要调整窗口

坐标转换

在这里插入图片描述


🎶(C 三角函数


在这里插入图片描述

弧度转角度

float rad = 1;
float anger = rad * Mathf.Rad2Deg;

角度转弧度

anger = 1;
rad = anger * Mathf.Deg2Rad;

三角函数

//注意:需要加上弧度值

Mathf.Sin(30 * Mathf.Deg2Rad) //0.5
Mathf.Cos(60 * Mathf.Deg2Rad) //0.5

通过反三角函数求弧度

  • 弧度 = Mathf.Asin() / Acos();

  • 反三角函数得到的结果是 正弦或者余弦值对应的弧度

      rad = Mathf.Asin(0.5f);         //弧度
      print(rad * Mathf.Rad2Deg);     //角度
    

练习

【Unity每日一记】让一个物体按余弦曲线移动—(三角函数的简单运用)


🎶(D 向量


在这里插入图片描述


👨‍💻👍常用


位置 + 向量 = 平移位置
位置 - 向量 = 平移位置
位置 - 位置 = 向量
向量 - 位置 = 无意义
向量 * 向量 = 向量
向量 * 值 = 扩大模长

  • 向量之间的距离 ——Vector3.Disrtance() 向量 和向量之间相减 A - B

  • 0向量——Vector.zero()

  • 向量模长——Vector3.magnitude() 相等于向量之间的距离

  • 单位向量——Vector3.normalized()适用于物体移动的时候的单位化计算

  • 向量+向量 和向量+位置 的区别——前者为向量(高数中的向量相加)后者为相当于扩大作用结果是位置

  • 位置-位置的几何意义——结果为向量 ,向量-向量 = 向量

  • 向量的加减乘除 —— 加减应用于物体平移 乘除的进行缩放要用本地坐标

  • 向量的点乘——Vector3.Dot 结果为余弦值,用来判断对象的大概方位(前后)和夹角

  • 向量的叉乘——Vector3.Dot 结果为法向量垂直于两个向量构成的平面,判断(左右)

  • 向量的线性差值运算——直线轨迹
    vector3.Lerp( S,E,T); ——S为开始值,E为最终值
    ①每帧改变S的值(先快后慢)—适合摄像机的跟随
    ②每帧改变T的值(匀速变化)—适合摄像机的跟随

线性插值
 //1.先快后慢 每帧改变start位置 位置无限接近 但不会得到end位置
 transform.position = Vector3.Lerp(   
 transform.position,target.position, Time.deltaTime);
        //2.匀速 每帧改变时间  当t>=1时 得到结果
        //当time>=1时  改变了目标位置后会直接瞬移到目标位置
        if(nowTarget != target.position)
        {
            nowTarget = target.position;
            time = 0;
            startPos = B.position;
        }
        time += Time.deltaTime;
        B.position = Vector3.Lerp(startPos, nowTarget, time);
 
  • 向量的球形差值运算——弧形轨迹
    vector3.SLerp( S,E,T); ——S为开始值,E为最终值
    对两个向量进行插值计算 t的取值范围为0~1
  球形插值
 C.position = Vector3.Slerp(Vector3.right * 10, Vector3.left * 10 + 
 Vector3.up*0.1f, time*0.01f);

【Unity每日一记】向量操作摄像机的移动(向量加减)
【Unity每日一记】关于物体(敌方)检测—(向量点乘相关)
【Unity每日一记】方位辨别—向量的叉乘点乘结合


🎶(E 四元数


在这里插入图片描述

特点

1,绕着某个轴转x度,轴可以是任意轴(轴-角对)
2,避免了欧拉角中万向节死锁的问题
3,避免了欧拉角中角度变化不在(-180,180)范围内的问题

  • 四元数解决了欧拉角中万向节死锁的问题
  • 当Unity中transform的X轴为90度是发生万向节死锁,此时不管移动y轴还是z轴,物体都往X轴进行旋转

原理公式

假定四元数Q绕着n轴旋转β度
在这里插入图片描述

 //计算原理_绕x轴旋转60度
  Quaternion q = new Quaternion(Mathf.Sin(30 * Mathf.Deg2Rad),
   0, 0, Mathf.Cos(30 * Mathf.Deg2Rad));

直接简单公式

  • Quaternion.AngleAxis(角度数值,轴(向量))
//绕x轴旋转60度
 Quaternion q = Quaternion.AngleAxis(60, Vector3.right);

API常用

1.四元数和欧拉角转换

  • 欧拉角转四元数
    Quaternion A = Quaternion.Euler(60, 0, 0);

  • 四元数转欧拉角
    A.eulerAngles


2.旋转

四元数相乘代表旋转四元数

//四元数旋转方法
transform.rotation *= Quaternion.AngleAxis(30,vector3.forword);


3.单位化四元数

  • [1,(0,0,0)]和[-1,(0,0,0)]都是单位四元数
    表示没有旋转量
  • Quaternion.identity _用于对象角度初始化
Instantiate(XXXX, Vector3.zero, Quaternion.identity);

4.四元数的差值运算

  • 特点: Lerp() 和Slerp();官方建议一般用Slerp();
  • 先快后慢旋转
transform.rotation = Quaternion.Slerp(transform.rotation, 
target.rotation, Time.deltaTime);
  • 匀速旋转—— time>=1 到达目标
  time += Time.deltaTime;
  B.transform.rotation = Quaternion.Slerp(start,
   target.rotation, time);

5.四元数的旋转看向——LookAt的本质

Quaternion A = Quaternion.LookRotation(B.position - A.position);

    //B - A = AB 向量 ,所以传入的是向量

transform.rotation = A;

【Unity每日一记】进行发射,位置相关的方法总结
【Unity每日一记】摄像机相关向量代码API大全


🎶(F 延时函数


在这里插入图片描述

应用于:方法活物体的延时执行 和 计时器应用

👨‍💻👍1.延时调用


Invoke(“名字”,秒数)
InvokeRepeating(“名字”,第一次延时执行的时间,之后每次调用间隔秒数)

  • 使用协程的延时调用也可以
  • 使用计时器-MathF.MoveTowords也可以达到延时调用的效果
void Start()
    {
        //调用
        //Invoke("CreateGris",3);
        InvokeRepeating("CreateGris",1,1);
    }
    private void CreateGris()
    {
        Instantiate(grisGo); //实例化
    }


👨‍💻👍2.取消调用


CancelInvoke(“方法名”);暂停当前延时调用该方法
CancelInvoke();停止所有的延时调用方法


👨‍💻👍3.判断是否调用


● IsInvoke(“方法名”);判断当前方法是否进行了延时调用
● IsInvoke();停止程序中所有的延时调用

生命函数

  • 原理:
    脚本依附对象失活 或者 脚本自己失活 _ ——延迟函数可以继续执行
    脚本依附对象销毁或者脚本移除_——延迟函数无法继续执行
 private void OnEnable()
    {
        //对象激活 的生命周期函数中 开启延迟(重复执行的延迟)
    }

    private void OnDisable()
    {
        //对象失活 的生命周期函数中 停止延迟
    }

🎶(G Unity协程


在这里插入图片描述

Unity中的多线程

  • Unity支持多线程,但是操作相关对象还得在主线程中实现,要注意关闭线程最后
  • 但是可以作为复杂算法或逻辑运算计算的复线程,(线程是独立运行的管道)——专门用一个线程来做这些复杂的运算

协程和多线程的区别

  • 1.协程不是多线程,并且在继承 Mononabehavar类下使用
  • 2.多线程是和主线程区分开来的
  • 3.协程是在主线程中运行的,只是分时分布将逻辑进行处理

协程主要作用


1.延时调用

 IEnumerator ChangeState()  //协程迭代器的定义
    {
        //暂停几秒(协程挂起)
        yield return new WaitForSeconds(2);
        //暂停两秒后再切入走路的动画
        animator.Play("Walk");`    
   }

2.和其他逻辑一起协同执行

,比如一些很耗时的工作,在这个协程中执行异步操作,比如下载文件,加载文件,异步生成怪物等

*资源加载一般是一个比较耗时的操作,如果直接放在主线程中会导致游戏卡顿,通常会放到异步线程中去执行。
在这里插入图片描述

3.分布分时执行复杂算法或繁杂逻辑

比如创建随机创建一万个球不卡帧

在这里插入图片描述

 float time = 0;
    IEnumerator CreatCorutine( int number)
    {
        for (int i = 0; i < number; i++)
        {
                GameObject ball = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                ball.transform.position = new Vector3(Random.Range(0, 100), Random.Range(0, 100), Random.Range(0, 100));
            if(i % 1000 == 0)
            {
                yield return new WaitForSeconds(1);
            }      
        }                   
    }
    private void Update()
    {
        if(Input.GetKeyDown (KeyCode.Space))
        {
            StartCoroutine(CreatCorutine(10000));
        }    
    }

协程的声明

  • 返回值为IEnumerator类型及其子类
  • 函数中通过 yield return 进行返回
// MyCoroutine为自定义协程名
IEnumerator MyCoroutine(int i, string str)
    {
    //分时分布执行。先打印i然后暂停1秒之后再打印3242
        print(i); 
        yield return new WaitForSeconds(1f);
        print("3242");     
        
    }
    


协程的开启和停止

  • 开启
    StartCoroutine(MyCoroutine(1, “123”));

  • 关闭所有协程
    StopAllCoroutines();

  • 关闭指定协程
    StopCoroutine(c1);

只有当组件失活时协程不会失活,对象失活时协程也会失活

void start()
{
启动方法一 String:
StartCoroutine("ChangeState"); //括号内的是协程名
启动方法二 函数:
StartCoroutine(ChangeState());
启动方法三 接口:                   //有参协程只能用该方法开启
IEnumerator ie = ChangeState();
StartCoroutine(ie);

停止方法一 String:
StopCoroutine("ChangeState");
停止方法二 函数:
StopCoroutine(ChangeState());
停止方法三 接口:  
StopCoroutine(ie);
停止方法四 协程:  
Coroutine c1 = StartCoroutine( ChangeState());
StopCoroutine(c1);
停止所有协程:
StopAllCoroutines();
}

-------------协程中的 yield------------
//1.下一帧执行
        yield return 数字;
        yield return null;
        //在Update和LateUpdate之间执行
        
//表示在本帧帧末执行以下逻辑
       yield return new WaitForEndOfFrame();
 
//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;


👨‍💻👍4.协程中的协程和有参协程


    StartCoroutine("CreateBoss");  //启动协程
    
  //协程1 功能实时实例化游戏物体 
 IEnumerator CreateBoss()   
    {
        StartCoroutine(SetCreateCount(5));
        while (true) //功能实时实例化游戏物体
        {
            if (BossNum>=BossCount)
            {
             yield break; //在协程中break前面要加 yield
            }
            Instantiate(animator.gameObject);
            BossNum++;
            yield return new WaitForSeconds(2);
        }
    }
    
 //协程2 功能实时实例化游戏物体  
 IEnumerator SetCreateCount(int num) 
    {
        BossCount =num;
        yield return null; //暂停一帧
---------------------
此时如果这里只是暂停一帧的话,
那么上面调该有参协程的协程体中,
后面的语句并未生效,因为暂停一帧后,
后面的方法已经执行了,
所以此时的BossCount并不等于有参传递的5
(当然BossCount是全局变量)
---------------------
    }
    

协程的本质

  • 1.本体为迭代器
  • 2.协程调度器(可自己实现)
//Ieunmrator接口中的两个成员:MoveNext_移动下一个  Current——当前返回值
 while(ie.MoveNext())
        {
            print(ie.Current);
        }

🎶(H特殊文件夹


在这里插入图片描述

  • 特殊文件夹读写性

1.Resources 可读 不可写 打包后找不到
2.Application.streamingAssetsPath 可读 PC端可写 找得到
3.Application.dataPath 打包后找不到
4.Application.persistentDataPath 可读可写找得到


1.工程路径获取

该方式 获取到的路径 一般情况下 只在 编辑模式下使用
游戏发布过后 该路径就不存在了

  • Application.dataPath

2.Resources资源文件夹

一般不获取路径只能使用Resources相关API进行加载

  • 注意:
    手动创建
  • 作用:
    资源文件夹
    1.需要通过Resources相关API动态加载的资源需要放在其中
    2.该文件夹下所有文件都会被打包出去
    3.打包时Unity会对其压缩加密
    4.该文件夹打包后只读 只能通过Resources相关API加载

3.StreamingAssets 流动资源文件夹

  • Application.streamingAssetsPath
  • 注意:
    手动创建
  • 作用:
    流文件夹
    1.打包出去不会被压缩加密,可以任由我们摆布
    2.移动平台只读,PC平台可读可写
    3.可以放入一些需要自定义动态加载的初始资源
    4.不愿意放在Resources中的资源可以放入StreamingAssets中

4.persistentDataPath 持久数据文件夹

  • 注意:
    不需要手动创建

  • Application.persistentDataPath
    不同平台路径不一样

  • 作用:
    固定数据文件夹
    1.所有平台都可读可写
    2.一般用于放置动态下载或者动态创建的文件,游戏中创建或者获取的文件都放在其中(热更新会用到)

5.Plugins 插件文件夹

  • 注意
    不需要手动创建
  • 作用:
    插件文件夹
    不同平台的插件相关文件放在其中
    比如IOS和Android平台

6. Editor 编辑器文件夹

  • 注意
    手动创建
  • 作用
    编辑器文件夹
    1.开发Unity编辑器时,编辑器相关脚本放在该文件夹中
    2.文件夹中内容不会被打包出去

7. 默认资源文件夹 Standard Assets

  • 注意
    手动创建

  • 作用:
    默认资源文件夹
    一般Unity自带资源都放在这个文件夹下
    代码和资源优先被编译

  • 一般不用


🎶(KResources资源动态加载


在这里插入图片描述

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


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



🎶(LSceneManager场景资源动态加载



👨‍💻👍加载场景的方法


  • 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();
        };
    }
}


🎶(M线渲染器 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;
    

🎶(N手动范围检测


在这里插入图片描述

特点:

  • 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 )



🎶(ORay射线检测


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

  • 应用场景
    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 )
 
        {
        }

【Unity每日一记】模仿FPS射击,用弹痕作画的原理如此简单

【Unity每日一记】拖拽放置类游戏的行为原来和这个API有关

🅰️


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

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

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

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

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

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

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


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


在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/920649.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无人机空管电台-中大型无人机远程VHF语音电台系统

方案背景 中大型无人机在执行飞行任务时&#xff0c;特别是在管制空域飞行时地面航管人员需要通过语音与无人机通信。按《无人驾驶航空器飞行管理暂行条例》规定&#xff0c;中大型无人机应当进行适航管理。物流无人机和载人eVTOL都将进行适航管理&#xff0c;所以无人机也要有…

水经微图网页版基础名词

水经微图网页版&#xff0c;可轻松将关注的地点制作成您的个人地图。 您可以在任意位置添加标注点或绘制地图&#xff0c;查找地点并将其保存到您的地图中&#xff0c;或导入地图数据迅速制作地图并保存&#xff0c;您还可以运用图标和颜色展示个性风采&#xff0c;从而可让每…

ACM模式(基础输入输出)

import java.lang.*; import java.util.*; public class Main{public static void main(String[] args){Scanner in new Scanner(System.in);while(in.hasNextInt()){//下一行是否有数据int ain.nextInt();int bin.nextInt();System.out.println(ab);}} }Java方法间的调用 http…

本地部署 Stable Diffusion(Windows 系统)

相对于使用整合包&#xff0c;手动在 Windows 系统下本地部署 Stable Diffusion Web UI&#xff08;简称 SD-WebUI&#xff09;&#xff0c;更能让人了解一些事情的来龙去脉。 一、安装前置软件&#xff1a;Python 和 Git 1、安装 Python for windows。 下载地址 https://www.p…

Paramiko远程操作Linux服务器

在日常工作中我们经常会跟Linux打交道&#xff0c;对于测试同学来说&#xff0c;使用Linux的场景还是比较多的&#xff0c;比如&#xff1a;搭建测试环境、查看日志信息、修改配置文件、监控服务资源等。 本篇将介绍一个Python的第三方库Paramiko&#xff0c;使用Paramiko&…

java八股文面试[java基础]——接口和抽象类的区别

知识来源&#xff1a; 【基础】接口和抽象类_哔哩哔哩_bilibili 【2023年面试】Java中抽象类和接口有什么区别_哔哩哔哩_bilibili

Stable Diffusion 系列教程 | 如何获得更高清优质的AI绘画

目录 1 高清修复 1.1 原理 1.2 基本操作 1.3 优缺点 2 UpScale 放大脚本 2.1 原理 2.2 基本操作 2.3 优缺点 3 附加功能放大 3.1 原理 3.2 基本操作 3.3 优缺点 优化出图质量&#xff0c;产出更高清&#xff0c;分辨率更高&#xff0c;更有细节的绘画作品呢&#x…

Ubuntu 配置国内源

配置国内源 因为众所周知的原因&#xff0c;国外的很多网站在国内是访问不了或者访问极慢的&#xff0c;这其中就包括了Ubuntu的官方源。 所以&#xff0c;想要流畅的使用apt安装应用&#xff0c;就需要配置国内源的镜像。 市面上Ubuntu的国内镜像源非常多&#xff0c;比较有…

质量追溯系统方案

一、需求分析 在制造行业中&#xff0c;产品质量追溯至关重要。本方案旨在建立一个完善的质量追溯系统&#xff0c;满足以下需求&#xff1a; 对象追溯&#xff1a;能够追踪产品从原材料到成品的整个生产过程&#xff0c;以及与产品相关的所有信息。工序追溯&#xff1a;能够…

【大模型AIGC系列课程 2-2】大语言模型的“第二大脑”

1. 大型语言模型的不足之处 很多人使用OpenAI提供的GPT系列模型时都反馈效果不佳。其中一个主要问题是它无法回答一些简单的问题。 ● 可控性:当我们用中文问AI一些关于事实的问题时,它很容易编造虚假答案。 ● 实时性:而当你询问它最近发生的新闻事件时,它会干脆地告诉你…

Android 系统桌面 App —— Launcher 开发(1)

Android 系统桌面 App —— Launcher 开发&#xff08;1&#xff09; Launcher简介 Launcher就是Android系统的桌面&#xff0c;俗称“HomeScreen”也就是我们开机后看到的第一个App。launcher其实就是一个app&#xff0c;它的作用是显示和管理手机上其他App。目前市场上有很…

激活函数总结(十八):激活函数补充(RBF、SQ-RBF)

激活函数总结&#xff08;十八&#xff09;&#xff1a;激活函数补充 1 引言2 激活函数2.1 Radial Basis Function (RBF)激活函数2.2 Square Radial Basis Function&#xff08;SQ-RBF&#xff09;激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系列激活函数 (Sig…

《动手学深度学习》-28批量归一化

沐神版《动手学深度学习》学习笔记&#xff0c;记录学习过程&#xff0c;详细的内容请大家购买书籍查阅。 b站视频链接 开源教程链接 批量归一化 将参数的量级进行统一&#xff0c;使得深度神经网络更好收敛&#xff1a; γ \gamma γ和 β \beta β是可学习的参数&#xf…

Shader Graph24-摇晃树叶

一、开始Unreal&#xff0c;新建Materail命名为DemoUVRotation。 二、在网上找个素材&#xff0c;去掉背景&#xff0c;保证树根是在边上的位置 三、换上我们的图片&#xff0c;在time节点后添加一个sine&#xff0c;让他的位置是周期性的就行了。 四、结果

Java接收前端请求体方式

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 文章目录 RequestBodyPathVariableRequestParamValidated方法参数校验方法返回值校验 RequestHeaderHttpServletRequest ## Java接收前端请求体的方式 请求体&#xf…

Python - 面向对象的属性,类方法,静态方法,实例方法的区别及用法详解

一. 前言 在Python的面向对象编程中&#xff0c;类属性和实例属性是两个不同的概念&#xff0c;它们在作用域和使用方式上有所区别。在Python中的面向对象编程中有三种方法&#xff1a;实例方法、类方法和静态方法&#xff0c;它们之间的差异主要体现在参数传递和调用方式上。…

java八股文面试[数据结构]——集合框架

Java集合体系框架 Java集合类主要由两个根接口Collection和Map派生出来的。 Collection派生出了三个子接口&#xff1a; Map接口派生&#xff1a; Map代表的是存储key-value对的集合&#xff0c;可根据元素的key来访问value。 因此Java集合大致也可分成List、Set、Queue、Map…

赋能道路交通场景,九州未来助力建成广西交科车路协同智能网联示范园区

智慧高速车路协同需要更加稳固的技术基座 智慧高速是中国高速公路建设的热点之一&#xff0c;车路协同又是未来智慧高速建设的核心内容。高速公路运行环境相对简单、主体权责清晰、路侧机电设施齐全&#xff0c;具备开展车路协同创新示范的良好条件。 广西交科集团&#xff0…

使用element-plus组件,默认显示英文 转换为中文

最近在边写项目边学习vue3 所以这几天没有更新 找机会把vue3的知识也统计一下吧 先说今天遇到的问题 最近做项目的时候使用element-plus分页组件时发现&#xff0c;显示的不是中文的了&#xff0c;是英文的 解决方法 在app.vue里面配置 <template><el-config-provi…

【ES】笔记-生成器函数与调用

function* function* 这种声明方式 (function关键字后跟一个星号&#xff09;会定义一个生成器函数 (generator function)&#xff0c;它返回一个 Generator 对象。 function * gen(){console.log("heloo generator")}如何调用呢&#xff1f;先看下里面的内容 返回…