1-3 Unity零基礎入門 古跡探險
任務1/2:資料下載
鏈接:https://pan.baidu.com/s/1jHVymNk 密碼:rbob
任務3:工程的創建和打開
Project:古跡探險
任務4:工程目錄
任務5:資源的導入方式
方法1a. 在window->Asset Store->搜索
方法1b. 在Project面板上的搜索框內直接搜索想要資源的關鍵字即可,可以指定搜索范圍
可以選為Asset Store(前提是在Edit->Preferences->General->勾選Show Asset Store search hits)
方法2. 從第三方.unitypackage中導入
將.unitypackage拖入工程面板即可
或是在工程面板右鍵Import Package->Custom Package,選擇.unitypackage即可
方法3. 導入unity自帶的資源(指的是安裝unity自帶的Standard Assets資源)
在工程面板右鍵Import Package->除了Custom Package之外的都是自帶資源
如果在安裝unity的時候沒有勾選Standard Assets,則不會顯示
Standard Assets里面的資源挺優質的
任務6:3D物體
1. 自帶的簡單3D幾何體
cube/ sphere/ capsule/ cylinder/ Plane(單面顯示,多用作地板)/ Quad面片(單面顯示,小)/ Terrain/ Tree/ WindZone(風區,制造隨風搖擺的效果)/ 3D Text等
2. 復雜的3D模型
Mesh Filter:網格,模型的形狀
Mesh Renderer中的Materials:模型的特點,光滑度/透明等等
Texture:使用貼圖
任務7:菜單欄
Mobile Input是Standard Assets中擴展出來的一個菜單,用來表示是否啟動移動端的控制
GameObject菜單下方有一些有用的工具
Align With View:當想要把Camera的視角設置成當前Scene的視角的時候
任務8:工具欄
Center/ Pivot的區別
Center:中心點 有子物體的時候會計算平均的中心位置,可能會變化
Pivot:原點/ 坐標點 Position,在建模的時候一般就確定了
中間三個鍵:運行/ 暫停/ 逐幀運行
右上角Layers:每個GameObject都屬於一個層,可以設定成鎖定/不可見
任務9:窗口操作
任務10:Scene窗口下視野控制
飛行模式:按住鼠標右鍵進入飛行模式
鼠標移動進行視野旋轉
WASD進行前進后退左右的控制
QE進行垂直上下的控制
任務11:Transform組件
任務12:控制物體移動的小技巧
Ctrl:
之前提到了按住ctrl移動物體的時候會一米一米地移動,那么步長可以修改嗎?
Edit->Snap Settings->默認的move x/y/z 為1,可以修改
按住ctrl后也可以進行單位化的scale和rotate
v:
選定一個物體,按住v鍵,鼠標會自動吸附物體的頂點
可以將物體按照該頂點進行移動/ 旋轉/ 縮放
移動時會將該頂點與其他物體的頂點進行吸附
任務13:導入資源,Prefab預制體
Prefab的instance中的Inspector上有Select/ Revert/ Apply
Select:會跳轉到該instance對應的prefab上
Revert:
(如果instance的某些屬性修改成和Prefab不同時,會以粗體顯示,並且不會受到prefab的修改而改變)
Apply:點擊某個instance里的Apply,會將該instance的屬性值賦值給prefab(修改了prefab的屬性)
如果有一個instance的prefab被刪除了而仍需要保留該instance,但是instance會顯示missing,在GameObject中選中break prefab instance即可;如果有某一個instance想脫離prefab的關聯,也是選中break prefab instance即可
任務14&15:地形設計
作為開發,了解就好,團隊里的美工會設計好的
3D Object->Terrain
選中pivot,從原點進行聚焦觀察
創建一個Terrain后會在Project中自動創建一個New Terrain的文件,該文件保存了具體的地形數據,可以新建文件夾Terrains並命名為Terrain Data
組件:
Terrain Collider 地形的碰撞體
Terrain 設置地形的形狀
第一個按鈕為Raise/Lower the Terrain Height:筆刷粉刷地形的時候地形會升高/(按住Shift)降低(最低值為0)
第二個按鈕為Set the Terrain Height:升高地形,有一個height的值,升高的時候不會超過這個height,如果原地形的高度已經超過,則會慢慢降低地形直至該height;height旁邊有一個flatten的按鈕,會使整個地形的高度變為相同(flat),但不會超過maximun height
第三個按鈕為Smooth the Terrain Height:將地形變化變得平緩
第四個按鈕為Paint Texture:繪制貼圖
Edit Texture->Add Texture,select texture: 分為Albedo Smoothness和Normal,Normal不是必要的。Normal選擇后會將凹凸不平的細節顯示地更好
可以添加多張貼圖,第一張被添加的貼圖會覆蓋整個Tarrain,第二張被添加的時候不會有任何效果,需要通過鼠標進行粉刷
添加貼圖的時候下面有一個size的選擇:表示一張貼圖的大小(需要粉刷多張貼圖到整個terrain)
第五個按鈕為Place Trees:放置植被
Edit Trees->Add Tree->選擇Tree的prefab->add
之后用筆刷粉刷即可,按住shift粉刷為減少樹;
可以設置brush size/ tree density/ tree height (random)/ Lock width to height/ color variation等
第六個按鈕為Paint Details:一般用來粉飾小草/植被的細節
Edit details->Add grass texture->選擇貼圖->筆刷粉刷即可(Opacity為密度)
草是貼圖,而樹是模型,草會隨着你的視野方向改變而面向你
第七個按鈕可以設置大小等(默認長寬為500m,一個大格為100m);這里設置成50*50*height(此時一個大格為10m);高度height為地形的最大高度,設置成50
可以設置筆刷的形狀/ 大小size/ 影響地形的快慢opacity
在修改地形屬性的時候右下角會有一個Clustering的處理光照進度條,如果不想要這個處理的話(耗費性能),Window->Lighting->Setting->Scene->uncheck Auto Generate
任務16/17/18:古跡探險地形設計
1. 放置人物 Meshes->dwarf_hero
2. 如何知道hero的大小呢?
創建一個cube,大小對比;調節hero高度在1-2m之間即可
3. 創建Terrain;width:20,length:20,height:20
4. 將自動生成的Terrain數據命名並放入Terrains文件夾
5 將hero放在(10, 0, 0)的位置
6. 地形粉刷
思路:三面環山,中間略微有起伏
size 100 opacity 30 粉刷山脈
size 100 opacity 5 粉刷中間空曠地區起伏
使用smooth height將地形變得平滑
7. 添加貼圖Texture:選擇GrassRockyAlbedo
將size改為20, 20
8. 實現群山環繞的效果
Prefabs->Rock_Large, scale為0.3
環繞三面擺放,並將每一塊石頭手動隨機旋轉/調節大小等
9. 既然為古跡探險,加入Ruin元素
Prefabs里的石頭/ruin隨意加
10. 添加草/植被
Meshes->Vegetation->Low有多種草的模型
Meshes->Vegetation->Bushes有樹的模型
手動調整大小位置旋轉
11. 將所有環境有關的GameObject(樹/石/Ruin)放入empty gameobject Env
總體效果:
任務19:剛體
Mass 質量,可以控制慣性
Drag 摩擦力(移動時的阻力)
Angular Drag 旋轉時的摩擦力
Constraints:凍結某個屬性(剛體效果不改變某個屬性)
任務20:碰撞器
Box collider是最節約性能的,越復雜的collider越耗費性能,Mesh collider最耗費性能
Mesh Collider:需要assign一個mesh,選擇和Mesh Filter相同的mesh即可
比如想要給Rock_Large添加一個Mesh Collider,需要展開Rock_Large,選中里面的Group1,添加一個mesh collider,把mesh選擇為Group1即可(會自動選擇)
NB: 不需要太精細的情況下,沒必要選擇mesh collider,因為太耗費性能;如果你的mesh比較簡單,那么選擇mesh collider是可行的
任務21/22:碰撞檢測函數/ 碰撞信息取得
void OnCollisionEnter/Exit/Stay(Collision collision);
碰撞檢測是基於剛體的,也就是說即使有collider但是沒有rigidbody,碰撞檢測是不可用的
碰撞檢測的條件:https://docs.unity3d.com/Manual/CollidersOverview.html
任務23:觸發檢測
勾選collider的is trigger,使得該collider成為一個觸發器,其他物體可以進入該collider內部
void OnTriggerEnter/Exit/Stay(Collider other);
任務24:Unity中的四種燈光
Create->Light->Directional Light/ Point Light/ Spotlight/ Area Light
Directional Light:直射光/ 平行光/ 太陽,它的position是沒有影響的,只有rotation是有影響的;在天空盒子里可以看到一個太陽,太陽是位於直射光的后面的,當直射光旋轉的時候,太陽的位置也會隨之改變
Point Light:點光源/ 燈泡,屬性Range,Intensity
SpotLight:手電筒/ 從一點發射一個錐形范圍的光,錐形的大小和長度是可調節的
Area Light:區域光,主要用於烘培,實際環境的光照設置不會使用它
任務25:給場景添加火堆
古墓探險不需要太強烈的光,將directional light調成日出的狀態(180, 90, 0), indensity 0.3
創建一個空物體Light,將Direcitional light放在其下,並添加一個Point light
調成暗紫色,intensity調弱一點,分別放幾個在山上
調成弱黃色,放幾個在空地上
創建火堆Bonfire:
Prefabs->Lantern_01 火堆頭
Prefabs->Barrier_02 火堆底
在Bonfire中創建一個point light,放置在火堆的正中間,顏色偏黃,intensity調強
制作成Prefab方便日后修改
任務26/27:Lightmapping
Lightmapping 光照貼圖
如果不使用光照貼圖的話,光在游戲運行時對場景的影響是需要實時計算的,耗費性能
如果使用lightmapping的話,會提前將光照計算好,烘培成貼圖,將貼圖貼在環境模型上,實際運行時就不需要實時進行計算了,能夠很大提高性能
將Terrain,Env及其孩子勾選成static的;再將所有燈光也勾選成static
將所有燈光的mode選擇成baked
Window->Lighting->Settings
Scene中的Debug Settings中點擊Generate Lighting
會發現整個環境亮了許多,將直射光改為Rotation的x值改為191.2;點光源的range調小,重新烘焙
此時若是禁用了燈光,會發現環境下的燈光效果不變(不再是real time了)
但是這樣的話火堆的效果就沒有了,火焰需要一閃一閃的效果
火堆光的進一步改進:
將火堆光的mode改為mixed,表示即可以實時計算,又可以烘培
並將其的Shadow Type改為Hard Shadows或Soft Shadows(hard烘培時間會慢一點)
任務28:使用粒子系統創建火焰
在Bonfire下創建Effects->Particle System
Shape:修改成火堆的大小
Start Lifetime:生命時間改小一點 1.5
Start Speed:速度設置為Random between two constants 1~1.5
粒子樣子:FX->Fire->flame 4x4,這是一個4*4的動畫效果
在Fire中創建material flame,shader選擇Particles->Additive;texture選擇flame 4x4;顏色設置成白色
將該material指定給粒子系統
改變粒子系統的Renderer中的material即可
但是這時候texture的動畫效果沒有展示
勾選粒子系統的Texture Sheet Animation,將Tiles設置成4*4(4行4列的動畫)
現在已經有火焰的效果了,但是粒子太大了
修改粒子系統的Start Size即可
粒子應該越來越小:
Size over Lifetime:修改成一個曲線
也可以修改粒子數量
Emission中的Rate over time可以修改成1-20
任務29: 創建動畫(火光閃爍)
通過動畫系統實現燈光的閃爍
1. 選中Bonfire的點光源
2. Window->Animation->Create->將新建的Flicker.anim放在文件夾Animations中
會自動在Bonfire的點光源里創建一個Animator的組件,用來控制動畫的播放;和在Animations文件夾下創建一個動畫文件Flicker.anim和一個叫Point light的動畫狀態機
3. 編輯Flicker動畫
Window->Animation,以打開animation窗口,並選中Flicker或點光源
Add Property->Light->Intensity 火光亮度
經過不同時間,調整intensity數值(火焰效果需要intensity的變化很大)
Add Property->Transform->Position 火光左右搖擺
把sample設為25,減慢動畫播放速度
任務30:導航系統-導航網格生成
導航系統(尋路系統):角色朝某個地方運動時,通過導航系統尋找最短路徑,並沿着最短路徑到達指定位置,並會自動進行避障
進行導航網格的烘焙:
確保Env和Terrain的navigation static是勾選狀態
生成導航網格
Window->Navigation->Bake
點擊bake生成藍色區域,為可行走區域
Agent Radius:控制不可行走區域的半徑,修改成0.1
Agent Height:
因為草是可以穿越的,所以把草的Navigation static取消勾選
發現一些石頭/樹的上方也是可行走的,選中石頭的Mesh renderer組件(Group1),Navigation->Object->Navigation Area->Not Walkable(樹也類似)
控制Hero在導航網格上行走
給Hero添加導航組件Nav Mesh Agent后會自動生成一個圓柱體,用於計算某個區域是否可以穿過的參照,需要保證圓柱體和Hero模型大小保持一致:Radius/ Height
之后需要代碼來告訴Hero要去的目的地(下個任務)
任務31:通過導航系統控制英雄的移動
思路:通過鼠標在地面上點擊的點作為目的地,讓導航系統控制英雄向目的地移動
創建Hero.cs並attach到Hero
1. 獲取目標位置:鼠標按下的時候,向鼠標點擊的位置發射一道射線,判斷射線和Terrain的哪一個位置發生碰撞,獲取該位置
Input.GetMouseButtonDown(0); // 鼠標左鍵按下
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // main camera中的ScreenPointToRay()將屏幕坐標轉換為一道射線;Input.mousePosition為屏幕坐標
RaycastHit hit; // 用來保存碰撞信息
Physics.Raycast(ray, out hit); // 如果與任意碰撞器發生碰撞,返回true;out參數hit為碰撞信息
hit.point; // 碰撞的地面位置(x,y,z)
2. 控制角色到達位置:將hit.point的點賦值給Nav Mesh Agent
using UnityEngine.AI;
public navMeshAgent agent; // 得到Nav Mesh Agent;
agent.SetDestination(hit.point); // 設置Nav Mesh Agent的目的地點
3. 成功,但是角色轉向太慢了
Nav Mesh Agent->Angular Speed=360
public class Hero : MonoBehaviour { public NavMeshAgent agent; // Update is called once per frame void Update () { if(Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if(Physics.Raycast(ray, out hit)) { agent.SetDestination(hit.point); } } } }
任務32:控制攝像機的跟隨
調整相機的跟隨位置(12.22, 7.27, -5) (39.3, 0, 0) (Hero位置(12.078, 1.363, 0))
創建FollowTarget.cs並attach到Main Camera上
public Transform hero; // 跟隨目標的Transform(Transform組件就夠用了)
private Vector3 offset; offset = transform.position - hero.position; // 偏移量
transform.position = hero.position + offset; // 相機位置的跟隨
public class FollowTarget : MonoBehaviour { public Transform hero; private Vector3 offset; // Use this for initialization void Start () { offset = transform.position - hero.position; } // Update is called once per frame void Update () { transform.position = hero.position + offset; } }
任務33:控制角色的動畫播放
動畫效果為Animations中的四個動畫文件,我們這里需要的是idle/ walk和run
通過動畫狀態機進行動畫的控制
Hero->Animator中需要動畫狀態機
在Animation文件夾中創建Animation Controller,叫做HeroController,並賦值到Hero
編輯動畫狀態機:
選中Hero,Window->Animator
設置默認狀態Entry,將idle動畫拖到Entry
狀態切換:
idle->walk; // 通過速度的檢測來切換狀態
如何獲得Nav Mesh Agent中的Speed呢
在Animator窗口左側Parameter中添加一個float speed
將walk動畫拖到Animator窗口中
右鍵idle狀態,make transition,指向walk狀態
點擊transition的線
在Inspector中添加一個condition:speed greater than 0
取消勾選Has Exit Time,因為動畫的切換會隨時發生
在Hero.cs中
public Animator anim; // 獲取Animator組件
anim.setFloat("speed", agent.velocity.magnitude); // 賦值給speed
public class Hero : MonoBehaviour { public NavMeshAgent agent; public Animator anim; // Update is called once per frame void Update () { if(Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if(Physics.Raycast(ray, out hit)) { agent.SetDestination(hit.point); } } anim.SetFloat("speed", agent.velocity.magnitude); } }
walk->run; // speed>2時
run->walk; //類似
walk->idle; // 類似
完成