?????個(gè)人主頁(yè):@元宇宙-秩沅
????? hallo 歡迎 點(diǎn)贊?? 收藏? 留言?? 加關(guān)注?!
????? 本文由 秩沅 原創(chuàng)
????? 收錄于專(zhuān)欄:UnityUI篇實(shí)戰(zhàn)
????基礎(chǔ)?
相關(guān)專(zhuān)欄:
?【軟件設(shè)計(jì)師高頻考點(diǎn)暴擊】
?前言?
??(A) MathF類(lèi)
####???????1,MathF類(lèi)的靜態(tài)變量
?Math和MathF的區(qū)別:
mathf是unity封裝的類(lèi)它在基于math數(shù)學(xué)類(lèi)的基礎(chǔ)上添加了適合unity游相關(guān)的方法
?強(qiáng)制類(lèi)型轉(zhuǎn)換和向下取整&向下取整:
除去c#中常用的三個(gè)強(qiáng)轉(zhuǎn) —ceilToInt() 和 FloorInt()
?鉗制函數(shù)MathF.clamp(min ,xx ,max)
超過(guò)max取最大,小于min 取最小
?Mathf.sigh()-判斷正負(fù)
?Mathf.MoveTowords()——無(wú)限接近但不完全相等
//1.π - PI
//2.取絕對(duì)值 - Abs
//3.向上取整 - CeilToInt
//4.向下取整 - FloorToInt
//5.鉗制函數(shù) - Clamp
//6.獲取最大值 - Max
//7.獲取最小值 - Min
//8.一個(gè)數(shù)的n次冪 - Pow
//9.四舍五入 - RoundToInt
//10.返回一個(gè)數(shù)的平方根 - Sqrt
//11.判斷一個(gè)數(shù)是否是2的n次 - IsPowerOfTwo
//12.判斷正負(fù)數(shù) - Sign
???????1,MathF類(lèi)的靜態(tài)變量
- print(Mathf.Deg2Rad+“,度到弧度換算常量”);
- print(Mathf.Rad2Deg+ “,弧度到度換算常量”);
- print(Mathf.Infinity+“正無(wú)窮大的表示形式”);
- print(Mathf.NegativeInfinity + “負(fù)無(wú)窮大的表示形式”);
- print(Mathf.PI);
???????2,MathF類(lèi)的靜態(tài)函數(shù)
-
print(Mathf.Abs(-1.2f)+ “,-1.2的絕對(duì)值”);
-
print(Mathf.Acos(1)+“,1(以弧度為單位)的反余弦”);
-
print(Mathf.Floor(2.74f)+“,小于或等于2.74的最大整數(shù)”);
-
print(Mathf.FloorToInt(2.74f)+“,小于或等于2.74的最大整數(shù)”);
-
Mathf.Lerp(1,2,0.5f) ——,a和b按參數(shù)t進(jìn)行線性插值
-
Mathf.LerpUnclamped(1, 2, -0.5f)——,a和b按參數(shù)t進(jìn)行線性插值
-
float start = 0;
float result = 0;
float time = 0;
//Lerp函數(shù)公式
//result = Mathf.Lerp(start, end, t);
//t為插值系數(shù),取值范圍為 0~1
//result = start + (end - start)*t -
插值運(yùn)算用法一
每幀改變start的值——變化速度先快后慢,位置無(wú)限接近,但是不會(huì)得到end位置
start = Mathf.Lerp(start, 10, Time.deltaTime); -
插值運(yùn)算用法二
每幀改變t的值——變化速度勻速,位置每幀接近,當(dāng)t>=1時(shí),得到結(jié)果
time += Time.deltaTime;
result = Mathf.Lerp(start, 10, time);
???????3,MathF類(lèi)中的 倒計(jì)時(shí) 函數(shù)
Math.MoveTowards()
void Update()
{
print("游戲倒計(jì)時(shí):" + endTime);
endTime = Mathf.MoveTowards(endTime,0,0.1f); //每次減0.01 直到endTime為0
}
??(B) 坐標(biāo)系
①世界坐標(biāo)系——transform…
②物體坐標(biāo)系——transform.Local…
③屏幕坐標(biāo)系
④視口坐標(biāo)系——用的較少,主要調(diào)整窗口
坐標(biāo)轉(zhuǎn)換
??(C) 三角函數(shù)
弧度轉(zhuǎn)角度
float rad = 1;
float anger = rad * Mathf.Rad2Deg;
角度轉(zhuǎn)弧度
anger = 1;
rad = anger * Mathf.Deg2Rad;
三角函數(shù)
//注意:需要加上弧度值
Mathf.Sin(30 * Mathf.Deg2Rad) //0.5
Mathf.Cos(60 * Mathf.Deg2Rad) //0.5
通過(guò)反三角函數(shù)求弧度
-
弧度 = Mathf.Asin() / Acos();
-
反三角函數(shù)得到的結(jié)果是 正弦或者余弦值對(duì)應(yīng)的弧度
rad = Mathf.Asin(0.5f); //弧度 print(rad * Mathf.Rad2Deg); //角度
練習(xí)
【Unity每日一記】讓一個(gè)物體按余弦曲線移動(dòng)—(三角函數(shù)的簡(jiǎn)單運(yùn)用)
??(D) 向量
???????常用
位置 + 向量 = 平移位置
位置 - 向量 = 平移位置
位置 - 位置 = 向量
向量 - 位置 = 無(wú)意義
向量 * 向量 = 向量
向量 * 值 = 擴(kuò)大模長(zhǎng)
-
向量之間的距離 ——Vector3.Disrtance() 向量 和向量之間相減 A - B
-
0向量——Vector.zero()
-
向量模長(zhǎng)——Vector3.magnitude() 相等于向量之間的距離
-
單位向量——Vector3.normalized()適用于物體移動(dòng)的時(shí)候的單位化計(jì)算
-
向量+向量 和向量+位置 的區(qū)別——前者為向量(高數(shù)中的向量相加)后者為相當(dāng)于擴(kuò)大作用結(jié)果是位置
-
位置-位置的幾何意義——結(jié)果為向量 ,向量-向量 = 向量
-
向量的加減乘除 —— 加減應(yīng)用于物體平移 乘除的進(jìn)行縮放要用本地坐標(biāo)
-
向量的點(diǎn)乘——Vector3.Dot 結(jié)果為余弦值,用來(lái)判斷對(duì)象的大概方位(前后)和夾角
-
向量的叉乘——Vector3.Dot 結(jié)果為法向量垂直于兩個(gè)向量構(gòu)成的平面,判斷(左右)
-
向量的線性差值運(yùn)算——直線軌跡
vector3.Lerp( S,E,T); ——S為開(kāi)始值,E為最終值
①每幀改變S的值(先快后慢)—適合攝像機(jī)的跟隨
②每幀改變T的值(勻速變化)—適合攝像機(jī)的跟隨
線性插值
//1.先快后慢 每幀改變start位置 位置無(wú)限接近 但不會(huì)得到end位置
transform.position = Vector3.Lerp(
transform.position,target.position, Time.deltaTime);
//2.勻速 每幀改變時(shí)間 當(dāng)t>=1時(shí) 得到結(jié)果
//當(dāng)time>=1時(shí) 改變了目標(biāo)位置后會(huì)直接瞬移到目標(biāo)位置
if(nowTarget != target.position)
{
nowTarget = target.position;
time = 0;
startPos = B.position;
}
time += Time.deltaTime;
B.position = Vector3.Lerp(startPos, nowTarget, time);
-
向量的球形差值運(yùn)算——弧形軌跡
vector3.SLerp( S,E,T); ——S為開(kāi)始值,E為最終值
對(duì)兩個(gè)向量進(jìn)行插值計(jì)算 t的取值范圍為0~1
球形插值
C.position = Vector3.Slerp(Vector3.right * 10, Vector3.left * 10 +
Vector3.up*0.1f, time*0.01f);
【Unity每日一記】向量操作攝像機(jī)的移動(dòng)(向量加減)
【Unity每日一記】關(guān)于物體(敵方)檢測(cè)—(向量點(diǎn)乘相關(guān))
【Unity每日一記】方位辨別—向量的叉乘點(diǎn)乘結(jié)合
??(E) 四元數(shù)
特點(diǎn)
1,繞著某個(gè)軸轉(zhuǎn)x度,軸可以是任意軸(軸-角對(duì))
2,避免了歐拉角中萬(wàn)向節(jié)死鎖的問(wèn)題
3,避免了歐拉角中角度變化不在(-180,180)范圍內(nèi)的問(wèn)題
- 四元數(shù)解決了歐拉角中萬(wàn)向節(jié)死鎖的問(wèn)題
- 當(dāng)Unity中transform的X軸為90度是發(fā)生萬(wàn)向節(jié)死鎖,此時(shí)不管移動(dòng)y軸還是z軸,物體都往X軸進(jìn)行旋轉(zhuǎn)
原理公式
假定四元數(shù)Q繞著n軸旋轉(zhuǎn)β度
//計(jì)算原理_繞x軸旋轉(zhuǎn)60度
Quaternion q = new Quaternion(Mathf.Sin(30 * Mathf.Deg2Rad),
0, 0, Mathf.Cos(30 * Mathf.Deg2Rad));
直接簡(jiǎn)單公式
- Quaternion.AngleAxis(角度數(shù)值,軸(向量))
//繞x軸旋轉(zhuǎn)60度
Quaternion q = Quaternion.AngleAxis(60, Vector3.right);
API常用
1.四元數(shù)和歐拉角轉(zhuǎn)換
-
歐拉角轉(zhuǎn)四元數(shù)
Quaternion A = Quaternion.Euler(60, 0, 0); -
四元數(shù)轉(zhuǎn)歐拉角
A.eulerAngles
2.旋轉(zhuǎn)
四元數(shù)相乘代表旋轉(zhuǎn)四元數(shù)
//四元數(shù)旋轉(zhuǎn)方法
transform.rotation *= Quaternion.AngleAxis(30,vector3.forword);
3.單位化四元數(shù)
- [1,(0,0,0)]和[-1,(0,0,0)]都是單位四元數(shù)
表示沒(méi)有旋轉(zhuǎn)量 - Quaternion.identity _用于對(duì)象角度初始化
Instantiate(XXXX, Vector3.zero, Quaternion.identity);
4.四元數(shù)的差值運(yùn)算
- 特點(diǎn): Lerp() 和Slerp();官方建議一般用Slerp();
- 先快后慢旋轉(zhuǎn)
transform.rotation = Quaternion.Slerp(transform.rotation,
target.rotation, Time.deltaTime);
- 勻速旋轉(zhuǎn)—— time>=1 到達(dá)目標(biāo)
time += Time.deltaTime;
B.transform.rotation = Quaternion.Slerp(start,
target.rotation, time);
5.四元數(shù)的旋轉(zhuǎn)看向——LookAt的本質(zhì)
Quaternion A = Quaternion.LookRotation(B.position - A.position);
//B - A = AB 向量 ,所以傳入的是向量
transform.rotation = A;
四元數(shù)和三維向量相乘
- 代表旋轉(zhuǎn)了也移動(dòng)了,最后返回的也是三維向量
//確定好角度,四元數(shù) * 三維向量 = 三維向量 和最終位置
lookPosition = Quaternion.AngleAxis(angle, target.right) * -target.forward;
【Unity每日一記】進(jìn)行發(fā)射,位置相關(guān)的方法總結(jié)
【Unity每日一記】攝像機(jī)相關(guān)向量代碼API大全
??(F) 延時(shí)函數(shù)
應(yīng)用于:方法活物體的延時(shí)執(zhí)行 和 計(jì)時(shí)器應(yīng)用
???????1.延時(shí)調(diào)用
● Invoke(“名字”,秒數(shù))
● InvokeRepeating(“名字”,第一次延時(shí)執(zhí)行的時(shí)間,之后每次調(diào)用間隔秒數(shù))
- 使用協(xié)程的延時(shí)調(diào)用也可以
- 使用計(jì)時(shí)器-MathF.MoveTowords也可以達(dá)到延時(shí)調(diào)用的效果
void Start()
{
//調(diào)用
//Invoke("CreateGris",3);
InvokeRepeating("CreateGris",1,1);
}
private void CreateGris()
{
Instantiate(grisGo); //實(shí)例化
}
???????2.取消調(diào)用
● CancelInvoke(“方法名”);暫停當(dāng)前延時(shí)調(diào)用該方法
● CancelInvoke();停止所有的延時(shí)調(diào)用方法
???????3.判斷是否調(diào)用
● IsInvoke(“方法名”);判斷當(dāng)前方法是否進(jìn)行了延時(shí)調(diào)用
● IsInvoke();停止程序中所有的延時(shí)調(diào)用
生命函數(shù)
-
原理:
腳本依附對(duì)象失活 或者 腳本自己失活 _ ——延遲函數(shù)可以繼續(xù)執(zhí)行
腳本依附對(duì)象銷(xiāo)毀或者腳本移除_——延遲函數(shù)無(wú)法繼續(xù)執(zhí)行
private void OnEnable()
{
//對(duì)象激活 的生命周期函數(shù)中 開(kāi)啟延遲(重復(fù)執(zhí)行的延遲)
}
private void OnDisable()
{
//對(duì)象失活 的生命周期函數(shù)中 停止延遲
}
??(G) Unity協(xié)程
Unity中的多線程
- Unity支持多線程,但是操作相關(guān)對(duì)象還得在主線程中實(shí)現(xiàn),要注意關(guān)閉線程最后
- 但是可以作為復(fù)雜算法或邏輯運(yùn)算計(jì)算的復(fù)線程,(線程是獨(dú)立運(yùn)行的管道)——專(zhuān)門(mén)用一個(gè)線程來(lái)做這些復(fù)雜的運(yùn)算
協(xié)程和多線程的區(qū)別
- 1.協(xié)程不是多線程,并且在繼承 Mononabehavar類(lèi)下使用
- 2.多線程是和主線程區(qū)分開(kāi)來(lái)的
- 3.協(xié)程是在主線程中運(yùn)行的,只是分時(shí)分布將邏輯進(jìn)行處理
協(xié)程主要作用
1.延時(shí)調(diào)用
IEnumerator ChangeState() //協(xié)程迭代器的定義
{
//暫停幾秒(協(xié)程掛起)
yield return new WaitForSeconds(2);
//暫停兩秒后再切入走路的動(dòng)畫(huà)
animator.Play("Walk");`
}
2.和其他邏輯一起協(xié)同執(zhí)行
,比如一些很耗時(shí)的工作,在這個(gè)協(xié)程中執(zhí)行異步操作,比如下載文件,加載文件,異步生成怪物等
*資源加載一般是一個(gè)比較耗時(shí)的操作,如果直接放在主線程中會(huì)導(dǎo)致游戲卡頓,通常會(huì)放到異步線程中去執(zhí)行。
3.分布分時(shí)執(zhí)行復(fù)雜算法或繁雜邏輯
比如創(chuàng)建隨機(jī)創(chuàng)建一萬(wàn)個(gè)球不卡幀
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));
}
}
協(xié)程的聲明
- 返回值為IEnumerator類(lèi)型及其子類(lèi)
- 函數(shù)中通過(guò) yield return 進(jìn)行返回
// MyCoroutine為自定義協(xié)程名
IEnumerator MyCoroutine(int i, string str)
{
//分時(shí)分布執(zhí)行。先打印i然后暫停1秒之后再打印3242
print(i);
yield return new WaitForSeconds(1f);
print("3242");
}
協(xié)程的開(kāi)啟和停止
-
開(kāi)啟
StartCoroutine(MyCoroutine(1, “123”)); -
關(guān)閉所有協(xié)程
StopAllCoroutines(); -
關(guān)閉指定協(xié)程
StopCoroutine(c1);
只有當(dāng)組件失活時(shí)協(xié)程不會(huì)失活,對(duì)象失活時(shí)協(xié)程也會(huì)失活
void start()
{
啟動(dòng)方法一 String:
StartCoroutine("ChangeState"); //括號(hào)內(nèi)的是協(xié)程名
啟動(dòng)方法二 函數(shù):
StartCoroutine(ChangeState());
啟動(dòng)方法三 接口: //有參協(xié)程只能用該方法開(kāi)啟
IEnumerator ie = ChangeState();
StartCoroutine(ie);
停止方法一 String:
StopCoroutine("ChangeState");
停止方法二 函數(shù):
StopCoroutine(ChangeState());
停止方法三 接口:
StopCoroutine(ie);
停止方法四 協(xié)程:
Coroutine c1 = StartCoroutine( ChangeState());
StopCoroutine(c1);
停止所有協(xié)程:
StopAllCoroutines();
}
-------------協(xié)程中的 yield------------
//1.下一幀執(zhí)行
yield return 數(shù)字;
yield return null;
//在Update和LateUpdate之間執(zhí)行
//表示在本幀幀末執(zhí)行以下邏輯
yield return new WaitForEndOfFrame();
//2.等待指定秒后執(zhí)行
yield return new WaitForSeconds(秒);
//在Update和LateUpdate之間執(zhí)行
//3.等待下一個(gè)固定物理幀更新時(shí)執(zhí)行
yield return new WaitForFixedUpdate();
//在FixedUpdate和碰撞檢測(cè)相關(guān)函數(shù)之后執(zhí)行
//4.等待攝像機(jī)和GUI渲染完成后執(zhí)行
yield return new WaitForEndOfFrame();
//在LateUpdate之后的渲染相關(guān)處理完畢后之后,截圖功能放在這個(gè)后面執(zhí)行
//5.一些特殊類(lèi)型的對(duì)象 異步加載相關(guān)函數(shù)返回的對(duì)象
//一般在Update和LateUpdate之間執(zhí)行
//6.跳出協(xié)程
yield break;
???????4.協(xié)程中的協(xié)程和有參協(xié)程
StartCoroutine("CreateBoss"); //啟動(dòng)協(xié)程
//協(xié)程1 功能實(shí)時(shí)實(shí)例化游戲物體
IEnumerator CreateBoss()
{
StartCoroutine(SetCreateCount(5));
while (true) //功能實(shí)時(shí)實(shí)例化游戲物體
{
if (BossNum>=BossCount)
{
yield break; //在協(xié)程中break前面要加 yield
}
Instantiate(animator.gameObject);
BossNum++;
yield return new WaitForSeconds(2);
}
}
//協(xié)程2 功能實(shí)時(shí)實(shí)例化游戲物體
IEnumerator SetCreateCount(int num)
{
BossCount =num;
yield return null; //暫停一幀
---------------------
此時(shí)如果這里只是暫停一幀的話,
那么上面調(diào)該有參協(xié)程的協(xié)程體中,
后面的語(yǔ)句并未生效,因?yàn)闀和R粠螅?后面的方法已經(jīng)執(zhí)行了,
所以此時(shí)的BossCount并不等于有參傳遞的5
(當(dāng)然BossCount是全局變量)
---------------------
}
協(xié)程的本質(zhì)
- 1.本體為迭代器
- 2.協(xié)程調(diào)度器(可自己實(shí)現(xiàn))
//Ieunmrator接口中的兩個(gè)成員:MoveNext_移動(dòng)下一個(gè) Current——當(dāng)前返回值
while(ie.MoveNext())
{
print(ie.Current);
}
??(H)特殊文件夾
- 特殊文件夾讀寫(xiě)性
1.Resources 可讀 不可寫(xiě) 打包后找不到
2.Application.streamingAssetsPath 可讀 PC端可寫(xiě) 找得到
3.Application.dataPath 打包后找不到
4.Application.persistentDataPath 可讀可寫(xiě)找得到
1.工程路徑獲取
該方式 獲取到的路徑 一般情況下 只在 編輯模式下使用
游戲發(fā)布過(guò)后 該路徑就不存在了
- Application.dataPath
2.Resources資源文件夾
一般不獲取路徑只能使用Resources相關(guān)API進(jìn)行加載
-
注意:
手動(dòng)創(chuàng)建 -
作用:
資源文件夾
1.需要通過(guò)Resources相關(guān)API動(dòng)態(tài)加載的資源需要放在其中
2.該文件夾下所有文件都會(huì)被打包出去
3.打包時(shí)Unity會(huì)對(duì)其壓縮加密
4.該文件夾打包后只讀 只能通過(guò)Resources相關(guān)API加載
3.StreamingAssets 流動(dòng)資源文件夾
- Application.streamingAssetsPath
-
注意:
手動(dòng)創(chuàng)建 -
作用:
流文件夾
1.打包出去不會(huì)被壓縮加密,可以任由我們擺布
2.移動(dòng)平臺(tái)只讀,PC平臺(tái)可讀可寫(xiě)
3.可以放入一些需要自定義動(dòng)態(tài)加載的初始資源
4.不愿意放在Resources中的資源可以放入StreamingAssets中
4.persistentDataPath 持久數(shù)據(jù)文件夾
-
注意:
不需要手動(dòng)創(chuàng)建 -
Application.persistentDataPath
不同平臺(tái)路徑不一樣 -
作用:
固定數(shù)據(jù)文件夾
1.所有平臺(tái)都可讀可寫(xiě)
2.一般用于放置動(dòng)態(tài)下載或者動(dòng)態(tài)創(chuàng)建的文件,游戲中創(chuàng)建或者獲取的文件都放在其中(熱更新會(huì)用到)
5.Plugins 插件文件夾
-
注意:
不需要手動(dòng)創(chuàng)建 -
作用:
插件文件夾
不同平臺(tái)的插件相關(guān)文件放在其中
比如IOS和Android平臺(tái)
6. Editor 編輯器文件夾
-
注意:
手動(dòng)創(chuàng)建 -
作用:
編輯器文件夾
1.開(kāi)發(fā)Unity編輯器時(shí),編輯器相關(guān)腳本放在該文件夾中
2.文件夾中內(nèi)容不會(huì)被打包出去
7. 默認(rèn)資源文件夾 Standard Assets
-
注意:
手動(dòng)創(chuàng)建 -
作用:
默認(rèn)資源文件夾
一般Unity自帶資源都放在這個(gè)文件夾下
代碼和資源優(yōu)先被編譯 -
一般不用
??(K)Resources資源動(dòng)態(tài)加載
###同步加載**———————
5種資源加載的方式,Resource加載介紹
- Resources(只能加載Resources目錄中的資源)
- AssetBundle(只能加載AB資源,當(dāng)前設(shè)備允許訪問(wèn)的路徑都可以)
- WWW(可以加載任意處資源,包括項(xiàng)目外資源(如遠(yuǎn)程服務(wù)器))
- AssetDatabase(只能加載Assets目錄下的資源,但只能用于Editor)
- UnityWebRequest(可以加載任意處資源,是WWW的升級(jí)版本)
資源加載適用于需要加載資源較多的 情況就不用一個(gè)一個(gè)的拖拽進(jìn)去
關(guān)鍵字:@ ,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#中的回收機(jī)制是系統(tǒng)自動(dòng)回收的,有多種回收機(jī)制,不像其他語(yǔ)言需要手動(dòng)回收
注意:
//預(yù)設(shè)體對(duì)象加載需要實(shí)例化
//其它資源加載一般直接用
#endregion
Resource資源加載操作
加載資源前首先需要在project面板中創(chuàng)建Resource名字的文件夾,為固定文件夾用于資源加載
以加載AudioClip類(lèi)型的資源為例:
- 根目錄加載 Resource.Load< AudioClip>(“voice”);
- 子目錄加載 Resource.Load ( @ " 子目錄名/ voice") ;
- 另一種形式:
Object xx = Resource.Load(“voice”);
AudioClip yy as xx ; // 顯性類(lèi)型轉(zhuǎn)換 ,前提是二者兼容 - 加載同類(lèi)型所有資源的方法:
①根目錄加載: AudioClip [] xx = Resource.AllLoad(" “) ;
②子目錄加載:AudioClip [] yy = Resource.AllLoad(” 子目錄名");
- 1.預(yù)設(shè)體對(duì)象
Object obj = Resources.Load("Cube");
Instantiate(obj);
- 2.音效資源
Object obj3 = Resources.Load("Music/BKMusic");
//我們不需要實(shí)例化 音效切片 我們只需要把數(shù)據(jù) 賦值到正確的腳本上即可
audioS.clip = obj3 as AudioClip;
audioS.Play();
- 3.文本資源
文本資源支持的格式——.txt .xml .bytes .json .html .csv …
TextAsset ta = Resources.Load("Txt/Test") as TextAsset;
//文本內(nèi)容
ta.text
//字節(jié)數(shù)據(jù)組
ta.bytes);
- 4.圖片
tex = Resources.Load("Tex/TestJPG") as Texture;
——————— 異步加載———————
如果我們加載過(guò)大的資源可能會(huì)造成程序卡頓
異步加載 就是內(nèi)部新開(kāi)一個(gè)線程進(jìn)行資源加載 不會(huì)造成主線程卡頓
- Resources.LoadAsync(“XXX”);
- 注意:
異步加載 不能馬上得到加載的資源 至少要等待一幀
直接異步加載——適用于加載單個(gè)資源
//通過(guò)事件監(jiān)聽(tīng)
ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG")
rq.completed += LoadOver;
//completed 是 ResourceRequest 中的委托
// AsyncOperation 是 ResourceRequest 的父類(lèi)
private void LoadOver( AsyncOperation rq)
{
//在事件中添加結(jié)束標(biāo)識(shí)邏輯,這樣我們就知道異步加載完成了
print("加載結(jié)束");
//加載完成后 會(huì)保存在 ResourceRequest類(lèi)中的 asset Object類(lèi)型成員里
//此時(shí)實(shí)現(xiàn)賦值
picture = (rq as ResourceRequest).asset as Texture;
}
配套協(xié)程異步加載——適用于加載多個(gè)資源
//通過(guò)協(xié)程的調(diào)度器自己判斷是否加載結(jié)束
StartCoroutine(Load());
IEnumerator Load()
{
ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG");
yield return rq;
// yield return rq會(huì)自己判斷 該資源是否加載完畢了,加載完畢過(guò)后才繼續(xù)執(zhí)行后面的代碼 ,因?yàn)镽esourceRequest 也是YieldInstruction的子類(lèi)
//-------------------------------
//isDone 和 progress API的應(yīng)用
while(!rq.isDone)
{
//打印當(dāng)前的 加載進(jìn)度
print(rq.progress);
yield return null;
}
//--------------------------------
picture = rq.asset as Texture;
}
———————資源加載器———————
利用異步直接加載和委托的使用構(gòu)成簡(jiǎn)單的資源加載器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
//-------------------------------------
//—————————————————————————————————————
//___________項(xiàng)目: ______________
//___________功能: 簡(jiǎn)單的資源管理器
//___________創(chuàng)建者:秩沅_______________
//_____________________________________
//-------------------------------------
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 );
};
}
}
//外部調(diào)用
private void Start()
{
GameObject shootball;
ResourcesControl.Control.AddResources<GameObject>("Profabs/ball",(sphere)=> {
shootball = sphere;
} );
}
———————卸載資源———————
-
Resources多次重復(fù)加載不會(huì)浪費(fèi)內(nèi)存
但是 會(huì)浪費(fèi)性能(每次加載都會(huì)去查找取出,始終伴隨一些性能消耗) -
1.卸載指定資源
Resources.UnloadAsset 方法
注意:它只能用于一些 不需要實(shí)例化的內(nèi)容 比如 圖片 和 音效 文本等 一般情況下很少單獨(dú)使用它
-
2.卸載未使用的資源
一般在過(guò)場(chǎng)景時(shí)和GC一起使用
Resources.UnloadUnusedAssets();
GC.Collect();
??(L)SceneManager場(chǎng)景資源動(dòng)態(tài)加載
???????加載場(chǎng)景的方法
- SceneManager.LoadScene() ; 場(chǎng)景同步加載
- SceneManager.LoadSceneSAsyn(); 場(chǎng)景異步加載
- SceneManage。GetActiveScene().name判斷當(dāng)前場(chǎng)景
- Application.LoadLevel():同步加載
- Application.LoadLevelAsync():異步加載
- Application.LoadLevelAddictive():同步附加式加載
- Application.LoadLevelAddictiveAsync():異步附加式加載
???????SceneManasger的操作
首先添加場(chǎng)景加載的命名空間Using UnityEngine.SceneManagement ;
而后把游戲場(chǎng)景都保存(拖拽)在 Buid setting 里面,相當(dāng)于存儲(chǔ)場(chǎng)景的目錄
??1.同步加載
SceneManager.Load( 序列號(hào)) ;
SceneManager.Load( “場(chǎng)景名”) ;
void Start()
{
//SceneManager.LoadScene(1);
//SceneManager.LoadScene("TriggerTest");
}
缺點(diǎn):加載時(shí)造成畫(huà)面卡幀,因?yàn)椋谖醇虞d完成前畫(huà)面是停止的,所以是卡幀現(xiàn)象
??2.異步加載
如果當(dāng)前場(chǎng)景 對(duì)象過(guò)多或者下一個(gè)場(chǎng)景對(duì)象過(guò)多
這個(gè)過(guò)程會(huì)非常的耗時(shí) 會(huì)讓玩家感受到卡頓
所以異步切換就是來(lái)解決該問(wèn)題的
通常我們和協(xié)程一起使用:
-
SceneManager.LoadAsync(序列號(hào))
-
SceneManager.LoadAsync(“場(chǎng)景名”)
-
StartCoroutine(協(xié)程迭代器方法() ); //調(diào)用協(xié)程
-
AsyncOperation 該類(lèi)型翻譯為異步操作 ,為下面獲得異步場(chǎng)景的返回值
AsyncOperation ao= SceneManager.LoadSceneAsync(2); -
ao.allowSceneActivation = true 激活場(chǎng)景
-
ao.progress 場(chǎng)景加載的進(jìn)度
//-----1.通過(guò)事件回調(diào)函數(shù) 異步加載------
AsyncOperation SS = SceneManager.LoadSceneAsync("XXXX");
SS.completed += (a) =>
{
print("加載結(jié)束");
};
SS.completed += LoadOver;
private void LoadOver(AsyncOperation ao)
{
print("LoadOver");
}
//---------2.通過(guò)協(xié)程異步加載--------
void Start()
{
//由于場(chǎng)景加載后就不會(huì)執(zhí)行加載后的邏輯了,如果要保存就使用 DontDestroyOnLoad(保留場(chǎng)景加載上個(gè)場(chǎng)景的東西)第一個(gè)異步方法不會(huì)出現(xiàn)該情況
DontDestroyOnLoad(this.gameObject);
StartCoroutine(LoadScene("XXXX"));
}
IEnumerator LoadScene(string name)
{
AsyncOperation SS= SceneManager.LoadSceneAsync(name);
//根據(jù)游戲規(guī)則 自定義進(jìn)度條變化的條件
yield return SS;
//1.場(chǎng)景加載結(jié)束 更新20%
//2.動(dòng)態(tài)加載怪物再更新20%
//3.動(dòng)態(tài)加載場(chǎng)景模型進(jìn)度條頂滿
//4.加載結(jié)束隱藏進(jìn)度條
}
總結(jié)
場(chǎng)景異步加載 和 資源異步加載 一樣
1.通過(guò)事件回調(diào)函數(shù)
2.協(xié)程異步加載
-
1.事件回調(diào)函數(shù)
優(yōu)點(diǎn):寫(xiě)法簡(jiǎn)單,邏輯清晰
缺點(diǎn):只能加載完場(chǎng)景做一些事情 不能在加載過(guò)程中處理邏輯 -
2.協(xié)程異步加載
優(yōu)點(diǎn):可以在加載過(guò)程中處理邏輯,比如進(jìn)度條更新等
缺點(diǎn):寫(xiě)法較為麻煩,要通過(guò)協(xié)程
場(chǎng)景管理器
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提供的一個(gè)用于畫(huà)線的組件來(lái)在場(chǎng)景中繪制線段
一般可以用于
- 繪制攻擊范圍
- 武器紅外線
- 輔助功能其它畫(huà)線功能
2.LineRenderer相關(guān)API
-
代碼動(dòng)態(tài)添加一個(gè)線段
GameObject line = new GameObject(); line.name = "Line"; LineRenderer lineRenderer = line.AddComponent<LineRenderer>();
-
首尾相連
lineRenderer.loop = true; -
開(kāi)始結(jié)束寬
lineRenderer.startWidth = 0.02f;
lineRenderer.endWidth = 0.02f; -
開(kāi)始結(jié)束顏色
-
lineRenderer.startColor = Color.white; lineRenderer.endColor = Color.red;
-
設(shè)置材質(zhì)
m = Resources.Load<Material>("XXX");
lineRenderer.material = m;
-
設(shè)置點(diǎn)
先設(shè)置點(diǎn)的個(gè)數(shù)
—— lineRenderer.positionCount = 4;
設(shè)置 對(duì)應(yīng)每個(gè)點(diǎn)的位置
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));
-
是否使用世界坐標(biāo)系
//決定了 是否隨對(duì)象移動(dòng)而移動(dòng) lineRenderer.useWorldSpace = false;
-
讓線段受光影響 會(huì)接受光數(shù)據(jù) 進(jìn)行著色器計(jì)算
lineRenderer.generateLightingData = true;
??(N)手動(dòng)范圍檢測(cè)
特點(diǎn):
- 1.執(zhí)行該句代碼時(shí) 進(jìn)行一次范圍檢測(cè) 它是瞬時(shí)的
- 2.范圍檢測(cè)相關(guān)API 并不會(huì)真正產(chǎn)生一個(gè)碰撞器 只是碰撞判斷計(jì)算而已
共同參數(shù):
- 參數(shù)一:物體中心點(diǎn)
- 參數(shù)二:物體的邊長(zhǎng)大小
- 參數(shù)三:物體的角度
- 參數(shù)四:檢測(cè)指定層級(jí)(不填檢測(cè)所有層)
- 參數(shù)五:是否忽略觸發(fā)器 UseGlobal-使用全局設(shè)置 Collide-檢測(cè)觸發(fā)器 Ignore-忽略觸發(fā)器 (不填使用UseGlobal)
- 返回值:在該范圍內(nèi)的觸發(fā)器(得到了對(duì)象觸發(fā)器就可以得到對(duì)象的所有信息)
UseGlobal-使用全局設(shè)置在該界面中已默認(rèn)
1.方塊狀范圍檢測(cè)
- Physics.OverlapBox ——返回值為數(shù)組,存儲(chǔ)檢測(cè)到的碰撞器
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 表示檢測(cè)的數(shù)量(最多6個(gè)參數(shù))
if(Physics.OverlapBoxNonAlloc(Vector3.zero, Vector3.one, 自定義數(shù)組名) != 0)
2.球形狀范圍檢測(cè)
無(wú)角度參數(shù)
參數(shù)二為球半徑
- Physics.OverlapSphere
colliders = Physics.OverlapSphere(Vector3.zero, 5, 1 << LayerMask.NameToLayer("Default"));
- Physics.OverlapSphereNonAlloc——同BOX
if( Physics.OverlapSphereNonAlloc(Vector3.zero, 5, colliders) != 0 )
.3.膠囊體范圍檢測(cè)
參數(shù)一:半圓一中心點(diǎn)
參數(shù)二:半圓二中心點(diǎn)
參數(shù)三:半圓半徑
- 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射線檢測(cè)
-
特點(diǎn)
只需要判斷一條線和物體的碰撞情況
可以在指定點(diǎn)發(fā)射一個(gè)指定方向的射線
判斷該射線與哪些碰撞器相交,得到對(duì)應(yīng)對(duì)象
瞬時(shí) -
應(yīng)用場(chǎng)景
1.鼠標(biāo)選擇場(chǎng)景上一物體
2.FPS射擊游戲(無(wú)彈道-不產(chǎn)生實(shí)際的子彈對(duì)象進(jìn)行移動(dòng))等
API
- Ray X = new Ray(Vector3.right, Vector3.forward);
參數(shù)一 | 參數(shù)二 |
---|---|
起點(diǎn) | 方向 |
X.origin | X.direction |
-
Ray XX = Camera.main.ScreenPointToRay(Input.mousePosition);
屏幕視口坐標(biāo)轉(zhuǎn)成射線——鼠標(biāo)點(diǎn)擊的地方變成射線 -
Physics.Raycast 無(wú)法檢測(cè)碰到了誰(shuí),只會(huì)檢測(cè)碰到了沒(méi)有
最多有16個(gè)重載
Physics.Raycast常用參數(shù) | 作用 |
---|---|
參數(shù)一 | 射線 |
參數(shù)二 | 檢測(cè)的最大距離 超出這個(gè)距離不檢測(cè) |
參數(shù)三 | 檢測(cè)指定層級(jí)(不填檢測(cè)所有層) |
參數(shù)四 | 是否忽略觸發(fā)器 UseGlobal-使用全局設(shè)置 Collide-檢測(cè)觸發(fā)器 Ignore-忽略觸發(fā)器 不填使用UseGlobal |
返回值 | bool 當(dāng)碰撞到對(duì)象時(shí) 返回 true 沒(méi)有 返回false |
//第一種寫(xiě)法
Physics.Raycast(XX, 1000,
1 << LayerMask.NameToLayer("層級(jí)名字"),
QueryTriggerInteraction.UseGlobal )
//第二種寫(xiě)法
Physics.Raycast(Vector3.right, Vector3.forward,
1 << LayerMask.NameToLayer("層級(jí)名字"),
QueryTriggerInteraction.UseGlobal )
-
RaycastHit 物體信息類(lèi)——得到相交的單個(gè)物體物理信息
RaycastHit 在Physics.Raycast的應(yīng)用 | 作用 |
---|---|
參數(shù)一 | 射線 |
參數(shù)二 | out RaycastHit 為什么是out ?RaycastHit是結(jié)構(gòu)體 是值類(lèi)型 out加上去就變成了引用類(lèi)型,而RaycastHit沒(méi)有復(fù)制所以不用ref |
參數(shù)三 | 檢測(cè)的最大距離 超出這個(gè)距離不檢測(cè) |
參數(shù)四 | 檢測(cè)指定層級(jí)(不填檢測(cè)所有層) |
參數(shù)五 | 是否忽略觸發(fā)器 UseGlobal-使用全局設(shè)置 Collide-檢測(cè)觸發(fā)器 Ignore-忽略觸發(fā)器 不填使用UseGlobal |
返回值 | bool 當(dāng)碰撞到對(duì)象時(shí) 返回 true 沒(méi)有 返回false |
//寫(xiě)法一
RaycastHit YY;
if( Physics.Raycast(XX, out YY, 1000,
1<<LayerMask.NameToLayer("層級(jí)名字"),
QueryTriggerInteraction.UseGlobal) )
//寫(xiě)法二
if( Physics.Raycast(Vector3.right, Vector3.forward, out YY, 1000,
1<<LayerMask.NameToLayer("層級(jí)名字"),
QueryTriggerInteraction.UseGlobal) )
- 碰撞到物體的名字 YY.collider.gameObject.name;
- 碰撞到的點(diǎn) YY.point
- 法線信息 YY.normal
- 碰撞到對(duì)象的位置 YY.transform.position
- 碰撞到對(duì)象 離自己的距離 YY.distance等等
- RaycastHit[] XX= Physics.RaycastAll——得到相交的多個(gè)物體物理信息
特點(diǎn): 先碰到的在數(shù)組的后面
- Physics.RaycastNonAlloc——返回的碰撞的數(shù)量 通過(guò)out得到數(shù)據(jù)
if((r3, XX, 1000, 1 << LayerMask.NameToLayer("Monster"),
QueryTriggerInteraction.UseGlobal) > 0 )
{
}
【Unity每日一記】模仿FPS射擊,用彈痕作畫(huà)的原理如此簡(jiǎn)單
【Unity每日一記】拖拽放置類(lèi)游戲的行為原來(lái)和這個(gè)API有關(guān)
?????
?【Unityc#專(zhuān)題篇】之c#進(jìn)階篇】
?【Unityc#專(zhuān)題篇】之c#核心篇】
?【Unityc#專(zhuān)題篇】之c#基礎(chǔ)篇】
?【Unity-c#專(zhuān)題篇】之c#入門(mén)篇】
?【Unityc#專(zhuān)題篇】—進(jìn)階章題單實(shí)踐練習(xí)
?【Unityc#專(zhuān)題篇】—基礎(chǔ)章題單實(shí)踐練習(xí)
?【Unityc#專(zhuān)題篇】—核心章題單實(shí)踐練習(xí)
你們的點(diǎn)贊?? 收藏? 留言?? 關(guān)注?是我持續(xù)創(chuàng)作,輸出優(yōu)質(zhì)內(nèi)容的最大動(dòng)力!、文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-703622.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-703622.html
到了這里,關(guān)于【Unity自制手冊(cè)】游戲基礎(chǔ)API大全的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!