有空的同學,點擊領取李笑來的糖果。
https://candy.one/i/300032
博客地址:
https://wlxklyh.github.io/2017/07/30/unity_study/
喜歡我的文章請關注我的簡書
總體的思維導圖
通過下面一張圖,大概的知道一個學習的方向和流程。對于這篇文章講的是第一個部分,入門,初次接觸unity。
一、安裝
1、安裝教程(windows)
mac就比較簡單 官網下載dmg就可以安裝使用了
我用下面圖中的兩個文件完成安裝,一個是安裝文件(4.7),一個是破解,然后根據下面鏈接完成安裝
http://jingyan.baidu.com/article/90895e0f959c7564ec6b0bfb.html
2、需要的文件(百度網盤分享)
http://pan.baidu.com/s/1slFHeFz
- 分享的文件里的東西有:
- 【安裝使用】:Unity 4.7.1安裝文件
- 【安裝使用】:Unity 4.x pro Patch.exe
- 【入門使用】:《unity4.x從入門到精通》
- 【入門使用】:簡單的工程(微信飛機游戲):
- 【進一步了解使用】:RPG游戲的簡單的工程
- 【shader學習使用】:《Unity Shader入門精要》
3、安裝結果
使用a.Unity 4.7.1安裝文件 b.Unity 4.x pro Patch.exe 然后用上上面的教程鏈接就可以完成windows unity的安裝 打開如下:
二、入門學習:
1、開始我找了本書看《unity4.x從入門到精通》:
《unity4.x從入門到精通》
http://pan.baidu.com/s/1slFHeFz
2、《unity4.x從入門到精通》讀書的記錄:
第一章 (可跳過)
第一章 沒什么干貨 可以直接跳過
第二章 (重點看2.1 2.2+實操一下)
- 剛接觸的unity的可以按照第二章說的去操作一下 感受一下unity的一些功能 想貪快的就看2.1 、2.2部分即可 后面的用到再查閱
- 快捷鍵部分 等到基本入門了 再來看一遍 會比較受用的感覺
第三章 (粗略看)
- 第三章看下 不用糾那么細致
第四章 (重點看+操作)
- 第四章書講的是怎么寫代碼的 看完第四章就會輸出hello world
截取兩張圖
后面5-17章的當作工具書看
12章 到16 是針對開發的介紹
17章 進階 : 網絡
3、大致的瀏覽了《unity4.x從入門到精通》 前四章之后帶著幾個疑問去分類學習:
3.1、C#代碼跟unity怎么關聯起來? 書中13章
1、C#腳本的規則
(1)凡事需要添加到游戲對象的C#腳本類都是需要直接或者間接的繼承 MonoBehaviour 如果在unity添加腳本 unity會自動填充繼承MonoBehaviour的代碼 如果是自己新建一個文件 然后在unity從拖拽添加component 這樣是不會成功的(后面會說unity怎么添加C#文件)
(2)繼承了MonoBehaviour的類 都會有Start 和 Awake函數的繼承 一般使用Start和Awake來初始化 不使用構造函數的原因是unity中無法確定構造函數的順序。這里我覺得有個原因是:unity會把所有綁定在對象身上的類實例化 然后才可以GetComponent() 例如:下面的操作如果在構造函數中做 可能PlayerAttack這個沒有實例化 那么獲取不到 所以把初始化工作放在Start中
(3)類名和腳本文件名相同
(4)協同函數Coroutines 返回類型必須是Ienumerator
(5)C#不支持自定義命名空間
2、C#腳本在unity編輯器中關聯對象(十三章有詳細介紹)
1、創建腳本的方法:
2、創建完之后的編輯:
這里可以修改用MonoDevelop的編輯器 或者用Vs2012作為代碼編輯
3、關聯到對象去
(3.1)添加一個gameobject
(3.2) 然后給gameObject添加腳本
在Unity中,繼承MonoBehaviour的C#腳本都被看作一個Component 游戲對象可以理解為一個容納各種類型component的容器 游戲對象的所有component一起決定了這個對象的行為表現 這個對象被添加到scene中之后 然后點擊build and run 之后這個腳本的Start函數就會被調用一起 可以在這里輸出 hello world 這就算是unity的hello world
3、怎么獲取別的對象以及他的component
使用函數 GameObject.Find null則是找不到 根據類名
使用函數GameObject.FindWithTag
還有在unity編輯器中拖拽
查看數組的表13-6 表13-7 表13-8 表13-9
三、工程學習:
看了《unity4.x從入門到精通》 簡單操作unity之后 我上網找幾個簡單的游戲demo來看下,這樣我覺得會比較快上手。
1、微信飛機大戰
工程下載地址:
http://pan.baidu.com/s/1slFHeFz (網上找的工程)
這個比較容易看懂
下面說明的過程:
(1)背景移動 -->(2)敵機出生-->(3)自己的飛行
==》 ==》
1、初看這個工程
只有一個場景scene
預制體有這些
腳本是這些
2、分幾個部分看
2.1、scene
1.里面有個 Main Camera 點擊它然后看導航欄Inspector
2.Main Camera里面有一些component組件 其中Camera 去修改size view port然后運行看下結果
3.除了Main Camera 這個Scene里面還有一些飛機(hero) 背景(bg) 還一些不是UI的東西(bombManager)
上面大概的了解到,在這個Scene里面拖拽了一些物件 還有一個攝像機 把這些物件投影到屏幕中,到目前為止,我們大概知道是怎么得到游戲的靜態界面的,但是游戲是怎么動起來的還不知道。接下來腳本就是講怎么動起來的。
2.2、腳本
- 代碼入口,沒有一個明確的Main函數入口
下面按照順序說下(1)背景移動 (2)怎么生成敵機 (3)怎么控制自己的戰機
(1)背景移動
scene里面有個object叫bg 然后再點擊其中一個background查看導航欄
可以看到每個background都掛在了一個腳本組件 BackgroundTransform.cs 這個腳本就是控制不背景移動的
看到BackgroundTransform這個腳本 兩個背景來控制屏幕的背景交替向下移動
public class BackgroundTransform : MonoBehaviour {
public static float moveSpeed = 2f;
// Update is called once per frame
void Update () {
this.transform.Translate( Vector3.down * moveSpeed * Time.deltaTime );
Vector3 postion = this.transform.position;
if(postion.y<=-8.52f){
//有兩個背景在交替滾動 如果有一個滾動到屏幕外面則改動顯示
this.transform.position = new Vector3(postion.x,postion.y+8.52f*2,postion.z );
}
}
}
(2)怎么生成敵機
scene里面有個叫spawn的東西 這個spawn十個空object 里面掛了一個spawn.cs腳本組件
【代碼如下】:
地機的行為就看模型上面掛的腳本組件Enemy.cs
(3)怎么控制自己的戰機
同樣的在hero這個上面掛了Hero.cs的腳本組件 然后具體就看里面的代碼
2、RPG游戲
然后再找個復雜點的游戲工程來看
1、初看工程
- 工程下載地址:
http://pan.baidu.com/s/1slFHeFz(網上找的工程) -
工程的腳本目錄
2、工程代碼查看
看下怎么把這個人物控制方向運動起來的
1.打開03_play這個scene 然后拖拽一個Magician模型到scene中
先在Prefabs文件夾中找到Magician看模型有什么掛件
Magician掛了Character Controller這個控制組件
這個是角色控制器 可以對角色做移動的操作 在playermove腳本里面用到-
Magician還掛了PlayerDir PlayerMove PlayerAnimation PlayerState PlayerAttack等腳本來實現模型的行為
看下PlayerMove的update函數
這里判斷如果距離大于0.3f則會移動
從Magician引發的問題:
2.1、移動的時候有個targetPosition 這個是怎么來的?
targetPosition 是PlayerDir.cs這個里面的成員
PlayerDir.cs里面會計算鼠標點擊屏幕的位置發出的射線的碰撞結果 如果是地面那么修改這個玩家的朝向
2.2、又引發一個問題鼠標怎么會變樣?
我們看到03_play這個scene有個object叫GameSetting 這個是一個純粹為了掛腳本用的object
我們看到這個CursorManager就是我們在游戲中的鼠標的管理類
2.3、模型怎么會動起來呢?
打開03_play這個scene 然后拖拽一個Magician模型到scene中 然后在菜單欄window animation打開animation窗口 然后可以選擇已經做好的動作 attack1 然后點擊播放 現在我們知道動作可以預先做好 然后再代碼中調用 我們看下代碼是怎么調用的
PlayerAnimation.cs這個腳本 根據一個狀態去 播放動畫animation.CrossFade(animName);
// Update is called once per frame
void LateUpdate () {
if (attack.state == PlayerState.ControlWalk) {
if (move.state == ControlWalkState.Moving) {
PlayAnim("Run");
} else if (move.state == ControlWalkState.Idle) {
PlayAnim("Idle");
}
} else if (attack.state == PlayerState.NormalAttack) {
if (attack.attack_state == AttackState.Moving) {
PlayAnim("Run");
}
}
}
void PlayAnim(string animName) {
animation.CrossFade(animName);
}
這個項目的運行
之后看下怎么改改這個項目 不懂的再google 或者再去細看unity的一些用法 或則C#的用法
四、Unity Shader學習
A、我學習的三個點
1.下載源碼中源碼下載:
https://github.com/candycat1992/Unity_Shaders_Book
2.學習hello world!
下面gif是unity shader的hello world!
3.看書照著源碼學習 然后實踐
B、學習隨便記錄的筆記
1.第一章
2.第二章 渲染流水線
應用階段->幾何階段->光柵化階段
應用階段把渲染圖元交給幾何階段
2.2CPU 和 GPU 的通信
- 把數據加載到顯存中
- 設置渲染狀態
- 調用 drallcall
1.把數據加載到顯存中
硬盤--->內存--->顯存
頂點數據 法線方向 紋理坐標
2.設置渲染狀態
vs ps
頂點著色器 片元著色器
3.drawcall
2.3GPU 流水線
頂點著色器
把頂點坐標轉換到齊次裁剪坐標系得到歸一化的設備坐標 NDC
opengl unity的 NDC 是-1 1
屏幕映射 轉換到屏幕坐標系
屏幕坐標系Opengl 是左下角
3.第三章 Unity shader基礎
3.1 創建shader的常見流程
- 創建一個材質
- 創建一個unity shader 并把它賦給上一步中創建的材質
- 把材質賦給要渲染的對象
- 在材質面板上(選中材質然后查看導航欄)調整shader的屬性
3.2 shader lab
GLSL是opengl的shader語言 Directx的shader語言是HLSL shader lab的就是 unity shader的shader語言
可以細看下這個章節 熟悉下語法
4 學習 Shader 所需的數學知識
一些基礎的知識都是大概知道 可以等到要用到的時候再去復習
一些空間 M 模型空間 W 世界空間 V 攝像機空間 NDC 歸一化空間
5 開始學習 Shader
5.2 最簡單的片元著色器 頂點著色器
5.2.2 unity支持的語義:
POSITION,TANGENT,NORMAL,TEXCOORD0,TEXCOORD1,COLOR
5.2.3 頂點著色器和片元著色器之間的通信:
聲明一個新的結構體v2f v2f可用于定點著色器和片元著色器之間傳遞信息
5.3.1內置包含的文件
在后面的學習中 總是會用到一些內置的文件
需要include一下 類似C++的include
5.5 Debug技巧
- 把想知道的值賦值到某個顏色 通過屏幕上顯示的顏色來判斷一個值
- 還可以找到一個簡單的取色腳本 ColorPicker.cs
- 高級的:Visual Studio Graphics Debugger
- Unity里面的幀調試器
6 Unity 中的基礎光照
6.2 進入攝像機的光分成4個部分
- 自發光:本身輻射量 如果沒有全局光照技術 自會影響自己的輻射量
- 高光反射:(我覺得是完全鏡面反射)光源的完全鏡面反射方向散射多少輻射量?? 是鏡面反射的散射??
- 漫反射:這個就是光源的漫反射
- 環境光:其他所有的間接光照
Phong 模型來計算高光反射部分:
6.4 光照實現
(1)Properties定義一個顏色值
(2)LightMode標簽是 Pass 標簽的一種 只有定義了正確的 LightMode 我們才能得到一些 Unity的內置光照變量
Tags { "LightMode"="ForwardBase" }
(3)還是之前的 CGPROGRAM ENDCG
(4)為了用到 Unity的內置變量
''' #include "Lighting.cginc" "'
(5)逐頂點 著色器
- 逐頂點漫反射:有鋸齒 應該是因為處理是每個片元的頂點 所以不精細
- 逐像素漫反射:無鋸齒 但是黑面太黑 都是一個色 黑色
- 半伯蘭特模型:無鋸齒 黑面有漸變
c = c * m (0.5 (n * I) + 0.5)
7 基礎紋理
- 記住這個 : o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
7.1.2 紋理取樣
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
7.2 凹凸映射
不改變頂點 改變的是繪制
法線紋理 normal map
7.2.1高度紋理
存儲的是強度值 這個通過高度來計算法線
顏色越淺越突 反而凹
7.2.2法線紋理
法線的向量分量是 -1 到1
所以 pixel = (noamal+1)/2
normal = (pixel * 2) - 1
這種紋理稱為是模型空間的法線紋理 我恩會采用另外一種坐標空間 切線空間 我們用模型頂點的切線空間來存儲法線 對于每個頂點都有一個屬于自己的切線空間 這個切線空間的原點就是該頂點本身 z 軸就是頂點的法線 x 軸是頂點的切線方向
我們的法線紋理 存儲的是 法線在各自的切線空間的向量 大部分都是淺藍色的原因是 0 0 1映射到0 1就是0.5 0.5 1(淺藍色) 0 0 1就是 z 軸 大部分的法線都是跟切線空間的 z 軸同方向
一種是模型空間下的法線紋理 一種是切線空間下的法線紋理
模型空間存儲的優點:
- 實現簡單 直觀。生成簡單
- 提供平滑的邊界 模型空間可以生成平滑
切線空間優點:
- 自由度高 模型空間的是絕對法線信息 應用到不同網格都有合理的效果
- 可進行 UV 動畫 我們通過移動一個紋理的 UV 坐標來實現凹凸移動的效果
- 可壓縮 只此處 xy z 可以推倒得到
7.2.3 實踐
- 一種在切線空間下進行光照計算 把光照方向、視角方向變換到切線空間下 :效率比較高 在頂點著色器可以完成 光照和視角的轉換 第二種要堆法線紋理取樣 需要在片元著色器中變換 我覺得應該是片元的數量大于頂點的數量所以轉換需要很多
有時我們要在世界空間下進行一些計算 例如在 Cubemap進行環境映射 需要使用世界空間下進行一些計算 (這個 cubemap 不知講啥) - 另外一種是在世界坐標空間下進行光照計算 我們要把切線空間下的法線防線轉換到世界空間下:
- 在切線空間下計算
思路:在片元著色器中得到紋理采樣的切線空間下的法線 然后再與切線空間下的視角方向 光照方向進行計算
注:float4 texcoord : TEXCOORD0; 傳入的是float4 xy 是原因的紋理 UV zw 是法線紋理 uv
7.2.4 unity 法線紋理類型
法線紋理會根據平臺被壓縮
使用 unpackNormal 函數取解壓
普通紋理的話 是4個通道都是不能舍棄 如果是法線紋理 那么只有ag 是需呀的 br 是不需要的 用 DXT5nm 可以升內存空間。
Create from Grayscale 是凹凸映射的方法 高度圖
7.3漸變紋理
7.4遮罩紋理
使用其中某個(或者幾個)通道做乘法 如果通道為0 可以保證表面不受該屬性影響
8透明效果
unity 先渲染 Background 然后渲染 Geometry 大多數的不透明物體 前面都是開啟深度測試和深度寫入 之后渲染 AlphaTest 這個是透明物體 需要排序 從遠到近 然后進行渲染
8.3透明度測試
用一個閥值決定
8.4透明度混合
Blend 內置的混合模式命令
Blend off 關閉混合
Blend SrcFactor DstFactor
srccolor * SrcFactor + dstcolor * DstFactor = Target
8.6.1 混合等式和參數
現在有 源顏色 S 和目標顏色 D 現在想要得到輸出顏色 O 就必須使用一個等式來計算,這個就是混合等式
我們會用兩個混合等式 一個用于混合 RGB 一個混合 A 通道 每個等式要兩個因子 一共四個因子。
中級篇
9 更復雜的光照
Forward Rendering Path、Deferred Rendering Path Vertext Lit Rendering Path
頂點照明渲染路徑:是對硬件配置要求最好 運算性能最高的
跳過。。。
10 高級紋理
10.1立方體紋理
立方體紋理是環境映射的一種實現方法
包含6張圖像 采樣的時候是用三維的坐標
使用立方體紋理的好處 實現簡單快捷 得到的效果好 缺點是 如果當場景引入了新的物體 光源 或者物體在發生移動時 我們就需要重新生成 立方體紋理 可以反射環境 但不能反射自己
10.1.1 天空盒子
windows -lighting 里面設置 skybox
10.1.2折射
折射 是用光照計算函數 然后用折射函數混合反射光
10.2渲染紋理
10.2程序紋理
11 讓畫面動起來
11.1 unity shader 中的內置變量
_Time float4 場景加載開始所經過的實際
_SinTime 正弦值
_CosTime 余弦值
unity_DeltaTime
11.2 紋理動畫
- 序列幀動畫:記住 UV 紋理坐標是左下角是原點
- 滾動的背景:修改 UV 紋理坐標 對兩張紋理取樣 然后混合