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

👨💻个人主页:@元宇宙-秩沅
👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!
👨💻 本文由 秩沅 原创
⭐🅰️基础⭐
相关专栏:
⭐【软件设计师高频考点暴击】
文章目录
- ⭐🅰️基础⭐
- ⭐前言⭐
- 🎶(==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秒之后再打印3242print(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自带资源都放在这个文件夹下
 代码和资源优先被编译
-  一般不用 
🎶(K)Resources资源动态加载

###同步加载**———————
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();
🎶(L)SceneManager场景资源动态加载
👨💻👍加载场景的方法
- 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 )🎶(O)Ray射线检测
-  特点 
 只需要判断一条线和物体的碰撞情况
 可以在指定点发射一个指定方向的射线
 判断该射线与哪些碰撞器相交,得到对应对象
 瞬时
-  应用场景 
 1.鼠标选择场景上一物体
 2.FPS射击游戏(无弹道-不产生实际的子弹对象进行移动)等
API
- Ray X = new Ray(Vector3.right, Vector3.forward);
| 参数一 | 参数二 | 
|---|---|
| 起点 | 方向 | 
| 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 物体信息类——得到相交的单个物体物理信息
  
| 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#专题篇】—核心章题单实践练习
你们的点赞👍 收藏⭐ 留言📝 关注✅是我持续创作,输出优质内容的最大动力!、

相关文章:
 
【Unity自制手册】游戏基础API大全
👨💻个人主页:元宇宙-秩沅 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 秩沅 原创 👨💻 收录于专栏:Uni…...
【LVS】4、HAProxy搭建web集群
目前常见的Web集群调度器分为软件和硬件 软件通常使用开源的LVS、Haproxy、Nginx LVS性能最好(基于内核转发),但是搭建相对复杂;Nginx的upstream模块支持群集功能,但是对群集节点健康检查功能不强,高并发性…...
 
【应用层】网络基础 -- HTTP协议
再谈协议HTTP协议认识URLurlencode和urldecodeHTTP协议格式HTTP的方法HTTP的状态码HTTP常见HeaderHTTP周边会话保持 再谈协议 协议是一种 “约定”. socket api的接口,在读写数据时,都是按 “字符串” 的方式来发送接收的(tcp是以字节流的方式发送的&am…...
【线性DP】模型总结(terse版)
【线性DP】模型总结 最长上升子序列 DP法  dp[i]表示以i结尾的最长上升子序列的长度。  对于每个i,遍历j1~i-1,若a[j] < a[i], 则dp[i] max(dp[i], dp[j] 1); 二分法  可以优化时间复杂度。  dp[]数组用来存储当前最长上升子序列。  若dp[]数…...
conda 常用命令
conda 常用命令 一、创建环境二、删除环境三、环境重命名四 、查看环境列表五、进入某个虚拟环境六、退出当前环境七、查看当前虚拟环境下的所有安装包八、安装或卸载包(进入虚拟环境之后)九、分享虚拟环境十、源服务器管理十一、升级十二、卸载十三、卸载十四、pip…...
前端面试:【异步编程】Callback、Promise和Async/Await
嗨,亲爱的JavaScript探险家!在JavaScript开发的旅程中,你会经常遇到异步编程的需求。为了处理异步操作,JavaScript提供了多种机制,包括Callbacks、Promises和Async/Await。本文将深入介绍这些机制,让你能够…...
大数据(四):Pandas的基础应用详解
专栏介绍 结合自身经验和内部资料总结的Python教程,每天3-5章,最短1个月就能全方位的完成Python的学习并进行实战开发,学完了定能成为大佬!加油吧!卷起来! 全部文章请访问专栏:《Python全栈教…...
 
计算机网络第3章(数据链路层)
计算机网络第3章(数据链路层) 3.1 数据链路层概述3.1.1 概述3.1.2 数据链路层使用的信道3.1.3 三个重要问题 3.2 封装成帧3.2.1 介绍3.2.2 透明传输3.2.3 总结 3.3 差错检测3.3.1 介绍3.3.2 奇偶校验3.3.3 循环冗余校验CRC(Cyclic Redundancy Check)3.3.…...
 
stm32之4.时钟体系
3.时钟体系(给单片机提供一个非常稳定的频率信号) ①可以使用三种不同的时钟源来驱动系统时钟(SYSCLK),CPU运行的频率为168MHZ; HSI(RC振荡器时钟,也就是高速内部时钟,一般来说很少用,因为精度…...
 
RPC和HTTP协议
RPC 全称(Remote Procedure Call),它是一种针对跨进程或者跨网络节点的应用之间的远程过程调用协议。 它的核心目标是,让开发人员在进行远程方法调用的时候,就像调用本地方法一样,不需要额外为了完成这个交…...
BUGFix:onnx -> TensorRT转换过程失败
先附上相关的onnx2trt的部分代码: def onnx2trt(onnx_path):logger trt.Logger(trt.Logger.ERROR)builder trt.Builder(logger)network builder.create_network(1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))parser trt.OnnxParser(netw…...
FFMPEG小白常用命令行
序列帧转H264视频 ffmpeg -r 60 -f image2 -s 1920x1080 -i fram%d.jpg -vcodec libx264 -crf 25 -pix_fmt yuv420p test.mp4 -vcodec h264 .\ffmpeg -r 60 -f image2 -s 1920x1080 -i %04d.jpeg -vcodec h264 test.mp4 %04d 表示用零来填充直到长度为4,i.e 000…...
 
个性定制还是纯粹简约:探寻界面选择背后的心理宇宙
在数码世界中,我们的界面选择成为了一张架起的桥梁,连接着个性的渴望与效率的追求。当我们面对个性化定制界面和极简版原装界面,我们仿佛站在了一座分岔路口,左右各有一片令人心驰神往的风景。究竟是走向五光十色的个性世界&#…...
 
【Java 高阶】一文精通 Spring MVC - 转发重定向(四)
👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主 ⛪️ 个人社区&#x…...
 
嵌入式Linux开发实操(十):ADC接口开发
#前言 ADC就是模数转换,可以用来接一些模拟量设备,所谓模拟量就是波形不是方波而是各种包络形状的波形的信号,比如电压、电流等电信号或压力、温度、湿度、位移、声音等非电信号,ADC就是将这些信号转换为数字方波信号,以便于信息传递的。 #ADC硬件设计 key按键连接了AD…...
 
精进语言模型:探索LLM Training微调与奖励模型技术的新途径
大语言模型训练(LLM Training) LLMs Trainer 是一个旨在帮助人们从零开始训练大模型的仓库,该仓库最早参考自 Open-Llama,并在其基础上进行扩充。 有关 LLM 训练流程的更多细节可以参考 【LLM】从零开始训练大模型。 使用仓库之…...
数据采集:selenium 提取 Cookie 自动登陆
写在前面 工作需要,简单整理博文内容涉及 通过 selenium 实现自动登陆理解不足小伙伴帮忙指正 对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的&#x…...
 
[Go版]算法通关村第十三关黄金——数字数学问题之数论问题(最大公约数、素数、埃氏筛、丑数)
目录 题目:辗转相除法(求最大公约数)思路分析:辗转相除法(也叫欧几里得算法)gcd(a,b) gcd(b,a mod b)复杂度:时间复杂度 O ( n l o g ( m a x ) ) O(nlog(max)) O(nlog(max))、空间复杂度 O (…...
 
Qt双击某一文件通过自己实现的程序打开,并加载文件显示
双击启动 简述方法一方法二注意 简述 在Windows系统中,双击某类扩展名的文件,通过自己实现的程序打开文件,并正确加载及显示文件。有两种方式可以到达这个目的。 对于系统不知道的扩展名的文件,第一次打开时,需要自行…...
硬件产品的量产问题------硬件工程师在产线关注什么
前言: 产品开发测试无误,但量产缺遇到很多不良甚至DOA问题。 硬件开发过程中如何确保产线的治具、生产及硬件工程师在产线需要关注一些什么。 坚信:好的产品是要可以做出来的。 1、禁忌: 禁忌热插拔;禁忌测试不防呆…...
 
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
 
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
 
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
 
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
 
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
 
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
