unity-1

創建游戲對象(游戲物體)

可通過unity中的菜單欄中的Gameobject創建;也可在Hierarchy(層級)中創建,

雙擊即可居中看到。

在Hierarchy空白處右鍵即可看到,能創建游戲對象。

在Scene框中,鼠標坐標選擇物體;右鍵 旋轉視角;

坐標系

?unity是以左手坐標系。

世界坐標系:類似地球的經緯度,你在場景中創建一個物體,都要有一個坐標原點把?以此確定相對位置,即(0,0,0)。

可創建一個物體,修改其坐標為(0,0,0) 。?

在Hierarchy(層級)欄中,可拖拽一個物體到另一個物體中,使其形成父子關系。

有個小三角,表示其含有父子關系。
在具有父子關系的物體中,移動子物體的位置不會影響父物體的位置;但是,若移動父物體的位置,則子物體跟著移動,以使得父子的相對位置不變。

通過右側inspector欄修改子物體的X,Y,Z坐標之后,無論怎么移動父物體(子物體會跟著移動),但是子物體的position的X,Y,Z坐標大小不會變化, 即這個X,Y,Z表示的是相對位置(而不是世界坐標系的位置)。? 這里X,Y,Z的相對位置,代表該物體相對于其父物體的位置。

其實,就是當 某個物體 沒有 父物體 時,其X,Y,Z就是相對于世界坐標系的;
? ? ? ? ? ? ? ? ??當 某個物體 有? ? ?父物體 時,其X,Y,Z就是相對于父物體的。

全局坐標軸示意圖

左上角圈中的地方,可將坐標軸修改為:全局、局部。

全局就是點擊物體時顯示的坐標軸 同? 右上角 世界的坐標軸 方向。?
局部就是點擊物體時顯示的坐標軸 會以物體為中心顯示, 大概率與世界坐標軸方向不同。

局部坐標軸示意圖

物體的基本操作

上圖中,可看到三根軸,顏色及方向? 與 右上角的世界坐標系 一樣,
另外,還有三個面,且帶有顏色,? 紅色的軸(X軸)與 紅色的面垂直,鼠標坐標點住紅色的面進行拖拽的話, 物體對應紅色軸的坐標是不變的, 只有另外兩個方向的坐標會變。

旋轉工具

可以看到,在左側菜單欄中點擊旋轉工具后,? 物體旁出現三根弧線,又是與坐標軸對應的紅藍綠。? 鼠標左鍵點擊紅色的弧線轉, 就是繞著x軸旋轉

縮放工具

拖拽紅色的軸, 就是沿著x軸縮放;? ? 點擊灰色的那個小立方體,就是整體縮放(三個方向同時縮放)

矩形工具

一般矩形工具? 在 2D、UI中使用,使物體沿著某個平面縮放。

Transform tool

其實就是個綜合工具,看圖,同時顯示 沿軸移動,沿軸縮放,沿軸旋轉的工具,減少切換工具的時間。

編輯碰撞器

就是圖中黃色的框框, 可以拖拽放大。按照這名字,我不確定是不是用在碰撞檢測上, 就像:游戲中 一個角色攻擊了另一個角色, 怎么判斷是否攻擊到呢? 就用這個?

最后,左側工具欄的快捷鍵是 QWERTY.

導入游戲模塊

可在項目project欄中,右鍵 :show in explorer? 。進而顯示出左側這個文件夾。
在該文件夾下創建文件或刪除文件? 等同于? 在項目欄中創建文件或刪除文件

需要導入文件/模塊時, 可拖拽到? 項目欄(project)中 Assets文件夾下, 也可拖拽到 上圖左邊那個資源文件夾下。 效果一樣。

將自身所作的內容導出成包

導出包

在project欄中,? 選中自己要導出的內容,右鍵 Export package , 再確認要選的內容導出即可。

正常來講,這個立方體其實就是那些三角形的線,? 我們怎么看到它這白色的面, 是軟件給我們渲染的, 即上圖右下角的材質球,(灰色那些,說明不能修改它這個材質球,但是可創建新的材質球)

材質創建

在project欄中,右鍵--》create--》Material? ? ? ? ?即可創建材質。

將材質拖拽到物體上,即應用材質。

資源商店

資源商店

在Window欄中,Asset Store 就是資源商店,打開再open online

資源有付費的也有免費的。

另外,想加載自己已經添加的資源的話,

可點擊 window--》Package Manager?

便會出現包管理器

包管理器

再如上圖點擊My Assets , 便可看到自己擁有的資源,? 右上角有搜索🔍,能利用關鍵字搜索自身的資源。

腳本組件

? ? ? ? 一個物體,可能具有 特效、重力、碰撞等等,每個物體都會有其特定的功能,而其實很多功能是很基礎的,每個物體都有的,即功能具有重復性。? ? ? ? ? ?不可能每一個物體的每一個功能都寫一段代碼,重復多次寫。于是就有了腳本組件。

選中要添加腳本組件的物體,在檢查器inspector中,下方有個 添加組件add component

如果已有的組件中不存在所要的功能,那就得編寫腳本。

空物體也是物體,雖然剛創建空物體時,它像是透明的,但它也有Transform組件,表示它的位置,旋轉角度,比例。? ?每一個創建的物體都有Transform。

其實每一個物體都是由一個空物體得來,只是在上面增加組件使其具有我們想要的形態罷了。

燈光物體 可以 由一個空物體賦予燈光組件light形成。

攝影機 可以由一個空物體賦予攝影機組件camera形成。

不同物體的表現形態不同都是因為組件。。

創建不存在的組件: 在project欄中空白處,右鍵creat - - C# Script 就是了。

創建組件也就是通過C#文件創建。

創建時需要注意:腳本名字和腳本內部的類名必須相同。(有時候可能改了腳本名,忘記改類名)

腳本的生命周期

? ? ? ? 除Start、Update兩個方法外,還有其他生命周期方法。如圖

周期方法


物體的腳本組件,那個小勾是勾上的,則組件是激活狀態(一開始默認勾上)

OnEnable在組件每次激活時都會執行一次,當取消勾選后再次勾選,也會執行。
取消勾選后,即取消激活組件,OnDisable執行一次。

Update是每一幀都會執行一次。(平時打游戲說的幀)

Update 、 LateUpdate都是與幀相關的

FixUpdate與幀無關,它是與時間相關,每隔固定時間間隔就會執行一次。

幀與電腦性能相關。假如電腦只能跑30幀,那么Update 、 LateUpdate每秒執行30次,若電腦能跑200幀,就能每秒執行200次;而FixUpdate,若間隔0.05秒執行一次,那無論你電腦能跑多少幀,其每秒都會執行20次。

OnDestroy,只有物體移除該組件時,才會執行。

腳本的執行順序

? ? ? ? 當一個游戲物體身上有多個腳本時,先執行哪個腳本?

游戲物體? 不是? 執行完一個腳本的Awake、Start、Update,再去執行另一個腳本的Awake、Start、Update。

而是 執行所有腳本的Awake,再執行所有腳本的Start......

控制順序:第一種方法-------例如兩個腳本t1,t2;想讓t2先輸出某些內容,就把內容放在t2的Awake方法中,t1的Awake方法不放東西。

顯然,第一種方法不好。

第二種方法--------

也可點擊腳本后,其右上角有個 執行順序(execution order)

點擊即可打開。

?修改腳本執行順序

通過那個 “+” 號按鈕,點擊添加所要控制的腳本進去。
注意:從上到下,負數到正數, 可以把它當作一個x軸,上面是負半軸。 執行順序是從上面到下面,即數值越小的越先執行。

(可修改數值,也可拖拽移動上下相對位置。)

別忘了 Apply 應用確定順序。

按上圖的順序:執行順序:t1的Awake、t2的Awake、t1的Start、t2的Start、t1的Update、t2的Update..................

做游戲就是,框架最底層的東西肯定要先初始化,所以其腳本應靠近上方。

游戲物體標記

? ? ? ? 當游戲場景中有多個游戲物體時,可能為了分類,更好查找管理,而給它們打上標簽。也方便我們下次點擊該物體時,通過標簽查看其是什么。例如:一類物體是“玩家”,一類是“NPC",一類是”boss“。

在inspector檢查器處,Tag標簽,點擊Add Tag可增加標簽, 并可任意自定義標簽名。
點擊物體后,在Tag處選擇標簽給物體加上標簽。

圖層Layer也可增加,但是給定只有32個,且個別已經被固定使用。?
圖層可用于碰撞檢測。--這個圖層的物體可被碰撞,那個圖層...
Culling Mask(剔除遮罩),選擇哪些圖層可以被攝像機看到。

游戲中幾個物體都設為kk圖層,當在Culling Mask這里把? kk 的勾取消勾選,攝像機就看不到 kk圖層的物體。 如下圖所示:

游戲中的向量

向量的運算和意義

? ? ? ? 向量的加減法法則,乘法,點乘運算。

加法法則:平行四邊形法則

減法法則:類似

乘法:向量*標量------------方向不變,大小縮放。

點乘:關鍵是能通過這樣獲取兩向量之間的夾角

利用歸一化,把兩個向量轉化為單位向量,再代入上式中,兩個向量的模就是1,等式右邊就只有cos。 很快計算出夾角。

預制體與變體

? ? ? ? 預制體其實就是做了一個游戲物體以后,把它身上所有組件合成一個整體,作為模板使用。 當下次要制作與預制體相似的游戲物體時,可通過預制體模板,先獲得一個基礎物體(由預制體創建),再進行修改。

對于變體,其是預制體的變體,可通過一個預制體創建一個實體后,把這個實體又做成模板(預制體) ,那就是兩個相同的預制體了,但它兩是獨立的, 修改舊預制體的屬性值等,不會影響新預制體的屬性值, 但是我們又想她兩是關聯的,
則要在把舊預制體做成新預制體時,選擇做成變體。??
變體的話, 修改舊預制體的屬性值等,會相應地修改變體的屬性值。

創建預制體

通過父子關系形成整體后,把父體從Hierarchy拖拽到Project處,就會在Project處形成預制體,還會有那個藍色的圖標。

預制體在Assets文件夾下是有文件的。

可將預制體導出成包,給他人使用。

改變預制體的屬性值,會相應地改變通過預制體創建的實例。
但是改變實例的值,不會影響預制體。

(其實就是模板與具體實例的關系。修改模板,那么通過模板創建的實例也會改變,但是你僅僅修改實例,不會影響到實例對應的模板)

修改模板的值會影響對應的具體實例

預制體創建的具體實例添加的組件,而預制體沒有的組件,點擊實例時,該組件會有個 “+” 。

可通過組件右邊的 三點 按鈕,----Add component ---apply to prefab 應用到 對應的預制件上

這樣的話,模板也有該組件了,當模板也有該組件后, 組件的“+”號就消失了。

在實例中,有兩個組件是 對應的預制件沒有的。?
可以像上面一樣將這兩個組件應用到預制件中;
不過有多個組件時,一個一個應用添加太慢,
在上面的Prefab欄 對應的? override(覆蓋)欄中, 點擊 Apply All 將所有未添加的組件應用到預制件。

有時候一個預制體,需針對其修改個別點, 讓其變成新的 預制體,

我們當然可以通過預制體創建一個實例, 再修改實例成新模板的樣子, 將其從Hierarchy欄中拖拽到Project欄中, 建立為一個新的預制體, 這樣就是兩個預制體了,且它兩形近。

這種做法的缺點:兩個預制體互相獨立,對應的實例也是獨立的, 修改1號預制體會影響其對應的實例,不會影響2號預制體對應的;同理,修改2號也是如此。

可有時,我又想,2號預制體是從1號中衍生的,能不能修改1號模板,進而影響到1號、2號對應的實例呢?-------------------變體

用1號預制體的實例創建新模板時,選擇其作為 預制體變體(Prefab Variant)?

圖標會些許不一樣

注意:? 此時,變體模板是依賴于 原始預制體的。 兩者并沒有互相獨立, 修改原始預制體的值會影響預制體變體,? 即同時改變兩類實例;? 但是, 修改變體的屬性值 不會影響原始預制體對應的實例。

????????

vector3的使用

? ? ? ? 在使用c#腳本對unity進行編程時,vector3可以代表什么?

1.代表向量

2.代表坐標
? ? ? ? 同上圖,顯然也能作為坐標使用。

3.代表 旋轉

4.代表縮放

x,y不要動,z變為0.5倍

遇到vector的時候,就可考慮是以上幾種,判斷具體是哪一種。

通過vector3.zero初始化可以獲得一個(0,0,0)的向量。

通過vector3.one初始化可以獲得一個(1,1,1)的向量。

通過vector3.forward初始化可以獲得一個(0,0,1)的向量。

通過vector3.back初始化可以獲得一個(0,0,-1)的向量。

通過vector3.left初始化可以獲得一個(-1,0,0)的向量。

通過vector3.right初始化可以獲得一個(1,0,0)的向量。

通過vector3.up初始化可以獲得一個(0,1,0)的向量

通過vector3.down初始化可以獲得一個(0,-1,0)的向量

vector3(左右,上下,前后)

使用Vector3.Angle(a,b)計算兩向量a,b之間的夾角。

使用Vector3.Distance(a,b)計算兩點a,b之間的距離。

計算向量的點乘,叉乘。

使用Vector3.Lerp()在兩向量之間進行插值,得到一個向量.

規范化就是變為單位向量

方向的描述

? ? ? ? 可用歐拉角、四元數描述方向。

new Vector3(0,30,0) 表示沿著y軸旋轉30°,x,z方向不動。

Quaternion是四元數, 可以用new來創建,用new需要給定四個數;

用Quaternion.identity初始化的話,就是所有方向都不動。

可以將歐拉角轉化為四元數,即用一個歐拉角初始化為四元數

以通過看向一個物體(向量)來獲取角度。

Debug

? ? ? ? Debug.Log("正常輸出信息")
? ? ? ? Debug.LogWarning("輸出的警告信息")
????????Debug.LogError("報錯信息")

? ? ? ? 使用Debug繪制一條線

? ? ? ? Debug.DrawLine(起點,終點,Color.顏色英文)

????????Debug.DrawLine(Vector3.zero,Vector3.one,Color.red)

? ? ? ? 使用Debug繪制一條射線

? ? ? ? Debug.DrawRay(射線起點,射線方向,顏色)

????????

起點可以用三維坐標表示,方向也可以是三維坐標表示。

上面Vector3.zero, Vector3.up 雖然都是使用的Vector3,但是它們含義各不相同,一個代表點,一個代表方向

物體類的使用

? ? ? ? 在游戲場景的物體中,都掛載了腳本,如何在腳本當中,獲取到掛載了該腳本的物體?

#獲取當前腳本所掛載的物體
GameObject go = this.gameObject;
Debug.Log(go.name);

甚至this都可以省略,直接用gameObject就能得到游戲物體。

Debug.Log(gameObject.name)
#輸出游戲物體名稱
Debug.Log(gameObject.name);#輸出游戲物體的標簽
Debug.Log(gameObject.tag);#輸出游戲物體的圖層
Debug.Log(gameObject.layer);

注意:輸出圖層是輸出該圖層對應的索引值,而不是圖層名字。

這個球體已經添加上了名為test的腳本,如何通過球體掛載的這個腳本控制另外一個立方體呢

首先,在test腳本中創建public GameObject cube;變量,注意,這里還未初始化。

接著,在unity中,點擊掛載了test腳本的球體,查看inspector檢查器中的腳本

可以看到,腳本中顯示,Cube還沒有對應的游戲物體GameObject

即腳本test中創建的public GameObject cube變量還未初始化,

在unity中進行初始化

將Hierarchy中的Cube游戲物體拖拽到檢查器inspector的Sphere的test腳本下方的cube中。

另外一種初始化方式:

在inspector欄中sphere物體中點擊上圖那個小圓圈,就會出現下圖的窗口,選擇cube即可。

注意:創建的public GameObject cube變量,最后在unity中選擇物體時,一定要選擇cube物體,否則可能出錯。

同時,注意到,腳本代碼中的public GameObject cube變量 不是在C#中用代碼初始化,而是在unity中初始化

通過上述方式,就可以在一個物體里寫腳本,再通過這個腳本操作另外一個物體

----------------------------------------------------------------------------------------------------------

有如下圖的游戲物體父子關系

現將GameObject物體取消激活

把原來的勾取消掉就是取消激活

會看到下圖中,GameObject的子物體顯示也是灰色的(即使Cube本身是激活的)

此時的狀態下,在腳本當中coding上述代碼,在unity運行,會得到
? ? ? ? False;
? ? ? ? True;

即cube在Hierarchy中是未激活的(灰色) ,但其自身的激活按鈕是勾上的。

-----------------------------------------------------------------------------------------------------------

所有物體都有transform組件,如何獲取

#獲取腳本掛載的物體的transform組件
Transform trans = this.transform;
#同GameObject一樣,可直接使用
Debug.Log(transform.position)

只有transform組件這么好獲取。

其他的:
?

#獲取其他組件
BoxCollider bc = GetComponent<BoxCollider>();#獲取當前物體的子物體身上的某個組件
GetComponentInChildren<CapsuleCollider>(bc);#獲取當前物體的父物體身上的某個組件
GetComponentInParent<BoxCollider>();#添加一個組件
GameObject.AddComponent<AudioSource(組件名)>;
Cube.AddComponent<AudioSource(組件名)>;

? ? ? ? 上面說過在腳本中創建變量后,可在unity用拖拽的辦法給它從初始化,其實還有幾種其他辦法進行初始化 。

1.通過游戲名稱

#通過游戲物體的名稱來獲取游戲物體
GameObject test = GameObject.Find("Test");

上述方法需要在unity中切實創建了一個游戲物體,且其名為Test

2.通過游戲標簽

#通過游戲標簽獲取游戲物體
GameObject test = GameObject.FindWithTag("Enemy");

上述方法如果是“Enemy”標簽有對應多個物體呢。咋辦?---------嘗試過后是:會把其余為Enemy標簽的物體在unity中刪掉,但是不善標簽為Enemy的空物體。

前面我們學習過了預制體的創建(從Hierarchy欄把物體拖拽到Project欄即可)

我們可以通過預制體可創建多個長得一樣的實例,之前我們是通過拖拽生成的方式,

那么,如何在腳本中用代碼給我們生成呢?

先創建好一個預制體

接著在腳本中?

#獲取預制體
public GameObject Prefab;

同前面那樣,用拖拽的方法給其初始化即可。

#通過預制體實例化一個游戲物體
Instantiate(Prefab);

在unity運行后,就會給我們創建一個物體,并且名字帶有Clone

#通過預制體實例化一個游戲物體,并且作為當前腳本掛載的物體的子物體
Instantiate(Prefab,transform);

還有很多種方式來進行實例化

GameObject go = Instantiate(Prefab,Vector3.zero,Quaternion.identity);
#銷毀方法
Destory(go);

以上是實例化后,并放在初始位置,不旋轉。

游戲時間類

void Start(){//游戲開始到現在所花的時間      Debug.Log(Time.time); #放在start方法是這個含義,那放在update方法中還是?//時間縮放值Debug.Log(Time.timeScale);#正常是1倍,可用于進行游戲加速減速暫停//固定時間間隔Debug.Log(Time.fixedDeltaTime);}void Update(){//上一幀到這一幀所用的游戲時間Debug.Log(Time.deltaTime);
}#想要記錄從開始到現在的時間可以
float timer = 0 ;
timer += Time.delataTime;

路徑權限Application

用unity寫游戲時,unity是跨平臺的,所以在不同平臺的目錄結構可能不一樣。

當我們在unity要寫一個文件時,文件應存放到哪個路徑下,要讀一個文件時,從哪里讀?

這些都是Application類管理的。

#游戲數據文件夾路徑(只讀,游戲打包發布后,這些會被加密壓縮)
Debug.Log(Application.dataPath);#其實就是Asset文件夾的路徑#持久化文件夾路徑(寫文件的話,就寫在該路徑)
Debug.Log(Application.persistentDataPath);
#上面輸出的這個路徑就是對應了不同系統給自己的應用程序分配的空間,空間用于保存游戲的一些數據資料
#所以上面會拿到不同平臺的可儲存文件的路徑#StreamingAssets文件夾路徑(只讀,放配置文件)
Debug.Log(Application.streamingAssetsPath);
#其實就是游戲數據文件夾路徑再加一個/StreamingAssets
#而StreamingAssets文件夾是要自己在Assets文件夾下創建的
#為何要這個路徑?(游戲打包發布后,這個路徑下的文件不會加密壓縮,文件能正常顯示)
#該路徑適合放 配置文件,能讓所有人都能正常看見#臨時文件夾
Debug.Log(Application.temporaryCachePath);#控制是否能在后臺運行
Debug.Log(Application.runInBackground);
#玩游戲到一半的時候,我切到網易云聽歌,游戲在后臺是否繼續運行#打開Url , 用瀏覽器打開對應的url鏈接
Application.OpenURL("https://www.bilibili.com/");#退出游戲
Application.Quit();

場景類與場景管理類

? ? ? ? 一個游戲中,會有多個不同的場景,需要在不同的場景進行切換,這是如何做的?

可以看到,層級Hierarchy欄下有默認場景SampleScene , 對應Project欄下Scenes文件夾下的名為SampleScene文件。

我們可以在Project欄的Assets文件夾下的Scenes文件夾下右鍵創建新場景 creat--Scene? ? ? ? ? ? ? ?

要想通過腳本的代碼實現切換場景

首先:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

在窗口欄的File中, 點擊 Build Settings (生成設置)? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?在BuildSettings中點擊Add Open Scenes會把當前打開的場景給加載進去,如當前打開的是MyScene,點擊Add Open Scenes 會把My Scene添加進去,如下圖

但是這種方式就比較慢,另一種方式是拖拽

直接把Scenes文件夾下的場景文件拖拽到那里。


接著,便能創建游戲物體,賦予腳本,在腳本中寫場景有關的代碼

using UnityEngine.SceneManagement;
void start(){#場景跳轉,既可用索引值,也可用場景名稱SceneManager.LoadScene(1);#SceneManager.LoadScene("MyScene");#獲取當前場景Scene scene = SceneManager.GetActiveScene();#場景名稱Debug.Log(scene.name);#場景是否已經被加載了Debug.Log(scene.isLoaded);#場景路徑Debug.Log(scene.path);#場景在Build Settings 中的索引值Debug.Log(scene.buildIndex);#獲取場景的根游戲物體GameObject[] gos = scene.GetRootGameObjects();Debug.Log(gos.Length);//場景管理類Debug.Log(SceneManager.sceneCount); //當前已加載的活動場景數量//創建新場景Scene newScene = SceneManager.CreateScene("newScene");//卸載場景SceneManager.UnloadSceneAsync(newScene);//加載場景SceneManager.LoadScene("MyScene",LoadSceneMode.Single);//上面這種方式很簡單,作為替換的形式。當前的活動場景變為MyScene這個場景SceneManager.LoadScene("MyScene",LoadSceneMode.Additive);//Additive方式是添加,活動場景變為 原來的+MyScene。 場景內容疊加在一起}

場景異步加載

加載的方式可以是同步也可以異步加載。

同步就是順序執行所有代碼;? 可能會有卡頓現象。

異步則是把耗時操作交由其他線程去執行,執行完再把結果返回。

C#使用多線程實現異步,unity用協程實現異步。

using UnityEngine.SceneManagement;AsyncOperation operation;void start(){StartCoroutine(loadScene());    
}#創建協程方法來異步加載場景
IEnumerator loadScene(){    #方法有返回值,返回值類型IEnumeratoroperation = SceneManager.LoadSceneAsync(1);//可用場景索引值或場景名稱#加載完場景不要自動跳轉operation.allowSceneActivation = false;//默認值是true,即自動跳轉yield return operation;
}
float time = 0;void Update(){  #獲取場景加載進度。在Update方法中獲取,因為它加載的時間可能長可能短#要時時刻刻獲取它的加載進度。就可在Update里,每一幀都獲取一下進度//輸出加載進度0-0.9Debug.Log(operation.progress);//如果達到5s,再跳轉if(time>5){operation.allowSceneActivation = true;}}

了解transform

unity中的游戲物體之間可以有父子關系, 而父子關系是靠什么實現的?------transform組件

觀察父子的狀況,其實就是父物體與子物體的相對位置不會變化, 移動父物體時,子物體跟著動,保持相對位置。

而transform組件就是跟位置、旋轉、縮放相關。

游戲物體在腳本中是GameObject類,但是該類中沒有方法去控制父子關系。

使用Transform組件來控制游戲物體的父子關系,以及位置,旋轉,縮放。

void Start(){//獲取位置  position、localPosition都是vector3類型DebugLog(transform.position);#物體在世界坐標系的位置DebugLog(transform.localPosition);#物體相對于其父物體的位置//獲取旋轉 rotation、localRotation是四元數DebugLog(transform.rotation);  #相對于世界的DebugLog(transform.localRotation);#相對于父物體的DebugLog(transform.eulerAngles);#xyz方向旋轉角DebugLog(transform.localEulerAngles);//獲取縮放DebugLog(transform.localScale);#只有相對于父物體的縮放
}

當作一個3D游戲時,一般把(藍)Z軸正方向當作前方,相當于世界的前方,(紅)X軸正方向就是右方,(綠)Y軸正方向是上方。

//獲取三個軸的方向向量
Debug.Log(transform.forward);
Debug.Log(transform.right);
Debug.Log(transform.up);

void Update(){//時時刻刻看向000點。 要時刻肯定是每幀都要,每幀就要用Updatetransform.LookAt(Vector3.zero);#是正前方的z軸始終會指向0-0-0點//旋轉(自轉)transform.Rotate(Vector3.up,1); #注,Update方法每幀執行一次,則會繞y軸每幀旋轉1°//繞某物體旋轉(公轉)transform.RotateAround(Vector3.zero,Vector3.up,5);#三個參數:繞哪個點,哪個軸,旋轉度數//移動transform.Translate(Vector3.forward*0.1f);//移動方向*速度
}
void Start(){//父子關系//獲取父物體transform.parent.gameObject;//子物體個數。 父僅一個,子可多個DebugLog.(transform.childCount);//解除與子物體的關系transform.DetachChildren();//獲取子物體Transform trans = transform.Find("Child");//通過子物體名稱獲得trans = transform.GetChild(0);//通過索引獲取,第0個子物體//判斷一個物體是否是另一個物體的子物體bool res = trans.IsChildOf(transform);DebugLog.(res);//設置為父物體trans.SetParent(transform);}

電腦游戲操作方式

? ? ? ? 對于游戲來說,每一刻都要監聽鍵盤、鼠標的動靜,即要把相應的監聽代碼放在Update方法中。

void Update(){#鼠標的點擊#按下鼠標  0左鍵  1右鍵  2滾輪if (Input.GetMouseButtonDown(0)){Debug.Log("按下了鼠標左鍵");}#持續按下鼠標if (Input.GetMouseButton(0)){Debug.Log("持續按下鼠標左鍵");}#抬起鼠標if (Input.GetMouseButtonUp(0)){Debug.Log("抬起了鼠標左鍵");}#按下鍵盤按鍵if(Input.GetKeyDown(KeyCode.A)){Debug.Log("按下了A");}#持續按下鍵盤按鍵if(Input.GetKey(KeyCode.A)){Debug.Log("持續按下A");}#抬起鍵盤按鍵if(Input.GetKeyUp(KeyCode.A)){Debug.Log("松開了A");}
}

虛擬軸的使用

為何需要虛擬軸?

? ? ? ? 這關乎到游戲兼容問題,我們做的一個游戲可能需要兼容多個平臺,switch,任天堂,stream,有的玩家喜歡用鍵盤,有的喜歡用手柄。

如果代碼寫死,只能按”A“建左移,按"D"建右移,那游戲就只能在PC上跑了。

但是如果你設置了虛擬軸,就可以設置不同 的設備來操作這個虛擬軸。這樣,隨便不同的設備操作方式不同,但是都讓它控制虛擬軸,代碼通過判斷虛擬軸做出不同的操作。比如人物的移動不通過按鍵來進行,而通過虛擬軸。這樣無論什么游戲設備都能兼容這個游戲了。

Unity查看虛擬軸:

在窗口欄Edit - -- - - Project Settings

InputManager輸入管理器中,點擊展開Axes(軸)?

常用的是Horizontal 水平? 、 Vertical垂直? 兩個。

打開horizontal水平軸

left是鍵盤的上下左右鍵的←鍵。? ?備用按鍵就是 a

注:并不是Axes下的所有項都能作虛擬軸, 例如Jump

Jump只存在一個按鍵,你就沒法做成虛擬軸, 因為上面介紹虛擬軸時說過了,要兩個按鍵來作虛擬軸。 Jump就只能作成一個虛擬按鍵了。

void Update(){//獲取水平軸】 垂直軸float horizontal = Input.GetAxis("Horizontal");//用水平軸的名稱獲取float vertical = Input.GetAxis("Vertical");Debug.Log(horizontal+"     "+vertical);//虛擬按鍵if(Input.GetButtonDown("Jump")){Debug.Log("空格");}if(Input.GetButton("Jump")){Debug.Log("空格");}if(Input.GetButtonUp("Jump")){Debug.Log("空格");}}

觸摸方法的使用

? ? ? ? 移動端游戲,手機平板要用觸屏來玩游戲。

void Start(){//開啟多點觸摸Input.multiTouchEnabled =  true;}void Update(){//判斷單點觸摸if(Input.touchCount = = 1){//觸摸對象Touch touch = Input.touches[0];//觸摸位置Debug.Log(touch.position);//觸摸階段switch(touch.phase){case TouchPhase.Began:break;case TouchPhase.Moved:break;case TouchPhase.Stationary:break;case TouchPhase.Ended:break;case TouchPhase.Canceled:break;}}//判斷多點觸摸(假如這里是判斷兩點)if(Input.touchCount = = 2){Touch touch = Input.touches[0];Touch touch1 = Input.touches[1];}

燈光與烘焙

? ? ? ? ? ? ? ? 燈光有幾種類型。Directional light ; Spot light; Point Light, Area light.(定向光,聚光燈,點光源,區域(僅烘焙))

定向光: 就是從無窮遠處照射過來。? ?這是無論把燈光源物體放在哪里,整個場景的燈光都是從無窮遠處按照燈光物體設置的方向照射過來。

對于這四個物體而言,影子都是一樣的,影子的偏移量和方向是完全一樣的。

無論把上圖中的燈光物體放在哪里,它們影子都不變,只有燈光物體旋轉方向才會改變影子

color可修改燈光的顏色,intensity修改燈光強度;

shadow type改變陰影類型:無陰影,硬陰影:陰影邊緣是鋸齒一樣,對電腦性能消耗低;軟陰影:陰影邊緣被柔化,更真實,對電腦性能消耗大。

resolution:分辨率。低中高,非常高。越高性能消耗越大

Cookie:(剪影) 選一張鏤空圖片,再把燈光照射到上面進行投影,有點像皮影戲那種。

Draw Halo:(光暈)就是平常的光暈。勾上后,光源物體所在位置有光暈顯示。

Flare:(炫光)之后用資源實現。

culling mask:(剔除遮罩) everything就是所有的圖層都能受到照射。取消勾選的圖層就會照射不到,接受不到燈光,一身黑。

聚光燈:就像是拿手電筒照射。中間那個點控制照射距離,環上的四點控制照射半徑

點光源:顧名思義,就像是放個燈泡在那,向四面八方,360°發出光線。

看到這個球體了嘛,就是從點光源向四面八方照射,最遠照射到球面。

區域燈光(僅烘焙):就是個平面,從這個平面發出平行光。形狀可選矩形或圓形。

類似于影樓燈。

區域燈光怎么開啟? 這就要說到 模式了。

Mode:realtime,mixed,baked(實時,混合,烘焙)

混合就是將 實時和烘焙 都用上。

實時和烘焙的區別:

實時就是在游戲場景中,實時計算生成的燈光。(每一幀的燈光都可能不同)像賽車游戲,車燈就需要實時的更貼切,因為照射的內容在變,物體形狀變,那影子就會變。顯然,實時燈光很耗性能。

烘焙燈光: 先調好燈光,在這個場景中此時有這個燈光照射下,會有一張陰影圖或者說燈光照射的情況圖,保存場景當前的燈光照射信息,這就是烘焙-----------把場景當前的燈光照射信息實時計算一次保存下來,之后作為場景的燈光效果打在場景上,相當于保存了一張燈光照射圖再貼上去,以后不會變化燈光

區域燈光是僅烘焙的, 那么烘焙燈光怎么做:

選中區域燈光,確定對哪個物體進行烘焙, 選中物體

選中后,邊界會有橙色線框著(選中父,就會把子也選上)

接著在檢查器inspector中右邊的static處把 Contribute GI 勾上。

現在就支持燈光烘焙了

點擊window(窗口) --Rendering(渲染)--lighting(光照)

最后再點擊Generate lighting(生成照明)

最后便有文件生成出來,就是場景當前光照的烘焙信息

這時,即使刪掉燈光物體,場景還會有烘焙的燈光效果存在。

(燈光物體已經刪掉)

這時就省性能,還有光照信息,它就是把烘焙燈光的貼圖給貼上了。

攝影機

攝影機物體,在inspector檢查器欄中,projection(投影)可選擇為:perspective(透視)、orthographic(正交)

透視攝影機(perspective)

正交攝影機(orthographic)

正交攝影機就是一個矩形過去

接下來說一些細節

clear Flags(清除標志):skybox / solid color / depth only / Don't clear(天空盒/純色/僅深度/不清除)

skybox的意思:通過相機,把天空盒的內容清除掉 , 然后自己添加一個天空盒skybox組件,弄一個非常好看的天空

可以到資源商店下載天空盒資源使用

雖然場景當中沒有任何東西,但是對于相機而言,它就可以顯示這個天空盒了。

solid color:純色,相機看到的就是純色,可以在background調整顏色。

Don't clear :不清除,就是拍攝不到,那就顯示不了,都是黑色? ?一般不怎么 用

?depth only:僅深度,就是拍攝不到,我就不拍攝了(主要是用來疊加的)

(看不出來跟不清除有什么區別.....................)

僅深度的說明:(用來疊加)

上圖中,相機只有一個主相機,場景有有一個平面和一個立方體,然而因為位置關系,主相機只拍攝到平面,拍攝不到立方體。

接下來,我們添加一個相機

第二個相機讓其拍到立方體但是拍不到平面。

(注意:現在兩個相機的clear flags 都是 skybox)

小的紅框是你當前點擊的相機拍攝到的

而大紅框是看你設置的幾個相機中,深度值最大的那個相機所拍攝到的內容

目前,camera 的深度depth 比 Main camera 大, 所以大紅框顯示camera拍攝到的內容

把camera的depth值設為-0.08,?

Main camera的值設為0.17. 此時Main camera的Depth值就比camera的大

此時,顯示的內容應該是Main camera拍的內容

所以嗎,,注意:相機的深度值越高,它拍到的內容就優先顯示

把camera的Depth值重新調大

顯示的內容是camera拍到的

現在,做一個操作,(讓camera只收集它拍攝到的信息,而camera拍攝不到的那些區域,則不顯示,只顯示它拍攝到的內容------怎么做:將camera的 Clear Flages選為 Depth only)

這時,顯示的內容:

camera拍攝到的立方體顯示出來了,其他部分(camera沒拍到的)不顯示,其他部分的信息就找下一個相機(深度值比camera小)拍到的內容補充

所以僅深度就是把兩個相機的拍攝內容疊在一起。

深度值較高的相機 我們就可以將其clear Flags改為 Depth only, 這樣的話,我深度高,優先顯示我,我拍攝到的內容顯示我的,我拍攝不到的就找下一個相機(按深度遞減)?

culling mask剔除遮罩:之前說過了,取消勾選的那些圖層,如果有物體使用這些圖層,這些物體將不會被拍攝到

FOV Axis:(FOV軸)可選為垂直、水平(vertical、horizontal)

選擇垂直或水平,影響的是 下面那項:Field of View(視野)

視野值拖動修改,會改變相機形成的錐形視野空間。

clipping planes(剪裁平面)、Near(近面)、Far(遠面)

就是視野棱柱的上下底面----近遠面? ? ? ?在這個棱柱內的才能拍到

這是關于顯示的內容的起點位置(? X,Y),WH是寬高比例

Target Texture 目標紋理, Target Display目標顯示

目標紋理就是i相機拍攝到的內容渲染到目標顯示上,

目標顯示 是Display 1 , 游戲窗口也是Display 1

?這兩者要一致,否則就是顯示不了任何內容

相機拍攝到的內容不想讓其顯示在窗口怎么辦?

目標紋理那里現在是? 無(None),給它一個目標紋理,就會取代目標顯示了。

在Project欄中,右鍵 create--Render Texture(渲染器紋理)、

把新建的渲染器紋理拖到相機的Target Texture上

這時,雖然我們有且僅有一個相機,但是其拍攝到的內容看不見了

相機拍到的內容都時時刻刻放到剛新建的紋理里面了

這個紋理可以拖到任何游戲物體上使用

原來的游戲物體

拖拽紋理到游戲問題上后

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717452.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717452.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717452.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

BioTech - ADMET的性質預測 概述

歡迎關注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/136438192 ADMET&#xff0c;即 Absorption、Distribution、Metabolism、Excretion、Toxicity&#xff0c;吸收、分布、代謝、排泄、毒性…

題目 1629: 藍橋杯算法訓練VIP-接水問題

題目描述: 學校里有一個水房&#xff0c;水房里一共裝有m個龍頭可供同學們打開水&#xff0c;每個龍頭每秒鐘的供水量相等&#xff0c;均為1。現在有n名同學準備接水&#xff0c;他們的初始接水順序已經確定。將這些同學按接水順序從1到n編號&#xff0c;i號同學的接水量為wi。…

Linux shell:補充命令的使用

目錄 一.導讀 二.正文 三.結語 一.導讀 上一篇介紹了腳本的簡單概念以及使用&#xff0c;現在補充一些命令。 二.正文 目前處于全局目錄&#xff0c;通過mkdir創建名我為day01的文件。 通過cd命令day01 切換至day01文件當中。 使用vim文本編輯器文件名&#xff08;firstdir&…

設計模式學習筆記——工廠方法模式

設計模式&#xff08;創建型&#xff09;—— 工廠方法模式 傳統的獲取對象方法&#xff0c;是通過 new 關鍵字獲取一個對象&#xff0c;但是如果多個地方都需要該對象&#xff0c;就需要 new 很多次&#xff0c;這時候如果這個類發生了一些改變&#xff0c;如類名變了&#x…

靜態上下文調用了非靜態上下文

問題描述&#xff1a; static修飾的方法不能調用非static修飾方法 問題原因&#xff1a; 在Java中&#xff0c;靜態方法&#xff08;如main方法&#xff09;可以直接訪問靜態成員&#xff08;包括靜態變量和靜態方法&#xff09;&#xff0c;但不能直接訪問非靜態成員&#…

【Python】進階學習:pandas--query()用法詳解

&#x1f4da;【Python】進階學習&#xff1a;pandas–query()用法詳解 &#x1f308; 個人主頁&#xff1a;高斯小哥 &#x1f525; 高質量專欄&#xff1a;Matplotlib之旅&#xff1a;零基礎精通數據可視化、Python基礎【高質量合集】、PyTorch零基礎入門教程&#x1f448; 希…

劍指offer面試題24 二叉樹搜索樹的后續遍歷序列

考察點 二叉搜索樹&#xff0c;樹的后序遍歷知識點 題目 分析 本題目要求判斷某序列是否是二叉搜索樹的后序遍歷序列&#xff0c;后序遍歷的特點是左右根&#xff0c;因此序列的最后一個元素肯定是根結點&#xff0c;而前面的序列可以分為倆部分&#xff0c;第一部分是左子樹…

LeetCode --- 無重復字符的最長子串

題目描述 無重復字符的最長子串 找到無重復的最長連續字符串。 示例1中 abc | bca | cab 都符合題意。輸出3即可。 代碼 可以使用暴力枚舉 哈希表&#xff0c;哈希表來判斷是否重復&#xff0c;枚舉來判斷每一種情況&#xff0c;需要開兩層for循環&#xff0c;時間復雜度n…

linux高級編程:線程(二)、進程間的通信方式

線程&#xff1a; 回顧線程&#xff08;一&#xff09;&#xff1a; 1.線程間通信問題 線程間共享同一個資源&#xff08;臨界資源&#xff09; 互斥&#xff1a; 排他性訪問 linux系統 -- 提供了Posix標準的函數庫 -- 互斥量&#xff08;互斥鎖&#xff09; 原子操作&#x…

精通Matplotlib:從入門到精通的繪圖指南

在本篇文章中&#xff0c;我們將深入探索Matplotlib庫&#xff0c;這是一個強大的Python繪圖庫&#xff0c;廣泛用于數據可視化。Matplotlib讓我們能夠以簡單而直觀的方式創建各種靜態、動態和交互式的圖表。無論你是數據分析師、科研人員&#xff0c;還是任何需要數據可視化的…

用Redis如何實現延遲隊列?

在Redis中實現延遲隊列可以利用有序集合&#xff08;Sorted Set&#xff09;和定時任務的方式。下面是一個基本的實現思路&#xff1a; 添加延遲任務&#xff1a; 將任務信息作為一個字符串存儲在Redis中&#xff0c;同時將其對應的執行時間作為分數(score)存儲在有序集合中。使…

Bililive-go 實現直播自動監控錄制

前言 最近有直播錄制的需求&#xff0c;但是自己手動錄制太麻煩繁瑣&#xff0c;于是用了開源項目Bililive-go進行全自動監控錄制&#xff0c;目前這個項目已經有3K stars了 部署 為了方便我使用了docker compose 部署 version: 3.8 services:bililive:image: chigusa/bilil…

win環境nginx實戰配置詳解

項目中經常使用nginx做負載均衡&#xff0c;接口路由、文件、文檔的上傳及下載、視頻的代理播放等等&#xff0c;都離不開nginx的支持&#xff0c;今天我們分享一下其個使用場景。 1、配置文件 nd-nginx.conf 全局配置 #全局配置端&#xff0c;對全局生效&#xff0c;主要設置…

leetcode-字符串相加

415. 字符串相加 題目中已經說明不能使用庫函數直接將輸入的字符串轉換為整數。這就需要我們自己實現大數加法的邏輯&#xff0c;我們可以從兩個字符串的最后一位開始&#xff0c;逐位相加&#xff0c;同時記錄進位。如果某一位相加的結果超過10&#xff0c;那么需要向前進位。…

javascript實現的星座查詢

今天在這個網站http://xzxys.wiicha.com/看到查詢星座幸運色的效果&#xff0c;想研究一下代碼&#xff0c;結果右鍵禁用。后來參考了一下別人的代碼&#xff0c;琢磨著先實現了一下星座查詢的功能&#xff0c;輸入月份和日期四位數后&#xff0c;可以查詢屬于哪個星座&#xf…

群體風暴之錘(War3地圖編輯器)

文章目錄 0、大致原理1、創建隱形單位2、新事件開端3、環境→新條件4、動作4.1、單位組4.1.1、圓范圍內單位4.1.2、指定條件 4.2、對單位組內的所有單位釋放風暴之錘 0、大致原理 真MK向目標點釋放風暴之錘時選定&#xff08;以技能釋放點為圓心&#xff0c;設定半徑&#xff0…

Python編程語言常用的包管理工具介紹

conda是一個開源的包管理器和環境管理器&#xff0c;用于安裝、運行和更新包和它們的依賴項。conda可以用于Python編程語言&#xff0c;但它也支持其他編程語言。conda的主要特點是它能夠在不同的環境中管理不同的包集合&#xff0c;這使得它非常適合于數據科學和機器學習項目&…

洛谷 P1439 最長公共子序列

題目描述 給出 1,2,…,n 的兩個排列 P1? 和 P2? &#xff0c;求它們的最長公共子序列。 輸入格式 第一行是一個數 n。 接下來兩行&#xff0c;每行為 n 個數&#xff0c;為自然數 1,2,…,n 的一個排列。 輸出格式 一個數&#xff0c;即最長公共子序列的長度。 輸入輸出…

詳解算法的時間復雜度和空間復雜度!

目錄 ?編輯 1. 算法效率 2. 時間復雜度 2.1 時間復雜度的概念 2.2 大O的表示漸進法 2.3 一個栗子 3. 空間復雜度 4. 常見復雜度對比 5. 完結散花 ??????? 悟已往之不諫&#xff0c;知來者猶可追 創作不易&#xff0c;寶子們&#xff01;如果這篇文章對你們有…

Flex布局

Flex布局是一種用于創建靈活且自適應的布局模型&#xff0c;它使得元素能夠更好地響應不同的屏幕尺寸和設備。Flex布局基于容器和項目的概念&#xff0c;通過設置容器的屬性來控制項目的布局和對齊方式。 Flex布局的關鍵概念包括&#xff1a; 父容器&#xff08;Flex容器&…