陳擎文教學網:Unity遊戲程式


資源(Resource)

chp0. 安裝unity

【chp1.object基礎練習】
範例1-1.建立物件,平移,旋轉,縮放,rigidbody,物理材質

範例1-2.建立群組物件,預鑄物件prefab

範例1-3.攝影機基本技巧(1):第一人稱視角控制器(使用FPS:First Person Controller)

範例1-4.攝影機基本技巧(2):第一人稱視角移動(使用main camera)

範例1-5.建立飄動的國旗

範例1-6.貼圖與燈光的基本操作

【chp2.c#基礎練習part(1)】
範例2-1:使用c#輸出訊息

範例2-2:(打直球保齡球)c#控制物件的旋轉與移動

範例2-3:(設定參數打彎曲旋轉保齡球)若c#宣告public變數,則變數可與面板的參數結合

範例2-4:(第一人稱視角踢足球)c#用鍵盤來控制輸入(方法1:用Input.GetKeyDown)

範例2-5:c#用鍵盤來控制輸入(方法2:用Input Manager)

範例2-6:c#的GUI界面(Graphic User Interface)

範例2-7:GUI界面:一開始就在label顯示(顯示文字,目前日期時間)

範例2-8:GUI界面:button顯示文字,button計算兩數相加(三個InputField)

範例2-9:GUI界面:兩數字if比較大小(2個inputField,一個button)

範例2-10:GUI界面:inputField直接控制改變足球轉速

範例2-11:GUI界面:inputField+button控制高爾夫入洞

【chp3.建立自然地形terrain:山地,湖泊,河流,樹木,草地,風力】
範例3-1:建立大自然地形terrain,地形貼圖

範例3-2:建立天空,建立火山(丘陵),建立湖泊,建立樹木

範例3-3:建立樹木的4種方法:terrain種樹工具,樹木生成器,風力

範例3-4:建立草地的4種方法,建立石頭方法

範例3-5:火山爆發,產生煙霧(粒子生成器),設定音效

範例3-6:鄉間小屋的虛擬實境VR導覽動畫(第一人稱導覽動畫),輸出.exe動畫

【chp4.建立可以走動的主角:角色Characters,動作Animations,動作控制器Animator Controller】
範例4-1:在大峽谷內走路跑步蹲下跳(使用standard asset之第三人視角的角色),遊戲切換場景的方法

範例4-2:讓我的主角跳街舞(用Mixamo快速建立各種角色與動作),修正匯入FBX的貼圖錯誤

範例4-3:角色種類1:用unity chan快速建立各種角色與動作(wait,win,lose,walk,run),但unity chan需要程式碼才能移動

範例4-4:角色種類2:用不需要程式碼的3D角色與動作(wait,walk),Raw Mocap不需要程式碼就能移動

範例4-5:Input Manager控制unity chan走路(但問題:無法旋轉)

範例4-6:正確鍵盤控制角色運動的第一種方法(local坐標控制:↑ ↓前進後退。 → ←控制旋轉)結合Input Manager控制walk,run,back

範例4-7:正確鍵盤控制角色運動的第二種方法(global坐標控制:↑ 往北,↓往南, →往東,←往西)結合Input Manager

範例4-8:使用UI的button控制角色動作+pose+audio(wait,win,lose,walk,run,damage,jump,slide,HANDUP,UMATOBI)

範例4-9:兩種觸發動作(撞到石頭跌倒,拿到寶物得分):OnCollision碰撞事件,OnTrigger觸發事件

【chp5.c#練習part(2)】
範例5-1:不使用public變數,來直接計算圓周長(1個inputField,一個button,一個Text)

範例5-2:不使用public變數,來直接控制球,滾進洞

範例5-3:計算碰撞得分,觸發結束比賽

範例5-4:切換場景兩個方法(按鈕切換,觸發切換)

範例5-5:對球施力移動:OnCollision碰撞事件,OnTrigger觸發事件

範例5-6:讓角色不斷進入場景內

【chp6.程式碼建立節點物件,改變節點組件參數】
6-1:程式碼建立一個新的cube物件

6-2:程式碼修改一個cube物件,材質為紅色,透明度為90(1~255)

6-3:點按一個cube物件,播放音效

6-4:一個cube物件,再程式碼隱藏

6-5:先隱藏一個cube物件,再程式碼顯示

6-6:先勾選物件的isKinematic有動力學反應,再程式碼取消動力學反應(產生真實力學)

6-7:程式碼建立的物件節點,如何自動產生某個組件,例如navMeshAgent(RequireComponent)

【chp7.滑鼠事件,觸控事件】
7-1:觸控事件的程式碼有兩種寫法

7-2:如何做『ray射線』檢測(紅外線)

7-3:如何取得射線ray,點按觸碰點的物件的資料(名稱,位置)

7-4:如何在程式碼,顯示觸控射線點位置圓圈(以淡黃色,透明100圓圈顯示)

7-5:如何觸控射線,讓角色unityChan緩動有各種動作動畫(idle,walk,jump)

7-6:複合物件(小蜜蜂)如何觸控點按能夠有反應

【chp8.節點物件的運動方法1:移動,旋轉,縮放】
8-1:如何程式碼設定一個cube的大小

8-2:移動,有兩種位移法:(1)再移動dx,(2)移動到某坐標點

8-3:移動,有兩種速度呈現法:(1)緩動,(2)瞬間移動到某坐標點

8-4:Vector有兩種:單位向量Vector3.left,new Vedtor3(2,2,0)

8-5:unity的角度有5種,unity的旋轉方式有5種

範例8-6:用幀動畫來控制直升機移動:上下、左移右移、左轉右轉

範例8-7:AddForce(單位向量)來施力讓物體移動

範例8-8:複合物件(小蜜蜂)如何觸控點按後就能向上移動1秒

範例8-9:複合物件(小蜜蜂)如何觸控點按後就以鏡頭camera垂直方向forward遠離鏡頭1秒

8-15:計算兩個物件之間的距離

【chp9.節點物件的運動方法2:緩動移動(導航網格navMesh,Time.deltaTime)】
9-1:要讓角色緩動(在一段時間內移動到目的地),有兩種方法:導航網格navMesh,Time.deltaTime

9-2:導航網格navMesh

9-3:導航網格的特殊功能1:兩點之間跳躍(等高點的跳躍)

9-4:導航網格的特殊功能2:兩點之間跳躍(高低點的跳躍)

9-5:如何修正:導航網格轉成AR(Vuforia)的錯誤:角色會浮在空中

範例9-6:實作主角膠囊在導航網格內,自由觸控移動

範例9-7:實作主角unityChan在導航網格內,自由觸控移動+動作(idle,walk,jump)

9-8:unity的導航網格無法做到移動,如何修正

9-9:導航網格的主角,如何不動就idle,特定位置則jump,否則walk

範例9-10:實作主角unityChan的極限體能王過關遊戲


【chp10.射擊遊戲,不斷生成的prefab】
10-1.如何設定怪物不斷生成產生

10-2.兩種計時器(Invoke,InvokeRepeating)與各種計時器指令

10-3.使用生成指令Instantiate,在某物件A的位置,生成新物件B

10-4.如何讓怪物monster亂數左右移動(蛇形走位)

10-5.從某個角色物件Cube-player,如何不斷發射子彈prefab

10-6.按鈕fire才開火(會飛的子彈),按鈕取消開火

範例10-7.直升機fire攻擊不斷來襲的敵機

10-8.在dx=(-30, 30)之間產生隨機亂數,移動dx位移

10-9.如何讓產生的生成物件Instantiate,在5秒後消失

10-10.在原地不斷生成怪物


【chp11.節點物件的碰撞事件1】
11-1:碰撞事件有2種處理方式:Collision碰撞,Trigger觸發

11-2:Trigger觸發碰撞事件的設定方法(最常用的碰撞方式)

11-3:如何設定碰撞時的粒子動畫效果(例如,顯示爆炸prefab)

11-4:被關卡撞到,如何顯示煙霧動畫

11-5:為什麼設定碰撞的音效,沒有出現,如何解決(子彈打到怪物播放爆炸聲音)

11-6:開啟爆炸範圍,任何進入範圍內的怪物都會被爆炸


【chp12.節點物件的碰撞事件2】
【chp13.切換場景】
13-1:切換場景的基本指令

範例13-2:遊戲失敗產生Game Over畫面,方法1:切換場景

範例13-3:遊戲失敗產生Game Over畫面,方法2:顯示圖片(隱藏的圖片,用public讀入後顯示)

範例13-4:遊戲失敗產生Game Over畫面,方法3:顯示圖片(隱藏圖片物件,用程式碼類別物件顯示)


【chp14.分數計算,記分系統】
範例14-1:呼叫另外c#檔案的show()函數顯示分數score(方法1:public拖曵設定cs程式碼掛載的物件)

範例14-2:呼叫另外c#檔案的show()函數顯示分數score(方法2:GameObject.FindObjectOfType)

範例14-3:很多怪物攻擊主角,計算同一個score變數(方法3:GameObject.FindObjectOfType)

【chp15.RPG的狀態機,主角攻擊怪物,怪物攻擊主角】
15-1:狀態機:設定角色的5種狀態

15-2:如何判斷角色的狀態是預備態IDLE

15-3:如何判斷角色的狀態是攻擊態ATTACK

範例15-4:實作enemy的四種狀態(預備idle,走路walk,攻擊attack,死亡die)

15-5:如何怪物死亡後,不再繼續自動導航追踪主角(還要設定animator狀態,設定5秒後消失)

範例15-6:兩種怪物攻擊主角,主角按炸彈來引爆炸彈


【chp36.實作打怪的3D遊戲】
範例36-1:建立3D場景(1)

範例36-2:建立主角john及其動作動畫(1)

範例36-3:用Unity動作控制器Animator Controller來設定主角john

範例36-4:建立環境,與複雜場景的地形

範例36-5:三種追踪角色的攝影機技巧:攝影機追踪法,程式碼追踪法,還Cinemachine套件追踪法)

範例6-6:遊戲結束的設定

範例36-7: 建立建立怪物及其動作動畫,寫c#程式碼控制主角joh與怪物的移動與旋轉

範例36-8:設定怪物的移動路徑(設定導航網格)

範例36-9:使用導航網格代理(NavMeshAgent),讓怪物自動行走

範例36-10:C#程式碼設定打擊的武器與子彈顯示方式

範例36-11:C#程式碼設定打擊怪物時分數計算與遊戲結束判斷

範例36-12:音效設定

範例36-13:輸出成最後的各種平台遊戲執行檔(視窗版,android版,網頁版)

【chp37.虛擬實境VR】
37-1.虛擬實境/擴增實境/混合實境(VR/AR/MR)之定義與應用

37-2.VR/AR/MR相關應用與案例介紹

37-3.技術原理(1):VR的定位追蹤機制

37-4.技術原理(2):VR的3 DoF/6 DoF、資料型態與定位技術-陀螺儀、加速度儀、影像識別與燈塔定位

37-5.技術原理(3):3D圖像基礎 ,電腦視覺基礎與三維建模

37-6.技術原理(4):虛擬實境技術的定位原理-MR、光場、立體視覺、結構光、ToF

37-7.開發實作(1):用Unity與C#程式實作:Google VR眼控互動遊戲

【chp8.擴增實境AR】
38-1.技術原理(1):AR相關技術(AR 3D物件辨識技術, AR辨識圖規劃)

38-2.技術原理(2):Vuforia Engine擴增實境引擎

38-3.技術原理(3):Vuforia Engine 電腦視覺,動態物件辨識能力

38-4.技術原理(4):Vuforia Engine的核心功能(Vuforia的圓柱識別,多目標識別,文字識別,掃描圖片識別,自訂目標識別,3D物體識別)

38-5.開發實作(1):實作Unity、c#程式與Vuforia Engine

38-6.開發實作(2):開發實作(3):AR影像識別

38-7.開發實作(3):用Vuforia + unity來製作互動AR型錄

38-8.開發實作(4):用Vuforia + unity來製作互動AR名片

38-9.開發實作(5):用Vuforia + unity來製作AR互動遊戲

【應用練習】
chp1. 安裝unity

chp2.第一個3D專案

chp3.籃球遊戲的材質貼圖

chp4.使用c#寫程式碼:在label顯示(新年快樂,計算器,目前日期時間)

chp5.使用c#寫程式碼:顯示兩數相加的結果(三個InputField)

chp6.使用c#寫程式碼:兩個數字if比較大小(2個inputField,一個button)

chp7.使用c#寫程式碼:不宣告public變數,計算圓周長(1個inputField,一個button,一個Text)

chp8.在OnGUI圖形使用者介面顯示元件

chp9.幽浮2D遊戲

chp10.幽浮3D遊戲(撿寶物遊戲)

chp11.狗狗過馬路3D遊戲

chp12. 第一人稱射擊遊戲

chp13. 遊戲場景中水特效及粒子動態效果

chp14.靜態場景光照效果的強化技術巧

chp20. 遊戲腳色的導入動畫系統與應用

chp21. 導航網格路徑搜尋


資源
  上課程式碼即時貼網站 線上黑板( Online blackboard) 上課即時貼(guestBook) 有道翻譯
  unity package物件 man木頭人 stamp印章 3D樹木
  unity package物件 爆炸prefab動畫(WFX_Nuke) 爆炸音效(nuclear_explode_aduio) enemy角色下載(Battle Wizard Poly Art) Effect textures and prefabs(煙霧動畫prefabs物件)asset store
  unity package物件 直升機的asset store 敵機的asset store 各種爆炸火焰煙霧的粒子動畫asset store Effect textures and prefabs(煙霧動畫prefabs物件)asset store
  audio 揮擊木棍聲音(Whoosh) 過關成功聲音(win) 氣化聲音(hiss) 各種爆炸音效
  unity terrain貼圖 terrain貼圖
  鍵盤控制物體移動程式碼 input.getkeydown控制物體運動的4組動作txt程式碼 input manager 控制物體運動的6組動作txt程式碼 input manager 控制物體眼睛攝影機上下旋轉的1組動作txt程式碼
  鍵盤控制角色運動的方法1(local坐標控制:↑ ↓前進後退。 → ←控制旋轉) 鍵盤控制角色運動的方法2(global坐標控制:↑ 往北,↓往南, →往東,←往西)
3D素材資源 unity asset store https://www.unityfly.com/ 2D素材商店:craftpix 2D,3D遊戲素材商店:GDM:gamedevmarket
free3d TurboSquid unitylist Mixamo 3D角色
音效sound effect samplefocus(簡單容易使用免費) YouTube音效庫(簡單容易使用免費) findsounds(簡單容易使用免費) free sounds library
findsounds mixkit音效(1/5免費) 遊戲音效 sound jay(沒有查詢)
YouTube音效庫 小森平的免費下載音效(沒有查詢) 日文音效-Sound Effect Lab免費音效下載網站 素材吧(簡體中文)
unity c#常用方法 unity 常用方法 unity 常用方法 Unity Script 常用語法教學 unity C# 語法入門
unity 手冊 UNITY3D中文手册 UNITY參考手册 UNITY組件手册 UNITY腳本手册
unity 教學資源 unity教學 阿發教學 unity從小白到超神-youtube沒有c# 【極客學院】unity 3D教學入門
>最全unity3D教學 韓老師unity教學 最簡單Unity零基礎 unity入門,進階,高級,保姆級
>**Unity 2D平臺跳躍遊戲開發全教程(1-50) **Unity官方認證教程:3D RPG系列課程介紹 **Unity 2D 遊戲入門教程-Beginner Tutorial
>3D unity工程師的獨立遊戲開發教學 unity零基礎從小白到專業 【千鋒合集】最全Unity3D全套 整合整合Unity官方教程設計最佳學習路線
最全Unity教程
2D >unity2D入門 Unity2D官方入門教程:Ruby' Adventure unity零基礎一小時快速入門 unity零基礎開發卡牌遊戲教程
  unity unity簡介影片 snap軟體    
  學生畢業專題 110學年學生畢業專題 @幽靈獵人:第一人稱視角(unreal) @PeaceCleaner(2D unity) @彈珠台:霧界彼方(3D unity)
  @地心鐵男:under dog(2D unreal,必須有搖桿) @極菌 X Plague(2D unity,apk,安卓手機) @幻世之旅(unreal) @Aries顏色(2.5D unity)
  愛永不放棄(unreal) dark element(2D unity) 嘴砲少年家(2D unity) 尋境傳説(2D unity)
  @實驗室(3D unity)
  Goole輸入法(Input:exe) Goole 輸入法(Input:zip) 畢業門檻(Graduation threshold) 2018通識課規定
 

 
chp1.安裝unity

安裝各種版本

1.參考:unity的安裝教學影片:
安裝unity
安裝unity1
安裝unity2
安裝unity3
登入unity4
新增unity project5
unity 視窗排列6

2.注意:不要下載最新的unity,因為新版還不成熟,較不穩定。
但是:unity新版可以向下兼容,可以打開舊版的檔案,但是舊版無法打開新版檔案
所以也不要用太舊版的
(1)☎建議下載LTS版本:LTS = Long-Term Support = 長期維護版
☎版本:選擇f版本,f是穩定版,例如:2020.2.4.f1
☎建議下載Final版本
(2)專案開發版本,推薦選擇:LTS。
(3)如果需要使用新功能,可酌情考慮Final。
(4)需要修復bug,可適當升級Patch。

3.各種版本說明:
(1)Final:最終版。
當前時間的一個最終版本。
一般大的功能跨度都是在年度版本進行更新。

(2)LTS:長期穩定支持版 。
LTS版本不會有新的任何功能,API變更或改進。
適用于正在開發以及已有發佈的開發者,
每年最後一個TECH版本會成為Unity LTS穩定支持版。

(3)TECH:技術前瞻版。
Unity TECH版本適合想要使用最新版Unity的用戶。

(4)Patch:補丁版。
針對當前版本所存在的Bug進行一個修復。。

(5)Beta:外部測試版。

(6)Alpha:預覽版,內部測試版。
此版本提供最新功能的早期試用,和Beta版相比,Alpha版有較大的穩定性風險。

4.安裝方法1(自動法):下載官網的Unity Hub(64bit版軟體)
(1)安裝三步驟:
A. Download the Unity Hub
B. Choose your Unity version
C. Start your project
官網下載unity Hub
選擇:Download for Windows

選取First-time users:Start here

5.安裝方法2(手動選擇版本法):下載官網的舊版Unity Archive
官網下載舊版unity LTS
官網下載舊版unity Archive(全部版本)
注意:如果你已經安裝的版本是很久的舊版編輯器,要如何更新?
(1)☎☎要先更新unity Hub版本
(2)再下載新的LTS版本(f1)
注意:用舊版的unity hub,是無法成功下載新的unity版本的

6.執行unity必須要login帳號:
(1)可以用facebook,google帳號登入

7.Unity的License Management
(1)免費版,要選擇:personal
(2)付費版(要商業化):選擇plus,pro

8.Unity的版權授權:
unity的授權只有2天, 超過了,要再重新授權一次

9.安裝visual studio 2019
(1)可以到微軟官網下載visual studio 2019
https://visualstudio.microsoft.com/zh-hant/vs/
安裝時,在visual studio installer勾選『使用unity進行遊戲開發』
(若是已經安裝vs 2019者,則重新執行visual studio installer➜勾選『使用unity進行遊戲開發』)
https://docs.microsoft.com/zh-tw/visualstudio/cross-platform/getting-started-with-visual-studio-tools-for-unity?view=vs-2019
https://www.youtube.com/watch?v=DL96YoqGhuc

(2)在unity裡面,設定連接到visual studio 2019
Edit➜Preferences➜External Tools➜External Script Editor➜
➜C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.exe
➜選visual studio 2019

10.注意:
(1)授權:選擇:unity個人版
(2)版本:LTS: long time support長期為維護
alpha:測試版
(3)版本:選擇f版本,f是穩定版,例如:新增2020.2.4.f1
(4)unity的授權只有2天, 屆時要再重新授權一次
(5)unity的語言盡量不要選繁體中文,選english
(6)新增專案時,路徑location:不要有中文
(7)新增c# script在asset裡面建立資料夾folder = script

11.登入unity的視窗排列方式:
(1)主要有5種:2by3, 4 split,default,Tall,Wide
調整方式:Window➜Layout

 
基礎部分:
chp1-1.建立物件,平移,旋轉,縮放,rigidbody,物理材質

範例1-1

範例1-1:建立三個可以彈跳的物件
專案成果圖片
下載本project成果檔案
1.重點:
(1)常用基本指令:
平移視窗:滑鼠中鍵
旋轉視窗:Alt+滑鼠左鍵
平移視窗:Alt+滑鼠中鍵
縮放視窗:Alt+滑鼠右鍵
複製物件:Ctrl+D
以場景視角當作攝影機視角:Ctrl+Shift+F
把物件置於場景中央且放大:double click該物件
(2)進階指令:
把目前場景視角,當作攝影機main camera的視角:ctrl+shift+F
把目前選取物件放大置中(1):在hirerachy:double click物件
把目前選取物件放大置中(2):在場景內:按F(fixed固定)
微調視窗:滑鼠右鍵鍵→出現眼睛+鍵盤符號→按wasd→上下左右移動

(3)設定物理物件有兩個要素:
_1.設定物件上剛體rigidbody(會有重力效果)
_2.設定物件的碰撞物件參數physics material(會有彈跳效果)
(3)常見材質的物理參數:
(4)金屬metal Dynamic Friction=0.25
static Friction=0.25
bounciness=0
friction combine = Avg
bounce combine =Avg
(5)木頭wood Dynamic Friction=0.45
static Friction=0.45
bounciness=0
friction combine = Avg
bounce combine =Avg
(6)橡膠rubber Dynamic Friction=1
static Friction=1
bounciness=0
friction combine = maximun
bounce combine =Avg
(7)彈跳球bouncy Dynamic Friction=0.3
static Friction=0.3
bounciness=1
friction combine = Avg
bounce combine =maximun
(8)冰ice Dynamic Friction=0.1
static Friction=0.1
bounciness=0
friction combine = multipy
bounce combine =multipy

2.建立物件:
plane
cube
成果圖片

3.注意:xyz軸的顏色=RGB(red,green,blue)
注意:高度不是z軸,高度是y軸(green)

4.unity基本操作:
(1)快速鍵盤:
平移視窗:滑鼠中鍵
旋轉視窗:Alt+滑鼠左鍵
平移視窗:Alt+滑鼠中鍵
縮放視窗:Alt+滑鼠右鍵
複製物件:Ctrl+D
Q,W,E,R,T:平移視窗,位移物件,旋轉物件,縮放,矩形工具

5.建立2個平面plane,兩個cube,一個膠囊capsule
成果圖片

6.設定攝影機camera視角
成果圖片

7.測試結果play

8.建立顏色材質
(1)先在asset裡面建立mat目錄(folder)
+新增一個material
改名字:red
設定顏色=red

(2)複製兩個材料(Ctrl+D)
改名字:green
設定顏色=green
改名字:blue
設定顏色=blue
成果圖片

(3)拖曵材質到指定物件

9.給定重力gravity效果
方法:設定為剛體rigidbody則可以有重力效果
方法:選定cube物件後→add component→physics→rigidbody
play
成果圖片

10.設定物件有彈跳球的物理特性
(1)先在asset裡面建立mat目錄(folder)
+新增一個physics
改名字:ball
成果圖片

(2)設定physics property
Dynamic Friction=0.3
static Friction=0.3
bounciness=1
friction combine = Avg
bounce combine =maximun
成果圖片

(3)設定cube物件有彈跳球的物理屬性
選cube物件→在cube collider項目→拖曵ball物理材質到material裡面

play
成果圖片

 
chp1-2.建立群組物件,預鑄物件prefab

範例1-2

範例1-2:建立建立群組物件,預鑄物件prefab
成果圖片
下載本project成果檔案
1.重點:
(1)群組物件:把很多物件放入一個empty物件(一個群組物件)
(2)預鑄物件prefab:把物件放入資源asset,就可以隨時拖曵到場景,變成相關的父子物件
(3)若要群組物件的物理反彈參數,要每個元素都給定,不能只給定群組主物件

2.建立物件:
plane
在世界中心原點建立一個cube(頭部)

3.變換layout(右上角)
從default,換成2 by 3
(上下兩個視野,下方是攝影機視角)
4.複製cube(身體)
把cube縮小(按住中央是三軸等距縮放)
5.複製cube(脖子)
把cube縮小(按住中央是三軸等距縮放)
6.複製cube(脖子)成為2個腳
把cube變長(按住中央是三軸等距縮放)
7.複製cube(腳)成為2個手
稍微旋轉(用內圈)
成果圖片

8.建立顏色材質
(1)先在asset裡面建立mat目錄(folder)
+新增一個material
改名字:red
設定顏色=red
成果圖片

9.建立群組物件(父子物件)
建立空物件:creat Empty (GameObject)
把全部的cube都拖曵到GameObject
移動GameObject,則全部一起移動
成果圖片

10.建立預鑄物件prefab
把GameObject拖曵到Assets
再把在assets裡面的GameObject,拖曵到主場景,形成多個子物件
成果圖片

11.改變預鑄物件prefab的內容(把身體改成黃色)
在material目錄裡面:+新增一個material
改名字:green
設定顏色=green
把green拖曵到一個物件的肚子
點選這個GameObject→屬性面板設定→prefab:apply all
成果圖片

12.在Hierachy裡面,藍色的物件就是預鑄物件的子物件

13.如何讓一個GameObject具有物理特性(重力)
觀念:子物件的物理特色無法繼承父物件
觀念:必須在子物件裡面,每一個都去設定物理特性
(1)把GameObject(2)抬高,
設定GameObject(2)→add component→rigidbody剛體
play
結果:可以重力落下
(2)讓物體碰撞時有彈性
在asset裡面建立目錄(folder)
+新增一個physics
改名字:ball
設定physics property
Dynamic Friction=0.3
static Friction=0.3
bounciness=1
friction combine = Avg
bounce combine =maximun
(3)選取GameObject(2)→add component→box collider
(4)選GameObject(2)→在box collider項目→拖曵ball物理材質到material裡面
play
結果:無法彈性
原因:子物件的物理特色無法繼承父物件
(5)改善:shift全選GameObject(2)裡面所有的cube子物件→在box collider項目→拖曵ball物理材質到material裡面
成果圖片
play
結果:有彈性
(6)設定三個gameOject都有彈性(要顯示rigidbody剛體重力效果)

14.把已經做好的預鑄物件輸出成package
(1)在assets→GameObject→export package→export→man01
成果圖片
(2)測試是否可行
先關閉unity
重新開啟unity→開始新專案project
在assets→import package→man01
抬高,讓它重力落下
play
結果:無法重力落下彈跳
原因:當初沒有在asset裡面設定rigidbody與彈跳物理屬性(當初是在scene裡面設定)

 
chp1-3.攝影機基本技巧(1):第一人稱視角控制器(使用FPS:First Person Controller)

範例1-3

範例1-3:chp1-3.攝影機基本技巧(1):第一人稱視角控制器(使用FPS:First Person Controller)
專案成果圖片
下載本project成果檔案

第一人稱射擊遊戲(First-person shooter,簡稱FPS)是以玩家的第一人稱視角
1.建立物件:plane
點選top view(y):
變換layout(右上角)
從default,換成2 by 3

2.讀入已經做好的man01
下載man01
在assets→import package→man01
拖曵10多個man01預鑄物件
成果圖片

3.讓10個main從高空重力落下,彈跳
設定10個main→add component→physics→rigidbody
在asset新增→physics material→ball→彈跳球屬性:0.3,0.3,1,max
設定10個main→box collider
設定10個main 的每個子元件→box colliderd的material→ball

4.使用第一人稱視角(FPS = First Person Controller)
(1)unity以前有提供FPS的功能,但是在2018年以後,untiy就移除了FPS的功能(還有很多功能都被移除)
(2)現在如何下載使用:
這些被移除的功能,可以在asset store裡面找到
Just download and import it from standard assets or from the asset store
方法:到asset store
輸入搜尋:standard assets
設定price=0的過濾條件
成果圖片
成果圖片
download
import
成果圖片

(3)import後如何使用
在assets裡面→standand asset目錄→Characters→FirstPersonCharacter
找預鑄物件→Prefabs:FPSController.prefab
把這個FPS預鑄物件拉到場景scene
成果圖片
play
結果:出現錯誤:compiler errer
原因:SimpleActivatorMenu.cs有某些指令錯誤無法執行

(4)如何改善錯誤:
使用visual studio net 打開cs檔案
C:\Users\TA312\exp1-2\Assets\Standard Assets\Utility\SimpleActivatorMenu.cs
成果圖片
把以下三行前面加上://
//public GUIText camSwitchButton;
//camSwitchButton.text = objects[m_CurrentActiveObject].name;
//camSwitchButton.text = objects[m_CurrentActiveObject].name;
成果圖片

測試,結果:可以正常使用
使用上下左右鍵(前後左右移動)
也可以用滑鼠(向上看)
成果圖片

測試
First Person Controller
3rd Person Controller

 
chp1-4.攝影機基本技巧(2):第一人稱視角移動(使用main camera)

範例1-4

chp1-4.攝影機基本技巧(2):第一人稱視角移動(使用main camera)
專案成果圖片
下載本project成果檔案
1.建立物件:plane
點選top view(y):
scale:放大
變換layout(右上角)
從default,換成2 by 3

2.讀入house免費物件:
到asset store
輸入搜尋:girl
設定price=0的過濾條件
成果圖片
download,load
在assets→House_of_Color_C_Green/Prefabs→拖曵House_of_Color_C_Green到場景內

3.讀入girl免費物件:
到asset store
輸入搜尋:girl
設定price=0的過濾條件
成果圖片
download,load
在assets→Cattleya/prefabs→拖曵HclothingSet_04_And_nackedSet到場景內
拖曵girl預鑄物件到場景的樓梯處,準備讓其跌倒
成果圖片

4.設定girl物件的兩個物理屬性(錯誤做法)
(1)重力效果:設定girl物件:clothingSet_04_And_nackedSet→add component→physics→rigidbody
(2)相撞的彈跳效果:設定clothingSet_04_And_nackedSet→add component→physics→mesh collider
在asset新增→physics material→ball2→彈跳球屬性:0.3,0.3,1,max
設定girl物件:clothingSet_04_And_nackedSet→mesh colliderd的material→ball2
結果:會一直向下落下keep falling

5.設定girl物件的兩個物理屬性(正確做法)
(1)重力效果:設定girl物件:clothingSet_04_And_nackedSet→add component→physics→rigidbody
(2)相撞的彈跳效果:設定clothingSet_04_And_nackedSet→add component→physics→box collider
在asset新增→physics material→ball2→彈跳球屬性:0.3,0.3,1,max
設定girl物件:clothingSet_04_And_nackedSet→mesh colliderd的material→ball2
結果:會與樓梯碰撞而上下彈跳
成果圖片

(重要觀念):
(1)從外部匯入import的物件(3ds max, assets store),盡量不要設定mesh collider,因為mesh collider容易出問題,會讓物體持續落下)
(2)匯入import的物件,要盡量設定為primitive colliders
(3)primitive colliders包括三種: Box Collider, Sphere Collider, and Capsule Collider
(4)設定為primitive colliders,就會有比較準確的collider 物理反彈效果。
成果圖片

6.(其它測試)讀入已經做好的man01
下載man01
在assets→import package→man01
拖曵man01預鑄物件到場景的樓梯處,準備讓其跌倒

7.調整攝影機的視野大小:
選取main camera
在右邊屬性視窗→Field of View→改變視野大小(預設60度)

5.把main camera拖曵到設定girl物件clothingSet_04_And_nackedSet裡面,變成子物件
(1)把main camera移動到眼睛的位置
(2)在main camera的屬性面板→rotation→x=-180, z=-180
成果圖片
測試結果play:會以第一人稱視角,跟著girl跌倒,看到整個過程

 
範例1-5.飄動的國旗

範例1-5

範例1-5.飄動的國旗
專案成果圖片
下載本project成果檔案

0.觀念:
物理材料:剛體rigidbody,布料cloth

1.建立布料
建立物件:plane
建立紅色材質
top view
修改成矩形

2.設定plane為布料物理材質
add component→phsics→cloth
成果圖片
取消:mesh collider

3.設定布料無法移動的位置
點選 edit constrain
出現網格點
選取上面兩列的網格點

在cloth constrain小視窗
select:上面兩排grid point
勾選:max distance=0(確定這兩列不會移動)
成果圖片
測試play

4.下載國旗
到google,輸入:國旗
下載圖片

5.把圖片拉到unity的asset
再把asset裡面的圖片,拖曵到plane
測試play
結果:國旗顛倒了
成果圖片

6.開啟photoshop
讀入國旗檔案
影像→影像旋轉→180度
成果圖片
存檔→檔案→另存新檔→flag2.png

7.把圖片flag2.png拉到unity的asset
再把asset裡面的圖片,拖曵到plane
測試play

結果:飄動的國旗
成果圖片

 
chp1-6.貼圖與燈光的基本操作

範例1-6

chp1-6.貼圖與燈光的基本操作
成果圖片1成果圖片2
下載本project成果檔案
1.重點:unity的燈光有三種:
平行光(directional light):太陽光,月光
點光源(point ligtht):燈泡,爆炸
聚光燈(spot light):手電筒,車燈

2.建立一個有四面牆的房間
(1)建立物件:plane
(2)複製plane,翻轉180度,當作屋頂
(注意,plane的貼圖,下面沒有貼圖,沒有辦法看到面,所以要翻轉180)
(rotation,z=-180)
(3)複製plane,當作三面牆壁
(注意:plane預設是10x10)
(4)變換layout(右上角)
從default,換成2 by 3

3.讀入已經做好的man01
下載man01
在assets→import package→man01
拖曵三個man01預鑄物件
成果圖片

4.牆壁貼圖
到google搜尋tile或brick或wallpaper
長寬最好是2的n次方例如:256x256(unity會用2^n方運算)
下載jpg檔,然後拖曵到assets裡面

5.建立顏色材質
(1)先在asset裡面建立mat目錄(folder)
+新增一個mat
改名字:wall
拖曵到設定顏色前方的框框內
(2)設定貼圖縮放比率=titling(x,y)
(在x的前方有箭頭出現,即可拖拉改變數字)
成果圖片

6.燈光的應用
7.平行光(directional light):自然的環境光
(1)把directional light移動到室外,一樣有環境光
(2)取消directional light
在右邊屬性面板,取消勾選:light
結果:環境變黑
(3)參數
color光顏色
intensity強度
shadow type影子

8.在牆壁加上壁燈(點光源)
取消directional light(不勾選)
在hierachy→create→light→point light
移動位置:在牆壁上接近天花板
color光顏色:黃色
intensity強度:4.5
複製個壁燈
設定不同位置,不同顏色
成果圖片

9.加上三個spot light照射人物
調整角度
調整intensity=40
成果圖片

10.調整讓房間不會那麼暗:
選擇兩個point light
改變range參數,調大
結果:變得比較亮
成果圖片

10.使用第一人稱視角(FPS = First Person Controller)
(1)unity以前有提供FPS的功能,但是在2018年以後,untiy就移除了FPS的功能(還有很多功能都被移除)
(2)現在如何下載使用:
這些被移除的功能,可以在asset store裡面找到
Just download and import it from standard assets or from the asset store
方法:到asset store
輸入搜尋:standard assets
download
import

(3)import後如何使用
在assets裡面→standand asset目錄→Characters→FirstPersonCharacter
找預鑄物件→Prefabs:FPSController.prefab
把這個FPS預鑄物件拉到場景scene
play
結果:出現錯誤:compiler errer
原因:SimpleActivatorMenu.cs有某些指令錯誤無法執行

(4)如何改善錯誤:
使用visual studio net 打開cs檔案
C:\Users\TA312\exp1-2\Assets\Standard Assets\Utility\SimpleActivatorMenu.cs
把以下三行前面加上://
//public GUIText camSwitchButton;
//camSwitchButton.text = objects[m_CurrentActiveObject].name;
//camSwitchButton.text = objects[m_CurrentActiveObject].name;

測試,結果:可以正常使用
使用上下左右鍵(前後左右移動)
也可以用滑鼠(向上看)
成果圖片
成果圖片

 
基礎部分:範例2-1:使用c#輸出訊息

範例2-1

專案成果圖片
下載本project成果檔案
範例2-1:使用c#輸出訊息

1.unity的互動程式碼可以用c#,javascript,但用C#最為推薦
2.unity所提供的sciprt指令手冊:在help→script reference
3.要設定scipt直接開啟c#,方法:Edit→preference
4.start()程式執行開始就會執行一次的函數
update()程式執行中,每隔//60秒就會執行一次的函數
(因為遊戲動畫的每秒60個frame)
5.輸出訊息(在console面板輸出)
指令1:pirnt()
指令2:Debug.Log()
6.建立c#程式碼的兩個步驟
步驟1:先在assets裡面建立c#
步驟2:把c#程式碼,綁定到hierachy裡面的物件
7.範例:
(1)在assets裡面建立folder:script
(2)建立test01.c#
start()
{
print("begin程式開始執行一次")
}

update()
{
print("每隔//60秒就會執行一次")
}
(3)把test01.c#綁定到Main Camera
成果圖片
(4)play
看console視窗

8.重點:
(1)unity所有類別物件,都是繼承自MonoBehaviour()
(2)幾個重要的函數
awake():場景建立後就會執行awake()
start():update()函數執行前,就會被執行一次的起始函數
update():每隔//60秒就會執行一次的函數
成果圖片

 
範例2-2:(打直球保齡球)c#控制物件的旋轉與移動

範例2-2

成果圖片成果圖片
下載本project成果檔案
範例2-2:c#控制物件的旋轉與移動

1.相關函數:在Transform類別裡面的兩個函數
(1)Translate(float x, float y, float z, Space relativTo=Space.Self)
(2)Rotate(float xAngle, float yAngle, float zAngle, Space relativTo=Space.Self)
這兩個函數的使用方法,可以開啟使用手冊
unity所提供的sciprt指令手冊:在help→script reference
查詢:transform
看教學範例transform.Translate()
https://docs.unity3d.com/ScriptReference/30_search.html?q=transform
https://docs.unity3d.com/ScriptReference/Transform.Translate.html
(3)注意:參數
_(A).旋轉角 = 度
_(B).Space.Self是一自己軸心做旋轉,
Space.World是一世界軸心做旋轉,

2.範例目的:把一個cube,每隔1/60秒移動x軸0.01,z軸旋轉1度
3.建立兩個cube,設定兩個顏色材質
3.程式碼:建立roate01.c#
void update()
{
transform.Translate(0.01f,0,0,Space.Self);
transform.Rotate(0,0,1.0f);
}
注意:
0.01的資料形態=double
0.01f的資料形態=float

7.製作兩個足球,籃球
(1)在hierachy場景裡面建立兩個3D物件:shpere01,shpere02
(2)下載足球,籃球的貼圖
到goole的chrome,輸入關鍵字:unity football texture
下載png圖檔
成果圖片
到goole的chrome,輸入關鍵字:unity basketball texture
下載png圖檔
把png圖檔,拖曵到asset裡面
(3)建立材質material
在asset裡面,新增material,命名=texture01
把足球.png拖曵到texture01材質的右邊inspector屬性視窗,設定顏色前方的框框內
(4)再把texture01材質,拖曵到shpere01裡
成果圖片
(5)同理,建立texture02材質,再把材質拖曵到shpere02裡

8.寫c#程式,讓足球籃球,原處旋轉
(1)程式碼:建立roate01.c#
目標:讓球沿著y軸旋轉
void update()
{
transform.Rotate(0,1,0);
}
注意:
unity只能夠處理float數字:0.1f(資料形態=float)
unity無法處理double數字:0.1(資料形態=double)

(2)程式碼:建立roate02.c#
目標:讓球沿著x,z軸旋轉
void update()
{
transform.Rotate(1,0,1);
}
(3)把c#程式roate01.c#拖曵到shpere01
把c#程式roate02.c#拖曵到shpere02
成果圖片

9.讀入已經做好的man01
下載man01
在assets→import package→man01
拖曵7個man01預鑄物件到場景plane的前方,不可以互相接觸,排成像保齡球的排列
成果圖片成果圖片

10.建立第三個足球,讓它向前移動
(1)在hierachy場景裡面建立3D物件:shpere03
(2)再把football材質,拖曵到shpere03裡
(3)寫c#程式,讓足球向z軸運動
建立tanslate01.c#
void update()
{
transform.Translate(0,0,0.07f,Space.Self);
}

(4)把c#程式tanslate01.c#拖曵到shpere03
結果:球無法撞到man,會穿透
成果圖片
原因:兩個物體相撞,必須要有一個是rigidbody,才有碰撞效果
方法:把shpere03設定為rigidbody
結果:即可相撞

11.對準足球shpere03,讓它向前移動,看看可以撞倒幾個?
成果圖片

 
範例2-3:(設定參數打彎曲旋轉保齡球)若c#宣告public變數,則變數可與面板的參數結合

範例2-3

成果圖片成果圖片成果圖片成果圖片
下載本project成果檔案
範例2-3:若c#宣告public變數,則變數可與inspector面板的參數結合
1.下載上一章的範例來做修改
下載上一章的範例
如何讀進已經存在的檔案:
成果圖片
結果:
成果圖片
2.觀念:
若c#宣告public變數,則變數可與inspector面板的參數結合
例如:
float xmove = 0.01f;
float xrotate = 1.0f;

2.調整camera的視角,改成上視圖
方便觀察曲球的路徑
成果圖片
3.新增程式碼:curve01.c#
//設定每次的x位移量,旋轉角度
public float xmove = 0.01f;
public float yrotate = 1.0f;
void update()
{
transform.Translate(xmove,0,0);
transform.Rotate(0,yrotate,0);
}
成果圖片

3.把curve01.c#綁定到Sphere03
4.檢查Sphere03的inspector面板
結果:多出兩個參數
xmove
yrotate

測試:從面板需改參數,觀察結果
成果圖片
成果圖片
**注意:若是球會亂跳,這是因為球的material屬性中,要設定摩擦力friction=0,設定彈跳係數bounciness=0

5.以移動速度,旋轉速度來設定變數
(1)觀念:
位移量 = 移動速度 * deltTinme
旋轉量 = 旋轉速度 * deltTinme

(2)修改程式碼:curve01.c#
//設定每次的x位移量,旋轉角度
float xspeed = 0.01f;
float yrotatespeed = 1.0f;
void update()
{
transform.Translate(xspeed*Time.deltaTime,0,0,Space.Self);
transform.Rotate(0,0,yrotatespeed*Time.deltaTime);
}

3.把curve01.c#綁定到Sphere03
成果圖片

 
範例2-4:(第一人稱視角踢足球)c#用鍵盤來控制左右移動,左右轉動(方法1:使用Input.GetKeyDown())

範例2-4

成果圖片
下載本project成果檔案
程式碼(WSAD鍵,←↑→↓鍵後左右移動,LR鍵左右轉動視角)
範例2-4:c#用鍵盤來控制印章,前後左右移動,左右轉動(方法1:使用Input.GetKeyDown())
1.觀念:
(1)Input Manager是對鍵盤,滑鼠.,手把,G-sensor(陀螺儀)..的管理模組
管理:Edit→project settiing→Input
(2)鍵盤的控制指令
GetKeyDown():按鍵被按下
GetKey():按鍵被一直按住時
GetKeyUp:按鍵被按住放開時

例如:
if(Input.GetKeyDown(KeyCode.A) print('A被按下')
if(Input.GetKey(KeyCode.A) print('A被一直按住')
if(Input.GetKeyUp(KeyCode.A) print('A被放開')

2.建立一個大平面plane(20x20),給定顏色
(1)建立一個印章(組合物件)
建立cube
建立cylinder
建立sphere
建立Create Empty物件,
把cube,cylinder,sphere拖曵到Empty物件內(改名stamp)
成果圖片

(2)下載木材的貼圖
到goole的chrome,輸入關鍵字:unity wood texture
下載wood.png圖檔
成果圖片
把png圖檔,拖曵到asset裡面
(3)建立材質material
在asset裡面,新增material,命名=wood01
把wood.png拖曵到wood01材質的右邊inspector屬性視窗,設定顏色前方的框框內
(4)再把wood01材質,拖曵到stamp裡
成果圖片

3.程式碼:建立move01.c#
void update()
{
if(Input.GetKeyDown(KeyCode.A) print('A被按下');
if(Input.GetKey(KeyCode.A) print('A被一直按住');
if(Input.GetKeyUp(KeyCode.A) print('A被放開');
}

4.把move01.c#拖曵到stamp
5.測試,
要先在screen視窗點按一下,再按A,才會有反應

6.寫程式碼,用WSAD鍵,←↑→↓鍵,來控制印章前後左右移動,用LR鍵來控制左右轉動視角
程式碼:move01.c#
成果圖片
txt程式碼
void update()
{
//WASD移動
if(Input.GetKeyDown(KeyCode.A)
{
this.transform.Translate(-1, 0,0);
}

if(Input.GetKeyDown(KeyCode.D)
{
this.transform.Translate(1, 0,0);
}

if(Input.GetKeyDown(KeyCode.W)
{
this.transform.Translate(0, 0,1);
}
if(Input.GetKeyDown(KeyCode.S)
{
this.transform.Translate(0, 0, -1);
}
//←↑→↓移動
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
transform.Translate(-1, 0, 0);
}
if (Input.GetKeyDown(KeyCode.RightArrow))
{
transform.Translate(1, 0, 0);
}
if (Input.GetKeyDown(KeyCode.UpArrow))
{
transform.Translate(0, 0, 1);
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
transform.Translate(0, 0, -1);
}
//左右轉動視角
if (Input.GetKeyDown(KeyCode.L))
{
transform.Rotate(0, -15, 0);
}
if (Input.GetKeyDown(KeyCode.R))
{
transform.Rotate(0, 15, 0);
}
}
7.建立第一人稱視角FPS
(1)把攝影機main camera拖曵到stamp裡面
(2)測試:前後左右移動,左右轉動印章,以FPS視角移動
成果圖片

 
範例2-5:c#用鍵盤來控制輸入(方法2:使用Input Manager)

範例2-5

專案成果圖片1圖片2圖片3
下載本project成果檔案
input manager 控制物體運動的6組動作txt程式碼
input manager 控制物體眼睛攝影機上下旋轉的1組動作txt程式碼
寫(前後左右,左轉e,右轉r,跳space,向上看t,向下看q)
input.getkeydown控制物體運動的4組動作txt程式碼
範例2-5:c#用鍵盤來控制輸入(方法2:使用Input Manager)
1.觀念:
(1)控制物件移動需要設定7組基本動作控制程式:
_A.水平x移動:Horizontal
_B.前後z移動:Vertical
_C.上下y移動:Jump
_D.左右y轉動:Rotate
_E.滑鼠水平x移動:MouseX
_F.滑鼠前後z移動:MouseZ
_G.眼睛攝影機上下x轉動:eyeRotate(另外獨立c#程式)

(2)unity控制物件移動有兩種方法:
_A.Input.GetAxis法:建議用這個Input Manager方法,因為程式碼少(可同時考慮正負值),可以反映你按下鍵盤的力道
_B.Input.GetKeyDown法:不建議這個方法

(3)Input Manager是對鍵盤,滑鼠.,手把,G-sensor(陀螺儀)..的管理模組
界面管理:Edit→project settiing→Input
預設有18種鍵盤滑鼠控制鍵
(4)常用的設定控制鍵(水平,垂直移動):
horizontal水平軸想的控制指令
Vertical垂直軸想的控制指令
預設上下左右鍵:WS,AD
預設上下鍵:WS(↑↓)
預設左右鍵:AD(及←→)
例如:
negative button = ←
positive button = →
Alt negative button(第二備用鍵) = A
Alt positive buttonn(第二備用鍵) = D
left:代表這左箭頭,以及a鍵,
right:代表右鍵頭以及d鍵

(5)觀念:Input.GetAxis("Horizontal")會傳回一個按鍵訊號強度值
範圍:-1~1的浮點數
功用:若為負值,則可以讓它反向移動
功用:若為正值,則可以讓它正向移動
當按下positiv按鈕時,傳回的浮點數會往+1慢慢移動。
當按下negative按鈕時,傳回的浮點數會往-1慢慢移動。
Gravity:按下後回复恢復的力道=10
(6)四個常用參數 參數設定說明影片:
_(A).gravity:代表的是放開按鈕時,傳回的浮點數往0移動的速度。
重力代表向下,代表按鈕放開後,訊號值回到地板0地方速度
3~0.1:放開按鈕後,浮點數緩慢到0,越小越慢
3~100:放開按鈕後,浮點數迅速到0,越大越快
_(B).sensitivity:代表的是按下按鈕時,傳回的浮點數增加或減少的速度
敏銳度代表反應,代表按鈕按下時,往興奮度最大值的速度
3~0.1:按下按鈕後,浮點數緩慢到0,越小越慢
3~100:按下按鈕後,浮點數迅速到0,越大越快

(7)18個預設控制功能,就是18個Axis
每個控制項目,就是一個Axis(有其軸心名稱)
程式碼控制時,乃是取得軸心axix的值
例如:
if(Input.GetAxis("Horizontal")!=0)//不等於0,表示有水平輸入訊號
{
//輸出按鍵訊號強度值
print("輸出按鍵訊號強度值" + Input.GetAxis("Horizontal")));
//根據按鍵訊號強度值,來進行水平方向的正負方向移動
this.transform.Translate(Input.GetAxis("Horizontal", 0,0,);
}
else if(Input.GetAxis("Vertical")!=0)//不等於0,表示有垂直輸入訊號
{
//輸出按鍵訊號強度值
print("輸出按鍵訊號強度值" + Input.GetAxis("Vertical")));
//根據按鍵訊號強度值,來進行垂直方向的正負方向移動
this.transform.Translate(Input.GetAxis("Vertical", 0,0,);
}

1.下載上一章的範例來做修改
下載上一章的範例
2.建立兩個stamp prefabs
目的:一個是getkeydown,一個是getAxis,比較差別
成果圖片
3.在stamp01寫程式碼:move01.c#
寫getkeydown(前後左右,左轉e,右轉r,跳space,向上看t,向下看q)
txt程式碼

4.在stamp02寫程式碼:move02.c#
寫getAxis(前後左右,左轉,右轉,跳,向上看,向下看,滑鼠x,滑鼠y,滑鼠中鍵向上看)
input manager 控制物體運動的6組動作txt程式碼
input manager 控制物體眼睛攝影機上下旋轉的1組動作txt程式碼
(1)print(input.getAxis('horizontal')),看數值是否在-1~1之間
(2)比較兩個的不同:
getAxis按下按鍵的時間,長短,強度,會影響移動的距離與強度
但是getkeydown的反應是固定量,不會反應按鍵的強弱大小
(3)因為getAxis的移動量距離大,所以要再乘上ratio1
(4)宣告ratio1為public,變成panel的參數,可以在外面修改
(5)新增兩個axis:一個左右轉Roate,一個向上看eyeRotate
成果圖片
(輸入Rotate後,要按enter,才會開始記錄,否則資料不會儲存)
(6)跳躍jump,發現會無法下降,因為沒有重力效應,所以還要加上rigidbody
(7)以第一人稱看跳過迎面而來的球,然後跳躍

(8)程式碼:建立move02.c#
void update()
{
if(Input.GetAxis("Horizontal")!=0)//不等於0,表示有水平輸入訊號
{
//輸出按鍵訊號強度值
print("輸出按鍵訊號強度值" + Input.GetAxis("Horizontal")));
//根據按鍵訊���強度值,來進行水平方向的正負方向移動
this.transform.Translate(Input.GetAxis("Horizontal", 0,0,);
}
else if(Input.GetAxis("Vertical")!=0)//不等於0,表示有垂直輸入訊號
{
//輸出按鍵訊號強度值
print("輸出按鍵訊號強度值" + Input.GetAxis("Vertical")));
//根據按鍵訊號強度值,來進行垂直方向的正負方向移動
this.transform.Translate(Input.GetAxis("Vertical", 0,0,);
}

(9).新增第19個鍵盤滑鼠控制
目的:讓印章stamp左右轉動
修改:size = 19
修改name = Rotate
Alt negative button(第二備用鍵) = e
Alt positive buttonn(第二備用鍵) = r
Gravity:按下後回覆的力道=10
Gravity=1000代表,從峰值回到原來值要1/1000秒,反應很快
Gravity=10代表,從峰值回到原來值要1/10秒,反應較慢

5.程式碼:move02.c#
void update()
{
if(Input.GetAxis("Horizontal")!=0)//不等於0,表示有水平輸入訊號
{
//輸出按鍵訊號強度值
print("輸出按鍵訊號強度值" + Input.GetAxis("Horizontal")));
//根據按鍵訊號強度值,來進行水平方向的正負方向移動
this.transform.Translate(Input.GetAxis("Horizontal", 0,0,);
}
else if(Input.GetAxis("Vertical")!=0)//不等於0,表示有垂直輸入訊號
{
//輸出按鍵訊號強度值
print("輸出按鍵訊號強度值" + Input.GetAxis("Vertical")));
//根據按鍵訊號強度值,來進行垂直方向的正負方向移動
this.transform.Translate(0, 0,Input.GetAxis("Vertical");
}
else if(Input.GetAxis("Move")!=0)//不等於0,表示有水平輸入訊號
{
//輸出按鍵訊號強度值
print("輸出按鍵訊號強度值" + Input.GetAxis("Move")));
//根據按鍵訊號強度值,來進行水平正負方向移動
this.transform.Translate(Input.GetAxis("Move", 0,0,);
}

6.如何讓stamp以第一人視角(攝影機放在頂端)向上看,向下看
(1)注意:若直接設定stamp物件向上看,會跌到
(2)要在眼睛加上eyeRotate.c#
(3)getAxis的移動量距離大,要再乘上ratio2,宣告ratio1為public,變成pane的參數
(4)getAxis,兩個函數,一個鍵盤tq鍵,一個滑鼠中鍵
成果圖片
input manager 控制物體眼睛攝影機上下旋轉的1組動作txt程式碼
注意:若用滑鼠中間滾動來上下看,要把sensitiviiy從0.1調大(5~10),才能滑順的旋轉,否則旋轉角度太小。
成果圖片

7.用stamp去踢球
(1)把兩個懸空的球放下地面
(2)加上rigidbody

8.結論:鍵盤控制物件移動有兩種方法,其中Input.GetAxis比較好,比較簡單,細緻,專業,可以反映你的鍵盤按下去的力量
(1)建議方法:Input.GetAxis
//1.x move
transform.Translate(r1*Input.GetAxis("Horizontal"), 0, 0);
//2.z move
transform.Translate(0, 0, r1*Input.GetAxis("Vertical"));
//3.y jump
transform.Translate(0, r1*Input.GetAxis("Jump"), 0);
//4.rotate y
transform.Rotate(0, Input.GetAxis("Rotate"), 0);
//5.mouse x move
transform.Translate(Input.GetAxis("Mouse X"), 0, 0);
//6.mouse z move
transform.Translate(0, 0, Input.GetAxis("Mouse Y"));

(2)不建議方法:
if(Input.GetKeyDown(KeyCode.A)
{
this.transform.Translate(-3, 0,0,Space.Self);
}
if(Input.GetKeyDown(KeyCode.D)
{
this.transform.Translate(3, 0,0,Space.Self);
}
成果圖片1圖片2圖片3

 
範例2-6:c#的UGUI界面(unity GUI= Graphic User Interface, gu e)

範例2-6

專案成果圖片
下載本project成果檔案
範例2-6:c#的UGUI界面(unity GUI= Graphic User Interface, gu e)
1.功能:人機互動界面
遊戲執行過程,可以讓使用者User輸入參數的界面

2.觀念:
(1)UGUI乃是建立在畫布Canvas裡面(將UI放到Canvas裡面)
(2)有9種UI:
Text,Image,RawImage,Button
Toggle,Slider,Scrollbar,Dropdown,
InputField(文字方塊)

3.下載前一個範例來做GUI
下載上個範例成果檔案

4.在場景裡面建立Create→UI→Text
方法:滑鼠右鍵→UI→Text
成果圖片
產生一個Canvas
如何找到Canvas畫布:先找到x-y平面(canvas是個2D畫布),盡量放大視野
成果圖片
canvs的長寬大小,就是攝影機視野的大小
所以不必須要去改變canvas的size
修改text的對齊參數:改到左上角
在Text:輸入2行文字:
unity的GUI文字
台灣首府大學
測試:要把邊框點調大,才能全部看到文字,改變文字大小,顏色
成果圖片

4.GUI Raw Image(一般圖片)
(1)功能:做成可以一直出現在螢幕的logo,或浮水印(都要先去背)
(2)到google下載png icon
(3)到photoshop,編輯
存檔(另外儲存為網頁用):去背,透明,png24
(4)拖曵圖檔到軟體project的asset裡面
(5)點選hierachy的canvas
建立Create→UI→Raw Image
在屬性面板→textture→選asset裡面的圖片
移動到右上角
成果圖片

8.GUI Image(Sprite圖片)
(1)功能:製作Sprite物件,切片
傳統動畫:連續30張變換的圖形,形成動畫(缺點:在手機顯示,會delay不順)
sprite動畫(2D):只有一張圖片,但是包含所有的變換,利用即時切片,形成動畫

(2)下載sprite動畫
到google,輸入:sprite animation
下載一張sprite動畫(png,gif)
必須要是去背透明的圖片
成果圖片
若是沒有去背圖片,到photoshop裡面編輯,魔術索點選顏色,del

(3)unity
在assets建立image目錄
把sprite圖片拖曵進去
點選sprite圖片→屬性→texture:sprite
成果圖片
mode→multiple
成果圖片
點選sprite edit 按鈕
成果圖片
出現錯誤訊息:no sprite editor
原因:安裝prite ediotr package
方法:Window >> Package Manager >> 2D Sprite.
成果圖片
Make sure it says All Packages near the top left and it should appear.
選擇一個切片→apply套用
成果圖片
結果:在assetsl/image裡面,多出來很多切片圖片
(但是記憶體只有讀取一張圖片,所以能夠很流暢)

(4)unity
點選hierachy的canvas
建立Create→UI→Image
屬性面板→source image→選取一個assets裡面的切片
成果圖片

 
範例2-7:GUI界面:一開始就在label顯示(一分鐘後結束,目前日期時間)

範例2-7

成果圖片
下載本project成果檔案
範例2-7:GUI界面:button在label顯示(一分鐘後結束,目前日期時間)

1.下載前一個範例來做GUI
下載上個範例成果檔案

2.在unity的主畫面場景新增一個Text(ui物件)
(1)在hierarchy視窗的空白處,滑鼠右鍵→UI→Text
修改名稱=Textbox1
FontSize= 20
Color = red
成果圖片

3.在unity裡面寫一個c#程式
(1)在Assets視窗裡面,滑鼠右鍵→Create→c# script
一個c#也是一個component
(2)名稱:text1
成果圖片
4.開始寫script1程式
(1)到Assets視窗的script1
(2)double click這個程式物件(script1)
(3)宣告一個Text類別的變數:a1
(注意:但是因為Text是顯示在畫面的UI變數,所以要先using UnityEngine.UI;)
using UnityEngine.UI;
...
...
public Text a1;

(6)顯示:一分鐘後結束
#注意:要先載入UI函數庫:using UnityEngine.UI;
程式碼內容
成果圖片

5.在unity建立一個UI控制物件
(1)在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty
名稱:GameObject
把Assets視窗裡面的text1,拖曵到GameObject的add component
■觀念:在unity場景裡面的c#程式物件=GameObject(不是button1.c#)
■觀念:unity的inside c#=GameObject(outside c#=button1.c#)
(2)結果:場景裡面的GameObject,就會連結到c# script1程式
成果圖片
(3)把場景裡面的textbox1,連結到text1裡面的a1
原理:因為text1裡面宣告為public的變數,都會顯示到場景裡面的GameObject
成果圖片
方法:把textbox1拖曵到a1裡面
成果圖片
結果
成果圖片

6.顯示目前日期時間
(1)建立一個UI→Text02
成果圖片
(2)寫c#程式碼:text2
lable1.text = System.DateTime.Now.ToString();
成果圖片
成果圖片
#注意:要先載入UI函數庫:using UnityEngine.UI;
程式碼內容
(3)在unity裡面連結text02與c#(text02)的a1
成果圖片
成果圖片
(4)結果:
成果圖片

 
範例2-8:GUI界面:button顯示文字,button計算兩數相加(三個InputField)

範例2-8

成果圖片
下載本project成果檔案
範例2-7:GUI界面:button在label顯示(一分鐘後結束,目前日期時間)

1.下載前一個範例來做GUI
下載上個範例成果檔案

2.button顯示文字:
(1)在unity的主畫面場景新增一個Text(ui物件),button
在hierarchy視窗的空白處,滑鼠右鍵→UI→Text
成果圖片
在unity的主畫面場景新增一個button(ui物件)
修改button的文字=按鈕
成果圖片

3.在unity裡面寫一個c#程式
(1)在Assets視窗裡面,滑鼠右鍵→Create→c# script
(2)名稱:button1.c#
目標:按鈕後顯示:新年快樂
■注意:要先載入UI函數庫:using UnityEngine.UI;
■注意:若要把c#裡面的變數/function,與unity做連結,就要宣告它們是public
程式碼內容
(5)在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty→名稱:GameObject
把Assets視窗裡面的button1.c#,拖曵到GameObject的add component
■觀念:在unity場景裡面的c#程式物件=GameObject(不是button1.c#)
■觀念:unity的inside c#=GameObject(outside c#=button1.c#)
成果圖片
方法:把UI 裡面的Text拖曵到T1裡面
成果圖片
(6)結果:一開始play就出現:新年快樂,
成果圖片

問題:目標是要,按按鈕後,才會出現:新年快樂,而不是一開始就顯示
4.解決方法:修改程式碼:不寫在void update()裡面,
而是另外函數:public void show()裡面
■注意:要先載入UI函數庫:using UnityEngine.UI;
■注意:若要把c#裡面的變數/function,與unity做連結,就要宣告它們是public
程式碼內容
5.重要關鍵:設定button的on click事件程式是GameObject物件
(1)先點選UI.Button→找on click事件區域
(2)拉GameObject物件→拖曵到button的on click事件
成果圖片
(3)點選no function→找script1→show1()
成果圖片
測試結果:
成果圖片

6.button計算兩數相加(三個InputField)
(1)增加三個inputField
在hierarchy視窗的空白處,滑鼠右鍵→UI→InputField
成果圖片
在unity的主畫面場景新增一個button(ui物件)
修改button的文字=計算
(2)在unity裡面寫一個c#程式:button2.c#
■注意:要先載入UI函數庫:using UnityEngine.UI;
■注意:若要把c#裡面的變數/function,與unity做連結,就要宣告它們是public
程式碼內容
(3)把場景裡面的三個InputField,連結到GameObject裡面的t1,t2,t3
方法:把UI 裡面的InputField拖曵到T1,T2,T3裡面
成果圖片
(4)設定button的on click事件程式是GameObject物件
■觀念:在unity場景裡面的c#程式物件=GameObject(不是button1.c#)
■觀念:unity的inside c#=GameObject(outside c#=button1.c#)
■觀念:要建立連結connection(1):把unity的UI元件(Text,InputField)→→→連結到GameObject的c#之public變數
■觀念:要建立連結connection(2):設定unity button的onclick連結到GameObject的show2()函數
先點選UI.Button→找on click事件區域
拉GameObject物件→拖曵到button的on click事件
點選no function→找script1→show1()
成果圖片
結果:play計算加法,
成果圖片

 
範例2-9:GUI界面:兩數字if比較大小(2個inputField,一個button)

範例2-9

成果圖片
下載本project成果檔案
範例2-7:GUI界面:button在label顯示(一分鐘後結束,目前日期時間)

1.下載前一個範例來做GUI
下載上個範例成果檔案

2.建立2個inputField,一個button:
(1)在unity的主畫面場景新增一個2個inputField,一個button
成果圖片

3.在unity裡面寫一個c#程式
(1)在Assets視窗裡面,滑鼠右鍵→Create→c# script
(2)名稱:compare.c#
目標:比較大小後顯示:大於,等於,小於
■注意:要先載入UI函數庫:using UnityEngine.UI;
■注意:若要把c#裡面的變數/function,與unity做連結,就要宣告它們是public
程式碼內容
(3)在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty→名稱:GameObject
把Assets視窗裡面的compare.c#,拖曵到GameObject的add component
■觀念:在unity場景裡面的c#程式物件=GameObject(不是compare.c#)
■觀念:unity的inside c#=GameObject(outside c#=compare.c#)
成果圖片
4.第一個連結connection:一個是inputfield與n1,n2變數
■注意:與unity做連結connection,要做兩個:
(第一個是inputfield與n1,n2變數)
(第二個是button-on_click與show()函數的連結)
方法:把UI 裡面的inputfield1 inputfield2拖曵到n1,n2裡面
方法:把UI 裡面的button, button/text拖曵到b1,t1裡面
成果圖片
結果:還是無法顯示
原因:與unity做連結connection,要做兩個(一個是inputfield與n1,n2變數,一個是button-on_click與show()函數的連結)

5.第二個連結connection:public void show()裡面,
■注意:若要把c#裡面的show function,與unity做連結,就要宣告它們是public void show()
(1)先點選UI.Button→找on click事件區域
(2)拉GameObject物件→拖曵到button的on click事件
(3)點選no function→找script1→show()
成果圖片
測試結果:
成果圖片

 
範例2-10:GUI界面:inputField直接控制改變足球轉速

範例2-10

成果圖片
下載本project成果檔案
範例2-10:GUI界面:inputField直接控制改變足球轉速

1.下載前一個範例來做GUI
下載上個範例成果檔案

2.讓stamp(1)以第一人稱視角FPS移動:
把main camera放入stamp(1)
建立move03.c#
複製程式碼:input.getkeydown控制物體運動的4組動作txt程式碼
把move03.c#拖曵到stamp(1)

3.在hierarchy視窗的空白處,滑鼠右鍵→UI→Text:足球轉速
在hierarchy視窗的空白處,滑鼠右鍵→UI→InputField
成果圖片

4.讓shper01轉動:
建立rotate03.c#(int a1)
撰寫程式碼:move03-txt程式碼
把rotate03.c#拖曵到shpere01

3.修改shper01的轉速(連結到畫面UI的InputField):
■注意:要先載入UI函數庫:using UnityEngine.UI;
■注意:若要把c#裡面的變數/function,與unity做連結,就要宣告它們是public
(1)修改程式碼:move03-txt程式碼
把rotate03.c#拖曵到shpere01
(2)把場景裡面的InputField,連結到shpere01裡面的a1
方法:把UI 裡面的InputField拖曵到A1裡面
成果圖片
(3)測試結果:
成果圖片

 
範例2-11:GUI界面:inputField+button控制高爾夫入洞

範例2-10

成果圖片
下載本project成果檔案
範例2-11:GUI界面:inputField+button控制高爾夫入洞

1.建立地形terrain(10x10x高度4),提升地面2公尺
在四周提升高度,形成圍牆,讓球無法掉出去
挖個洞
挖個沙坑
挖個湖泊
下載water物件(asset store:standard assets裡面有)
貼圖:草地,沙地
下載地形貼圖:https://www.ics.uci.edu/~djp3/classes/2014_03_ICS163/tasks/arMarker/Unity/arMarker/Assets/Terrain%20Assets/Textures/
設定天空:下載skybox
成果圖片

2.建立一個高爾夫球:
建立一個高爾夫球:sphere
下載貼圖:google:unity texture golf
成果圖片

3.建立UI(兩個text, 兩個inputfield,一個button)
在hierarchy視窗的空白處,滑鼠右鍵→UI→Text:x=,y=2
在hierarchy視窗的空白處,滑鼠右鍵→UI→InputField1,InputField2
成果圖片

4.建立程式碼,用UI的輸入值(x1,y1)控制球運動
■注意:要先載入UI函數庫:using UnityEngine.UI;
■注意:若要把c#裡面的變數/function,與unity做連結,就要宣告它們是public
建立move01.c#
寫程式碼:控制球移動程式碼

5.連結c#的變數到畫面UI的InputField,GameObject:
(1)建立unity的程式碼代表物件:
在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty→名稱:GameObject
把Assets視窗裡面的move01.c#,拖曵到GameObject的add component
■觀念:在unity場景裡面的c#程式物件=GameObject(不是compare.c#)
■觀念:unity的inside c#=GameObject(outside c#=compare.c#)
成果圖片
(2)注意:與unity做連結connection,要做三個連結:
第一個是inputfield與x1,y1變數
第二個是button-on_click與show()函數的連結
第三個是unity裡面的shpere與c#裡面的g1物件(gameObject)的連結
(3)第一個連結connection:連結inputfield與x1,y1變數
方法:
先點選GameObject物件
再把UI 裡面的inputfield1 inputfield2拖曵到x1,y1裡面
成果圖片
(4)第二個連結connection:public void show()裡面,
■注意:若要把c#裡面的show function,與unity做連結,就要宣告它們是public void show()
A.先點選UI.Button→找on click事件區域
B.再拉GameObject物件→拖曵到button的on click事件
C.點選no function→找script1→show()
成果圖片
(5)第三個連結connection:連結unity裡面的shpere與c#裡面的g1物件(gameObject),
先點選GameObject物件
再把hierarchy的shpere→拖曵到→GameObject物件裡面的g1變數
成果圖片

6.設定球的物理屬性:
(1)設定球:有剛體rigidbody物理性質(重力)
(2)設定球與其它文件碰撞時的物理性質:摩擦力,反彈係數
7.測試結果:
在畫面的inputfile輸入:x1,y1的數值,如何按鈕執行移動高爾夫球入洞
成果圖片

【chp3.建立自然地形terrain:山地,湖泊,河流,樹木,草地,風力】
範例3-1:建立大自然地形terrain,地形貼圖

範例3-1

專案成果圖片
下載本project成果檔案
範例3-1:建立大自然地形terrain,地形貼圖

建立大自然環境(地形,山地,火山,湖泊,樹木,草地)
1.專門工具:
地形製作工具
種樹工具
種地工具
地形設定

2.觀念:如何建模
(1)若是大自然地形(大規模),用unity內建工具建模(地形,山地,火山,湖泊,樹木,草地)
(2)若是局部物件(小規模),用3ds max建模再匯入(房子,家具...)

3.地形製作工具,有三種:
拉升
拉平
柔化

4.建立terrain地形物件
(1)建立地形的幾個要素:
先設定地形面積(長寬高)
再拉平地形
再拉升(湖泊的最低點時物件的最低點y=0)

(2)hierachy:+→create→ 3D object→terrain
注意:地形預設是1000x1000x600公尺,很大

(3)在地形的屬性面板,有7個設定
(4)選setting
在resulution→長寬高
width:1000
length:1000
height:600
空間位置示意圖片

(5)一次全部拉升水平面高度(先升高,等一下才能向下挖湖泊)
選paint terraiain按鈕

先把地平面全部升高到50高度(等一下才能向下挖湖泊)
在下拉選單:選set height
height = 200
按鈕:flatten all
結果:地平面向上抬高50公尺
成果圖片

(6)開始局部刷高或刷低地形
選paint terraiain按鈕
在下拉選單:選raise or lower terrain

滑鼠左鍵可以升高地形
設定參數
選擇筆刷大小:選擇有漸層小圓圈(才會建立平緩變化山峰)
筆刷大小:brushes size:100左右
筆刷強度opacity(影響地形高低強度):25左右
若opacity數值大,則刷一次就會造成很高的地形高度
成果圖片

用滑鼠左鍵拖曵筆刷,經過的地方就會隆起
若要局部微調地形高度,要降低opacity的數值

(7)向下降低地形(湖泊)
指令:shift+滑鼠左鍵
成果圖片

(8)邊緣的柔化
選paint terraiain按鈕
在下拉選單:選smotth the height
成果圖片

5.下載素材
1.到asset store視窗下載
進入unity,在左上點選,asset store
輸入地形的關鍵字:terrain
勾選免費的:pricing 選 0元,然後執行(>)
選2019版本的地形:unity version:2019
選擇一個,download
import:到project裡面
(注意:下載的素材不一定都可以用,因為有些有script,不一定相容)
成果圖片

6.幫地形貼圖
Top view
terrain物件的屬性面板→
(1)選paint terraiain按鈕
在下拉選單:選paint Texture→edit Texture layer按鈕→create texture layer
列出全部的texture清單
右上角的拉桿,可以控制顯示材質貼圖的icon大小
選擇綠色草皮,double click
結果:全部都是綠色草皮
成果圖片

(2)設定山地→半草半土
edit Texture layer按鈕→create texture layer
選擇半草半土貼圖,double click
在右邊的屬性面板,點選半草半土貼圖(出現藍色下緣,代表選取中)
控制brush大小
控制opacity強度大小
塗抹山地貼圖
成果圖片

(3)設定湖底→土質
edit Texture layer按鈕→create texture layer
選擇全土貼圖,double click
在右邊的屬性面板,點選全土貼圖(出現藍色下緣,代表選取中)
控制brush大小
控制opacity強度大小
塗抹湖底貼圖
成果圖片


範例3-2:建立天空,建立火山(丘陵),建立湖泊,建立樹木

範例3-2

專案成果圖片
下載本project成果檔案
範例3-2:建立天空,建立火山(丘陵),建立湖泊,建立樹木

0.下載前一個範例來做
下載上個範例成果檔案

1.建立天空skybox
(1)下載素材
到asset store視窗下載
輸入地形的關鍵字:skybox(或是standard asset)
勾選免費的:pricing 選 0元,然後執行(>)
選2019,或2018版本的skybox:例如:AllSky Free - 10 Sky / Skybox Set
選擇一個,download
import:到project裡面
成果圖片

(2)設定sky貼圖
Windows→Rendering→lighting Setting
成果圖片
選擇一個sky的貼圖assets
成果圖片
成果圖片

2.挖小河
在湖畔旁邊,挖小河
成果圖片
設定河流的貼圖

3.在湖泊,河流,填入水: (1)下載素材
到asset store視窗下載
輸入地形的關鍵字:standard asset(或是water)
勾選免費的:pricing 選 0元,然後執行(>)
選擇一個,download
只打勾:Environment→Water import:到project裡面
成果圖片
(2)拖曵water prefab到scene裡面
assets視窗→standard asset→Water→Water→Water4→Water→Prefabs→Water4→Advanced
拖曵到湖畔,河流
修改water的尺寸,使得填滿湖泊
成果圖片

4.種樹
(1)下載素材
到asset store視窗下載
輸入地形的關鍵字:tree
勾選免費的:pricing 選 0元,然後執行(>)
選2019,或2018版本
選擇一個,download
import:到project裡面
成果圖片

(2)選擇terrain
在下拉選單:選paint trees
設定參數
edit trees→add tree
bend factor:3(風力的吹彎效果)
筆刷brush size:
trees density:
直接種樹
成果圖片
成果圖片
成果圖片
也可以大面積的種樹
成果圖片

5.建立火山: (1)選擇terrain
在下拉選單:選raise or lower terrain
滑鼠左鍵可以升高地形
設定參數
選擇筆刷大小:選擇有漸層小圓圈(才會建立平緩變化山峰)
筆刷大小:brushes size:
筆刷強度opacity(影響地形高低強度):
用滑鼠左鍵拖曵筆刷,經過的地方就會隆起
邊緣的柔化
選paint terraiain按鈕
在下拉選單:選smotth the height

(2)火山貼圖: 岩石貼圖
https://www.ics.uci.edu/~djp3/classes/2014_03_ICS163/tasks/arMarker/Unity/arMarker/Assets/Terrain%20Assets/Textures/
terrain物件的屬性面板→paint terraiain按鈕
在下拉選單:選paint Texture→edit Texture layer按鈕→create texture layer
列出全部的texture清單
右上角的拉桿,可以控制顯示材質貼圖的icon大小
選擇:rock
成果圖片


範例3-3:建立樹木的4種方法:terrain種樹工具,樹木生成器,風力

範例3-3

成果圖片
成果圖片
下載本project成果檔案
範例3-3:建立樹木的4種方法:terrain種樹工具,樹木生成器,風力

下載上次進度檔案
1.建立地形terrain(50x50x高度10),提升地面4公尺
成果圖片
成果圖片
成果圖片
下載地形貼圖:https://www.ics.uci.edu/~djp3/classes/2014_03_ICS163/tasks/arMarker/Unity/arMarker/Assets/Terrain%20Assets/Textures/
成果圖片
在下拉選單:選paint Texture→edit Texture layer按鈕→create texture layer
列出全部的texture清單
右上角的拉桿,可以控制顯示材質貼圖的icon大小
選擇綠色草皮,double click
結果:全部都是綠色草皮
成果圖片
設定天空:下載skybox
成果圖片

2.種樹方法1:使用種樹工具:paint tree工具
(1)下載素材
到asset store視窗下載
輸入地形的關鍵字:tree
勾選免費的:pricing 選 0元,然後執行(>)
選2019,或2018版本
選擇:Realistic Tree 9 成果圖片
download→import:到project裡面
(2)選擇terrain:paint trees
edit trees→add tree→選擇一個tree物件
成果圖片
☎注意:要按:add
成果圖片
bend factor:3(風力的吹彎效果)
選擇筆刷大小brush size:
設定density:
成果圖片
☎若要在近距離內再種樹第二棵樹:調整density值變大
☎若要在一次只種一棵樹:調整筆刷大小brush size值變小
開始種樹
(3)☎如何刪除樹木:shift+滑鼠點選
☎如何改變種樹的高度:tree height(先取消random,再調整高度值)
(4)
☎缺點:比較無法在指定位置隨意種樹
☎優點:可以大面積種樹,速度快
☎適合:大面積種樹隨機種樹

3.種樹方法2:拖曵prefab元件到場景
(1)到assets/Tree9
→拖曵Tree9_4到場景
成果圖片
(2)☎如何刪除樹木:shift+滑鼠點選
☎如何改變種樹的高度:tree height(先取消random,再調整高度值)
(3)
☎缺點:一次只能種植一顆樹
☎優點:可以隨意在指定位置種樹
☎適合:自己指定位置種樹

4.建立風力效果
(1)hierachy:+→create→ 3D object→WindZone
風力力道=mian:0~50
擾流=turbulency=0~50
若要讓樹木不搖動:(main=0, turbulecy=0)
成果圖片
成果圖片
(2)風力種類:
☎方向性風directioanl(可以旋轉改變風向)
☎局部風shperical(可以改變風力範圍區域大小)
成果圖片

5.種樹方法3:樹不是3D物件,只是貼圖效果(不會隨風力而搖動)
(1)下載素材
到asset store視窗下載
輸入地形的關鍵字:Mobile Tree Package
成果圖片
download→import:到project裡面
(2)選擇terrain:paint trees
edit trees→add tree→選擇一個tree物件
注意:要按:add
開始種樹
(3)☎結果:樹木無法隨風力而搖動
原因:只是貼圖效果
成果圖片

6.種樹方法4:樹木生成器
(1)根部:root
成果圖片
(2)樹幹:branch
tree seed
成果圖片
area spread
成果圖片
設定多個樹幹:frquency
分佈的種類:distruibution
成果圖片
成果圖片
設定生長角度:angle
成果圖片
選擇樹幹貼圖:branch material:bark pine wh(樹皮鬆木)
成果圖片
樹幹長度:length
成果圖片
樹幹半徑粗細
成果圖片
設定樹幹上下粗細
成果圖片
設定樹幹是否要smooth:cap smoothing
成果圖片
設定樹幹彎曲度(枯樹彎曲度大):crinkliness
成果圖片
設定樹幹表面凹凸度:nosie
成果圖片
設定樹幹表面真實的曲度:flare
成果圖片
(3)建立第二層樹枝:add branch
成果圖片
設定樹枝的位置:seed
成果圖片
設定多個樹枝:frquency
成果圖片
把樹枝的位置移動上面一點:curve端點
成果圖片
把樹枝向上翹:angle
成果圖片
設定樹枝貼圖:branch material:
設定樹枝長度:scale
設定樹枝長度:length
設定樹枝半徑:radius
設定樹枝末端平滑度:cap smoothing
設定樹枝彎曲度(稍微彎曲才真實):crinkliness
(4)建立第三層樹枝:(可以在第三層加上葉子)
先選取第二層branch,再add branch
成果圖片
設定多個樹幹:frquency=3
設定生長角度:angle向上
分佈的種類:distruibution:random
設定樹枝長度:length(變小)
設定樹枝貼圖:branch material:
成果圖片
(5)建立葉子:在第三層加上葉子
先選取第三層樹幹branch,再add leaf group
成果圖片
設定多個樹葉:frquency=70
設定樹葉亂數發布種類:seed
設定生長角度:angle向上
分佈的種類:distruibution:random
設定樹葉長度:length(變小)
設定樹葉貼圖:material:選擇一個樹葉貼圖(ast3 lw),然後apply
成果圖片
成果圖片
設定樹葉大小:size
成果圖片
設定樹葉垂直分佈:perpendiculur align
設定樹葉水平分佈:horizontal align
(6)如何移動樹,向上:先選樹根root:再移動
成果圖片
(7)把樹木變成預鑄物件prefab
在assets裡面建立資料夾:mytree01
把樹木拖曵到asset/mytree01裡面
(8)用種樹工具paint tree來種樹
選擇terrain:paint trees
edit trees→add tree→選擇一個tree物件:選擇OptimizedTree,然後add
成果圖片
調整不同的tree height,tree density,沿著道路兩旁建立樹木
成果圖片
☎注意:如何刪除terrain所建立的樹木:shift+brush點按
成果圖片
(9)把自行建立的樹木預鑄物件prefab輸出:tree01 成果圖片
成果圖片
成果圖片
下載自行建立的樹木預鑄物件prefab

7.建立第一人稱視角FPS瀏覽場景
(1)下載stamp物件
(2)把攝影機main camera拖曵到stamp裡面
(3)建立move03.c#
複製程式碼:
input manager 控制物體運動的6組動作txt程式碼
input manager 控制物體眼睛攝影機上下旋轉的1組動作txt程式碼
把move03.c#拖曵到stamp
(4)測試:前後左右移動,左右轉動印章,以FPS視角移動


範例3-4:建立草地的4種方法,建立石頭方法

範例3-4

成果圖片
成果圖片
成果圖片
成果圖片
成果圖片
下載本project成果檔案
範例3-4:建立草地的4種方法,建立石頭

1.建立地形terrain(50x50x高度10),提升地面4公尺
成果圖片
成果圖片
成果圖片
設定天空:下載skybox
成果圖片

2.種草方法1:使用2D貼圖:paint texture工具
(1)下載地形貼圖:https://www.ics.uci.edu/~djp3/classes/2014_03_ICS163/tasks/arMarker/Unity/arMarker/Assets/Terrain%20Assets/Textures/
(2)在terrain下拉選單:選paint Texture→edit Texture layer按鈕→create texture layer
列出全部的texture清單
右上角的拉桿,可以控制顯示材質貼圖的icon大小
選擇綠色草皮,double click
結果:全部都是綠色草皮
成果圖片
成果圖片
(3)如何讓草皮有草皮的粗糙感:tilling seeting:size(變大) 成果圖片

3.種草方法2:使用2D+法向貼圖normal map(效果:會在法向上有凹凸立體感)
(1)下載素材
到asset store視窗下載
輸入地形的關鍵字:grass
勾選免費的:pricing 選 0元,然後執行(>)
選2019,或2018版本
選擇:Stylized Grass Texture
只要寫這個,就是法向貼圖normal map:Normal/Roughness/AO/Height maps included
成果圖片
成果圖片
download→import:到project裡面
結果:除了草地材質貼圖外,還有法向(垂直方向)的貼圖,可以造成粗糙感。
成果圖片
(2)選擇terrain:paint texture
edit texture layer→create layer→選擇一個tree物件
成果圖片
☎注意:設定方向貼圖(normal map):要點按select
成果圖片
選擇筆刷大小brush size:
控制opacity強度大小
塗抹草地貼圖
結果:有凹凸粗糙感
成果圖片

4.種草方法3:使用種草種花工具:paint detail工具
效果:2D貼圖,3D效果
(1)下載素材
到asset store視窗下載
輸入地形的關鍵字:grass
勾選免費的:pricing 選 0元,然後執行(>)
選擇:Grass And Flowers Pack 1
成果圖片
download→import:到project裡面
(2)選擇terrain:paint detail工具
edit Detail→add grass layer→選擇一個grass/flower物件
成果圖片
成果圖片
☎注意:要按:add
選擇筆刷大小brush size:1(一次種一棵)
開始種草/種花
成果圖片
成果圖片
☎注意:2D草也會飄動,但是與風力無關。

5.種草方法4:使用3D草的prefab
效果:3D物件,但是太多3D草,會佔據記憶體資源
(1)下載素材
到asset store視窗下載
輸入地形的關鍵字:grass
勾選免費的:pricing 選 0元,然後執行(>)
選擇:The Illustrated Nature - Sample
成果圖片
download→import:到project裡面
(2)種草方法1:拖曵prefab元件到場景
(3)到assets/IL3DN/Graphics/Prefabs
→拖曵prefab到場景
成果圖片
(4)種草方法2:使用種樹工具paint tree:
terrain→paint tree→craate layer→
成果圖片
(5)☎注意:
(A)種樹工具paint tree:任何的3D物件,都可以大量產生
(B)種草工具paint detail:任何的2D貼圖,都可以大量產生

6.如何種石頭:
(1)石頭,若是3D物件的話:必須用種樹工具paint tree
(2)種石頭1:拖曵prefab元件到場景
成果圖片
(3)種石頭方法2:使用種樹工具paint tree:
成果圖片
成果圖片

7.建立第一人稱視角FPS瀏覽場景 (1)下載stamp物件 (2)把攝影機main camera拖曵到stamp裡面 (3)建立move03.c#
複製程式碼:
input manager 控制物體運動的6組動作txt程式碼
input manager 控制物體眼睛攝影機上下旋轉的1組動作txt程式碼
把move03.c#拖曵到stamp
(4)測試:前後左右移動,左右轉動印章,以FPS視角移動

範例3-5:火山爆發,產生煙霧(粒子生成器),設定音效

範例3-5

成果圖片
下載本project成果檔案
範例3-5:火山爆發,產生煙霧(粒子生成器),設定音效

0.觀念:particles的用途:產生以下效果:smoke, fire, water droplets, or leaves

1.建立地形terrain(100x100x高度50),提升地面10公尺
成果圖片
設定天空:下載skybox
(1)下載地形貼圖:https://www.ics.uci.edu/~djp3/classes/2014_03_ICS163/tasks/arMarker/Unity/arMarker/Assets/Terrain%20Assets/Textures/
(2)在terrain下拉選單:選paint Texture→edit Texture layer按鈕→create texture layer
列出全部的texture清單
設定綠色草皮
設定沙地材質
設定岩石材質
成果圖片

2.產生煙霧效果的粒子生成器有兩種:
(1)舊版粒子生成器legacy particles:
(2)新版粒子生成器particles systems:

3.下載舊版粒子生成器legacy particles
(1)下載素材
到asset store視窗下載
輸入地形的關鍵字:grass
勾選免費的:pricing 選 0元,然後執行(>)
選2019,或2018版本
輸入選擇:particles
成果圖片
download→import:到project裡面
(2)直接拖曵prefab物件到場景
成果圖片
成果圖片

4.產生煙霧:使用particles system物件(新版)
(1)場景hierarchy→新增empty object:gameObject
成果圖片
把gameObject移動到火山口裡面
成果圖片
(2)inspector→shape→cone:但是cone的角度橫放
成果圖片
將它旋轉,往上
成果圖片
把cone的半徑變大:radius
成果圖片
修改噴出的粒子材質:目前紅色點,改成:render/material/default particle system
成果圖片
變成白色粒子
成果圖片
設定噴發粒子的最小size:render/min size=0.04,render/max size:1.37:
成果圖片
設定噴發粒子的最小size:render/min size=0.08,最大size:1.37:
成果圖片
設定噴發粒子的單一顏色:gameObject/start color:color
成果圖片
設定噴發粒子的漸層顏色:gameObject/start color:gradient
成果圖片
成果圖片
設定噴發粒子的漸層顏色:gameObject/start color:radom between two color
成果圖片
設定噴發粒子的漸層顏色:gameObject/start color:radom between two gradient
成果圖片
設定噴發粒子的漸層顏色:gameObject/start color:radom
成果圖片
希望一開始播放,就是粒子的平衡狀態:prewarm
成果圖片
讓粒子噴的高點(讓粒子壽命變長=11,但是速度不變=5):gameObject/start lifetime=11
成果圖片
讓粒子噴的高點(讓粒子壽命不變=5,但是速度變快=10):start speed=10
成果圖片
設定噴發粒子的最小size:render/min size=0.09:
成果圖片

5.設定unity的音效:
(1)下載火山爆發的音效:
https://mixkit.co/free-sound-effects/volcano/
https://www.freesoundslibrary.com/volcano-eruption-sound/
把檔案拖曵到unity→asset
(2)注意:聲音檔案與粒子系統,都要綁定在空的empty object(GameObject)
(3)連結檔案與GameObject
點選GameObject→add component:→audio→audio source
在inspector→audiosource→ audio clip:選擇檔案
loop勾選打勾
成果圖片

6.使用第一人稱視角(FPS = First Person Controller)
(1)unity以前有提供FPS的功能,但是在2018年以後,untiy就移除了FPS的功能(還有很多功能都被移除)
(2)現在如何下載使用:
這些被移除的功能,可以在asset store裡面找到
Just download and import it from standard assets or from the asset store
方法:到asset store
輸入搜尋:standard assets
設定price=0的過濾條件
成果圖片
成果圖片
成果圖片
(3)import後如何使用
在assets裡面→standand asset目錄→Characters→FirstPersonCharacter
找預鑄物件→Prefabs:FPSController.prefab
把這個FPS預鑄物件拉到場景scene
成果圖片
play
結果:出現錯誤:compiler errer
原因:SimpleActivatorMenu.cs有某些指令錯誤無法執行
(4)如何改善錯誤:
使用visual studio net 打開cs檔案
C:\Users\TA312\exp1-2\Assets\Standard Assets\Utility\SimpleActivatorMenu.cs
成果圖片
把以下三行前面加上://
//public GUIText camSwitchButton;
//camSwitchButton.text = objects[m_CurrentActiveObject].name;
//camSwitchButton.text = objects[m_CurrentActiveObject].name;
成果圖片
測試,結果:可以正常使用
使用上下左右鍵(前後左右移動)
也可以用滑鼠(向上看)
成果圖片

測試:前後左右移動,左右上下轉動,以FPS視角移動
☎注意:目前第一人稱fps綁定在攝影機上

範例3-6:鄉間小屋導覽虛擬實境VR動畫:第一人稱導覽動畫,輸出.exe動畫

成果圖片
成果圖片
成果圖片
成果圖片
成果圖片
成果圖片
下載成果動畫pc檔案
成果動畫web瀏覽
下載本project成果檔案
範例3-6:鄉間小屋的虛擬實境導覽VR動畫(第一人稱導覽動畫)

1.重新建立一個有煙囪噴煙的房屋:
(1)建立地形terrain(100x100x高度50),提升地面10公尺
下載地形貼圖:https://www.ics.uci.edu/~djp3/classes/2014_03_ICS163/tasks/arMarker/Unity/arMarker/Assets/Terrain%20Assets/Textures/
在terrain下拉選單:選paint Texture→edit Texture layer按鈕→create texture layer
設定綠色草皮
設定沙地材質
成果圖片
(2)到asset store下載房屋(有煙囪):
輸入:house
選擇:Fantasy Houses Exterior
成果圖片
下載,拖曵assets/FantasyWillageHouse/prefab/house_3
scale:x=20, y=20, z=20
position y = 20
成果圖片
再拖曵:house_3, house_2
成果圖片
(3)設定煙囪噴煙霧:
場景hierarchy→新增empty object:gameObject-somke1
把gameObject移動到煙囪裡面
inspector→shape→box:但是要旋轉box的角度
將它旋轉,往上
成果圖片
把box的長度寬度變大:scale:x,y
成果圖片
修改噴出的粒子材質:目前紅色點,改成:render/material/default particle system
變���白色粒子
設定噴發粒子的最小size:render/min size=0.01,最大maxsize:0.5:
設定噴發粒子的雙漸層隨機顏色:gameObject/start color:radom between two gradient
成果圖片
希望一開始播放,就是粒子的平衡狀態:prewarm
讓粒子噴的低點(讓粒子壽命變短=3,但是速度不變=5):start lifetime=3
成果圖片
設定噴發粒子的最小size:render/min size=0.02:
成果圖片
(4)建立其它兩個煙囪(建立prefab物件):
把gameObject-somke1拖曵到asset,形成prefab物件
再拖曵到house_3, house_1的煙囪上
成果圖片
調整噴煙量,顏色:
成果圖片

2.設定天空:下載skybox

3.種樹(3D)
方法1:使用種樹工具:terrain/paint trees
方法2:使用種樹工具:樹木生成器
成果圖片

3.設定風力
(1)風力影響樹木:
成果圖片
(2)讓風力影響煙霧(particle system):
在particle system→勾選external force
成果圖片
成果圖片
4.種草,種花(2D)
方法1:使用種草工具:terrain/paint detail
5.種石頭(3D)
方法1:使用種樹工具:terrain/paint trees

6.製作導覽動畫:
(1)製作導覽動畫步驟:
先打開animator時間軸面板。
設定camera的起始位置
在hierarchy建立gameObject-ani物件(然後新增animation component)
設定
(2)步驟1:先打開animator時間軸面板:
方法1:window→animation
成果圖片
方法2:asset 面板→add tab→animation
成果圖片
(3)步驟2:設定起始main camera的起始位置
新增一個camera
成果圖片
設定camera的起始位置
成果圖片
(4)步驟3:建立animatior還有animation clip
在animation 面板→create:New Animation.anim
成果圖片
成果圖片
先把坐標系統,調整成global
成果圖片
開始錄製(點選錄影開始)
成果圖片
add property(新增兩個屬性:postition,rotation屬性)
成果圖片
成果圖片
滾動滑鼠中鍵,縮小時間軸,顯示10秒
(動畫每秒60格(所以10秒=600格)
成果圖片
拖曵時間軸白色線,在第300個(5秒),移動camera位置,並旋轉(即可設定keyframe)
成果圖片
滑動時間軸,測試動畫效果
拖曵時間軸白色線,在第600個(10秒),移動camera位置,並旋轉(即可設定keyframe)
設定300,600,900,1200,1500格的位置
最後回到原點(可以設定x,y,z,scale數值與原點相同數字)
成果圖片
播放測試效果:play
成果圖片
成果圖片
成果圖片

7.如何電腦的.exe輸出動畫檔案:
File→Build settings
成果圖片
選擇pc→target=windows→Bulid
成果圖片
設定輸出資料夾:animation
成果圖片
再按一次build
成果圖片
輸出結果:
成果圖片
執行執行檔:exp3-6.exe
成果圖片

8.如何web的webGL動畫檔案:
File→Build settings

【chp4.建立可以走動的主角:角色Characters,動作Animations,動作控制器Animator Controller】
範例4-1:在大峽谷內走路跑步蹲下跳(使用standard asset之第三人視角的角色),遊戲切換場景的方法

範例4-1

成果圖片
成果圖片
下載本project成果檔案
範例4-1:在大峽谷內走路跑步蹲下跳(使用standard asset之第三人視角的角色),遊戲切換場景的方法

1.建立兩個場景:
(1)把預設場景存檔成:Scenes1
成果圖片
成果圖片
(2)新增場景:Scenes2
成果圖片
成果圖片
成果圖片
成果圖片

2.在Scenes1建立峽谷地形:
(1)建立地形terrain(500x500x高度300),提升地面20公尺
成果圖片
在terrain下拉選單:選paint Texture→edit Texture layer按鈕→create texture layer
設定地板高度:set height:20
成果圖片
建立峽谷山峰
成果圖片
清除峽谷中間,形成低窪平台(shift+paint terrain)
成果圖片
柔化山峰(smooth height)
成果圖片

3.幫地形貼圖
(1)選paint terraiain按鈕
在下拉選單:選paint Texture→edit Texture layer按鈕→create texture layer
列出全部的texture清單
右上角的拉桿,可以控制顯示材質貼圖的icon大小
下載地形貼圖:https://www.ics.uci.edu/~djp3/classes/2014_03_ICS163/tasks/arMarker/Unity/arMarker/Assets/Terrain%20Assets/Textures/
設定岩石材質:cliff
設定山峰貼圖cliff的size:x=20,y=20
成果圖片
設定低窪地貼圖pebble的size:x=20,y=20
成果圖片

4.種樹(3D)
下載3D樹木
在asset/滑鼠右鍵/import package
成果圖片
方法:使用種樹工具:terrain/paint trees
成果圖片

5.設定環境貼圖(包括skybox)
(1)到Asset Store線上商店下載classic skybox模型
Search:Fantasy Skybox FREE
成果圖片
download→Import→Import
成果圖片

(2)使用classic skybox
Windows → Rendering → Lighting Settings
→ Scene →Skybox → 選5

6.使用standard asset之第三人視角的角色
(1)下載standard assets
到asset store/輸入搜尋:standard assets
設定price=0的過濾條件
download/import
(2)import後如何使用
在assets裡面→standand asset目錄→Characters→ThirdPersonCharacter
找預鑄物件→Prefabs:ThirdPersonController.prefab
把這個FPS預鑄物件拉到場景scene
放大:scale(x=y=z=20)
成果圖片
play出現錯誤:
成果圖片
結果:出現錯誤:compiler errer
原因:SimpleActivatorMenu.cs有某些指令錯誤無法執行
(3)如何改善錯誤:
使用visual studio net 打開cs檔案
C:\Users\TA312\exp4-1\Assets\Standard Assets\Utility\SimpleActivatorMenu.cs
成果圖片
把以下三行前面加上://
//public GUIText camSwitchButton;
//camSwitchButton.text = objects[m_CurrentActiveObject].name;
//camSwitchButton.text = objects[m_CurrentActiveObject].name;
成果圖片

測試,結果:可以正常走路了
成果圖片

7.讓攝影機跟著角色移動:
(1)新增攝影機
成果圖片
(2)調整位置:在角色後面
成果圖片
(3)把攝影機置入角色內部(群組一體,成為子物件)
成果圖片
結果:走路,跑步,可以跟著移動
成果圖片
(4)指令:
跳:space
移動:WASD
蹲下:c
走向丘陵,可以跨過丘陵

9.製作場景2:scenes2
(1)如何進入場景2: double click Scence2 成果圖片
(2)建立物件: 成果圖片

8.如何用button與程式切換場景:
(1)設定全部場景名稱:
File -> Build Settings
成果圖片
成果圖片
(2)在scenes1場景
☎建立UI/button:
成果圖片
☎建立c#程式碼:goto2.c#
using UnityEngine.SceneManagement;
SceneManager.LoadScene("Scenes2");
程式碼內容
☎新增GameObject物件
在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty:GameObject
把Assets視窗裡面的goto2.c#,拖曵到GameObject的add component
成果圖片
☎設定button的on click事件程式是GameObject物件
A.先點選UI.Button→找on click事件區域
B.拉GameObject物件→拖曵到button的on click事件
成果圖片
C.點選no function→找script1→show1()
成果圖片
測試:可以切換·到scenes2
(3)在scenes2場景,建立button(到場景1)
做法一樣
(4)可以來回切換場景

範例4-2:讓我的主角跳街舞(使用Mixamo快速建立各種角色與動作),修正匯入FBX的貼圖錯誤

範例4-2

成果圖片成果圖片成果圖片成果圖片成果圖片成果圖片成果圖片成果圖片成果圖片成果圖片
下載動畫播放檔
下載本project成果檔案
範例4-2:讓我的主角跳街舞:使用Mixamo快速建立各種角色與動作,修正匯入FBX的貼圖錯誤

1.建立場景
(1)下載park公園
到asset store/輸入搜尋:park
設定price=0的過濾條件
找到:Low Poly Park
download/import
成果圖片
(2)import後如何使用
在assets裡面→Park Assets目錄→Scene→1→改名為Scenes1
double click Scenes1
成果圖片

2.到免費的3D角色動畫網站網站:Mixamo
(1)方法1:到Mixamo網站
Mixamo 是 Adobe 旗下的線上 3D 角色動畫網站,協助您製作高品質的角色動畫,可運用於電影特效、電玩遊戲、教育訓練等領域。
網頁上即時檢視套用骨架與動作的效果
登入後選擇login的按鈕,可以用gmail登入
成果圖片
(2)方法2:到assets store,輸入mixamo
也可以下載3D角色,與動作
(3)到Mixamo網站下載角色/動作
先選角色character:Remy
成果圖片
再選動作Animations:
輸入idle(閒置、待機、預備動作):fighting idle
成果圖片
download/選擇FBX for unity
成果圖片
在asset建立目錄:animation
拖曵下載的*.fbx檔案到assets,再拖曵到場景
成果圖片
新增camera,並拖曵到remy@Fighting Idle物件內,並調整位置角度
成果圖片
播放play,並不會動
成果圖片
(4)開啟角色的動作控制器animator:
點選remy@Fighting Idle物件→add component→其它雜項miscellaneous→animator
成果圖片
成果圖片
(5)產生動作控制器animator:
在asset/animation目錄
create→animator controller:New Animator Controller
成果圖片
(6)連結:角色vs動作控制器animator Controller
點選remy@Fighting Idle物件→
拖曵asset/animation目錄→裡面的New Animator Controller→拖曵到角色的Controller參數欄位內
成果圖片
(7)☎編輯動作控制器animator Controller
double click→ New Animator Controller
拖曵remy@Fighting Idle物件→到Controller內
成果圖片
測試play:結果可以移動了
成果圖片
但是,前後跳動4下就停止了
(8)修正Controller內的idel方塊→loop勾選
成果圖片
☎注意:修正animator controller後一定要先存檔(save scene+ save project),才會生效
成果圖片
測試play:有時候還是無法循環跳動??

3.繼續下載其它的跳舞動作:
(1)查詢:dance
下載:Twist dance
成果圖片
下載:Breaking dance套件
成果圖片
(2)拖曵到assets
成果圖片
(3)到Controller內
並且從fighting idle→滑鼠右鍵→make transition→拖曵到下一個
成果圖片
最後繞回fighting idle
成果圖片
測試play: 成果圖片成果圖片成果圖片成果圖片成果圖片成果圖片成果圖片

4.如何修正從FBX匯入unity,卻無法顯示貼圖texture的問題:
(☎注意:從Maya,3ds max,Mixamo匯入的FBX都有這個問題)
修正前:
成果圖片
☎修正方法:
點選assets/remy@Fighting Idle物
☎→inspector→Material→Extract texture
→建立資料夾:texture
成果圖片
點按fix now
成果圖片
新的問題:嘴巴牙齒的相失真
成果圖片

5.如何修正從FBX匯入unity,貼圖失真的問題:
(1)原因:這個是shader的法向貼圖normals導致的錯誤問題
(2)materal的設定都不見了:成果圖片
(3)☎修正方法:
點選assets/remy@Fighting Idle物
☎→inspector→Materials→Extract Materials
成果圖片
→選擇資料夾:texture
成果圖片
點按fix now
成果圖片
(4)點選assets/remy@Fighting Idle物 →→ body mesh
成果圖片
shader →→ standard →→ legacys shader →→ diffuse
成果圖片
成果圖片
修正後:結果:正常貼圖了與材質了
成果圖片
測試play: 成果圖片成果圖片成果圖片成果圖片成果圖片成果圖片成果圖片成果圖片成果圖片

6.配上音效
(1)下載跳舞的音效:
https://mixkit.co/free-sound-effects/volcano/
https://www.freesoundslibrary.com/volcano-eruption-sound/
把檔案拖曵到unity→asset
(2)注意:聲音檔案,要綁定在空的empty object(GameObject)
(3)連結檔案與GameObject
點選GameObject→add component:→audio→audio source
在inspector→audiosource→ audio clip:選擇檔案
loop勾選打勾
成果圖片

7.如何電腦的.exe輸出動畫檔案:
File→Build settings
成果圖片
選擇pc→target=windows→Bulid
成果圖片
設定輸出資料夾:animation
成果圖片
再按一次build
成果圖片
輸出結果:
成果圖片
執行執行檔:exp3-6.exe
成果圖片

範例4-3:使用unity chan快速建立各種角色與動作(閒置,走,跑,跌倒,拳擊)

範例4-3

成果圖片
成果圖片
成果圖片
下載動畫播放檔
下載本project成果檔案
範例4-3:使用unity chan快速建立各種角色與動作(閒置,走,跑,跌倒,拳擊)

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import
成果圖片
(2)import後如何使用
在assets裡面→POLYGON city pack目錄→double click:DemoScene
(3)新增一個camera,調整位置,角度:
成果圖片
(4)另存場景:scenes1
File/save as/scenes1
成果圖片

2.到asset store,下載3D角色
(1)到asset store下載各種角色: 方法1:Unity官方所提供的3D角色(已經套好骨架):unity chan(唸做jan=醬)
到assets store,輸入unity chan
download/import
成果圖片
方法2:找各種character
成果圖片
(3)下載角色有兩種主要部分:模型/動作動畫
模型: 成果圖片
動作動畫:(例如run動作動畫): 成果圖片

3.建立unity chan prefab到場景內:
(1)拖曵prefab到場景內:asset/unity-chan!/Unity-chan! Model/Art/Models/unitychan
成果圖片
播放play,並不會動

4.設定角色的兩個物理特性:重力rigidbody,膠囊碰撞器capsule collider
5.設定重力rigidbody:
(1)新增物理特性:重力rigidbody
點選unityChan→add component→physics→rigidbody
(2)設定人的重量:45
成果圖片
(3)設定碰撞時不不旋轉:rigidbody→constrains on x,y,z of rotation
成果圖片
☎出現問題:有重力後,會向下跌落地板
☎原因:角色沒有設定碰撞器collider,碰到地板,無法產生碰撞效果,才會穿越跌落

6.設定碰撞器collider:
(1)新增第二個物理特性:碰撞器collider:
點選unityChan→add component→physics→膠囊碰撞器capsule collider
(☎注意:人的碰撞器一般用capsule collider)
(2)調整膠囊碰撞器capsule collider的四周size,涵蓋到完整的一個人:
成果圖片
或是用editor去編輯碰撞器的端點:
成果圖片
☎出現問題:角色移動後,最後會跌到,並旋轉
☎解決辦法:要勾選角色unity chan的Rigidbody/Is Kinematic屬性
成果圖片

7.設定動作控制器animator:
(1)在asset建立目錄:animation
成果圖片
(2)建立動作控制器animator:
在asset/animation目錄
create→animator controller:New Animator Controller
修改名稱:AnimatorController1
成果圖片
(3)瀏覽各種animation動作的全名:
方法:拖曵檔案大小軸,到最小
成果圖片
(4)建立待(閒置,待機狀態idle)動作
拖曵等待(閒置,待機狀態idle)動作動畫物件
→asset/unity-chan!/Unity-chan! Model/Art/Animations/tunitychan_WAIT00
→拖曵到AnimatorController1
成果圖片
(5)連結:角色vs動作控制器animator Controller
點選unitychan物件→
拖曵asset/animation目錄→裡面的AnimatorController1→拖曵到角色的Controller參數欄位內
成果圖片
測試play:結果可以移動了
成果圖片
(6)建立高興跳躍動作
拖曵unitychan_WIN00動作動畫物件
→asset/unity-chan!/Unity-chan! Model/Art/Animations/unitychan_WIN00
→拖曵到AnimatorController1
設定mame transition
成果圖片
測試play:結果可以高興跳躍
成果圖片

8.如何設定人機互動=win(符合某條件(按了某按鈕, win=true),才會跳躍)
(1)建立判別是否win的變數:win
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:bool變數:win
成果圖片
(2)設定win的條件
若win=true,才讓wait00→win00
點選transition(from wait00→win00)
點按屬性面板的conditions→+
出現win=true
成果圖片
(3)設定不是win的條件
若win=false,讓win00→wait00
點選transition(from win00→wait00)
點按屬性面板的conditions→+
出現win=false
成果圖片
手動測試play:勾選win=true,結果可以高興跳躍
成果圖片
(4)問題:按了win=true後,要等一段時間才會反應(等到動作做完)
改善:如何馬上反應?
方法:把兩條transition連結的has exit time都取消勾選
成果圖片

9.設定人機互動=lose(符合某條件(按了某按鈕, lose=true),才會出現懊惱動作)
(1)建立判別是否lose的變數:lose
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:bool變數:lose
(2)設定lose的條件
若lose=true,才讓wait00→lose00
點選transition(from wait00→lose00)
點按屬性面板的conditions→+
出現lose=true
(3)設定不是lose的條件
若lose=false,讓lose00→wait00
點選transition(from lose00→wait00)
點按屬性面板的conditions→+
出現lose=false
成果圖片
(4)問題:按了lose=true後,要等一段時間才會反應(等到動作做完)
改善:如何馬上反應?
方法:把兩條transition連結的has exit time都取消勾選
成果圖片

10.設定人機互動=向前走(三種複合動作):
(1)向前走有三個動作:
向左前方走
向正前方走
向右前方走
☎注意:所以必須用混合樹blend tree來製作
(2)在動作控制器animator:建立blend tree
滑鼠右鍵→create state→from new blend Tree
成果圖片
修改名稱:walk
成果圖片
(3)在wait與walk之間,建立來回transiton 成果圖片
(4)建立判別前進後退的變數:speed
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:float變數:speed
成果圖片
(2)設定向前走的條件
點選transition(from wait00→walk)
點按屬性面板的conditions→+
設定spped greater:0.1
成果圖片
(3)設定停止向前走的條件
點選transition(from walk0→wait00)
點按屬性面板的conditions→+
設定spped less:0.1
成果圖片
(4)建立判別左右方向的變數:direction
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:float變數:direction
成果圖片
(5)設定walkback混合樹內的三種動作motion:
double click/walkback
點選blend tree→新增三種動作動畫→+
add motion field
成果圖片
設定direction的parameter的數值:-1,0,1 成果圖片
(6)結果測試:
參數測試,向右走:成果圖片
參數測試,向左走:成果圖片
blend tree parameter測試:成果圖片
(7)如何馬上反應?
方法:把兩條transition連結的has exit time都取消勾選
成果圖片
(8)☎問題:unity chan只能夠原地走,無法前進

11.☎如何讓unity chan走,能夠前進:
(1)☎方法:使用c#程式碼:UnityChanControlScriptWithRgidBody.cs
程式碼內容
檔案:asset/unity-chan!/Unity-chan! Model/Scripts/UnityChanControlScriptWithRgidBody.cs
拖曵到unitychan的add component→
成果圖片
(2)測試play:
先在animator設定speed=1,讓主角原地走
然後再Game視窗,點按一下→然後用鍵盤上下左右鍵:WS,AD來控制移動
上下鍵:WS(↑↓)
左右鍵:AD(及←→)
成果圖片
成果圖片
成果圖片
(3)☎結論:
(A).舊版的unity chan:只要打勾角色的Apply Root Motion,就可以動畫+移動了
(B).但新版的unity chan:其動畫不具有RootMotion效果, 所以移動的效果沒有,要自己寫c#程式才能移動, 可以參看它附的Script
☎新版:動作動畫:用動作控制器animator控制
☎新版:位移移動:要用c#程式碼控制

11.☎注意:asset store下載的3D角色有兩類:
(1)只要設定animator(不需要程式碼),就可以移動+動作動畫
(2)需要設定animator+程式碼,才能夠:移動+動作動畫,例如:unity chan

12.設定跑步的動畫(根據speed的大小,分為走路動畫,跑步動畫):
(1)把animator裡面的walk改成Locomotion(複合動作)
成果圖片
double click Locomotion→刪除三個walk的動作
在blend tree→滑鼠右鍵→add blend tree→新增兩個blend Texture→
成果圖片
(2)設定walk blend tree
修改名稱:walk
選擇parameter=direction
點選blend tree→新增三種動作動畫→+
add motion field
拖曵三個動作動畫(walk_L,walk_F,walk_R)
成果圖片
設定direction的parameter的數值:-1,0,1
成果圖片
(3)設定run blend tree
修改名稱:run
選擇parameter=direction
點選blend tree→新增三種動作動畫→+
add motion field
拖曵三個動作動畫(run_L,runk_F,run_R)
設定direction的parameter的數值:-1,0,1
成果圖片
測試結果:
成果圖片

範例4-4:角色種類2:用不需要程式碼的3D角色與動作(wait,walk),不需要程式碼就能移動

範例4-4

成果圖片
下載動畫播放檔
下載本project成果檔案
範例4-4:角色種類2:用不需要程式碼的3D角色與動作(wait,walk),不需要程式碼就能移動

1.☎注意:asset store下載的3D角色有兩類:
(1)只要設定animator(不需要程式碼),就可以移動+動作動畫
(2)需要設定animator+程式碼,才能夠:移動+動作動畫,例如:unity chan

2.官方提供的unity chan角色,有新舊兩種:
(1).舊版的unity chan:只要打勾角色的Apply Root Motion,就可以動畫+移動了
(2).新版的unity chan:其動畫不具有RootMotion效果, 所以移動的效果沒有,要自己寫c#程式才能移動, 可以參看它附的Script
☎新版:動作動畫:用動作控制器animator控制
☎新版:位移移動:要用c#程式碼控制

3.☎:下載不需要程式碼就能移動的3D角色與動作(wait,walk):
下載Raw Mocap Data 3D角色
測試結果:
成果圖片

範例4-5:Input Manager控制unity chan走路(但問題:無法旋轉)

成果圖片
下載動畫播放檔
下載本project成果檔案
範例4-5:Input Manager控制unity chan走路(但問題:無法旋轉)

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import
成果圖片
(2)import後如何使用
在assets裡面→POLYGON city pack目錄→double click:DemoScene
(3)新增一個camera,調整位置,角度:
成果圖片
(4)另存場景:scenes1
File/save as/scenes1
成果圖片

2.到asset store,下載3D角色
(1)到asset store下載各種角色: 方法1:Unity官方所提供的3D角色(已經套好骨架):unity chan(唸做jan=醬)
到assets store,輸入unity chan
download/import
成果圖片
方法2:找各種character
成果圖片
(3)下載角色有兩種主要部分:模型/動作動畫
模型: 成果圖片
動作動畫:(例如run動作動畫): 成果圖片

3.建立unity chan prefab到場景內:
(1)拖曵prefab到場景內:asset/unity-chan!/Unity-chan! Model/Art/Models/unitychan
成果圖片
播放play,並不會動

4.設定角色的兩個物理特性:重力rigidbody,膠囊碰撞器capsule collider
5.設定重力rigidbody:
(1)新增物理特性:重力rigidbody
點選unityChan→add component→physics→rigidbody
(2)設定人的重量:45
成果圖片
(3)設定碰撞時不不旋轉:rigidbody→constrains on x,y,z of rotation
成果圖片
☎出現問題:有重力後,會向下跌落地板
☎原因:角色沒有設定碰撞器collider,碰到地板,無法產生碰撞效果,才會穿越跌落

6.設定碰撞器collider:
(1)新增第二個物理特性:碰撞器collider:
點選unityChan→add component→physics→膠囊碰撞器capsule collider
(☎注意:人的碰撞器一般用capsule collider)
(2)調整膠囊碰撞器capsule collider的四周size,涵蓋到完整的一個人:
成果圖片
或是用editor去編輯碰撞器的端點:
成果圖片
☎出現問題:角色移動後,最後會跌到,並旋轉
☎解決辦法:要勾選角色unity chan的Rigidbody/Is Kinematic屬性
成果圖片

7.設定動作控制器animator:
(1)在asset建立目錄:animation
成果圖片
(2)建立動作控制器animator:
在asset/animation目錄
create→animator controller:New Animator Controller
修改名稱:AnimatorController1
成果圖片
(3)瀏覽各種animation動作的全名:
方法:拖曵檔案大小軸,到最小
成果圖片
(4)建立待(閒置,待機狀態idle)動作
拖曵等待(閒置,待機狀態idle)動作動畫物件
→asset/unity-chan!/Unity-chan! Model/Art/Animations/tunitychan_WAIT00
→拖曵到AnimatorController1
成果圖片
(5)連結:角色vs動作控制器animator Controller
點選unitychan物件→
拖曵asset/animation目錄→裡面的AnimatorController1→拖曵到角色的Controller參數欄位內
成果圖片
測試play:結果可以移動了
成果圖片
(6)建立高興跳躍動作
拖曵unitychan_WIN00動作動畫物件
→asset/unity-chan!/Unity-chan! Model/Art/Animations/unitychan_WIN00
→拖曵到AnimatorController1
設定mame transition
成果圖片
測試play:結果可以高興跳躍
成果圖片

8.如何設定人機互動=win(符合某條件(按了某按鈕, win=true),才會跳躍)
(1)建立判別是否win的變數:win
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:bool變數:win
成果圖片
(2)設定win的條件
若win=true,才讓wait00→win00
點選transition(from wait00→win00)
點按屬性面板的conditions→+
出現win=true
成果圖片
(3)設定不是win的條件
若win=false,讓win00→wait00
點選transition(from win00→wait00)
點按屬性面板的conditions→+
出現win=false
成果圖片
手動測試play:勾選win=true,結果可以高興跳躍
成果圖片
(4)問題:按了win=true後,要等一段時間才會反應(等到動作做完)
改善:如何馬上反應?
方法:把兩條transition連結的has exit time都取消勾選
成果圖片

9.設定人機互動=lose(符合某條件(按了某按鈕, lose=true),才會出現懊惱動作)
(1)建立判別是否lose的變數:lose
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:bool變數:lose
(2)設定lose的條件
若lose=true,才讓wait00→lose00
點選transition(from wait00→lose00)
點按屬性面板的conditions→+
出現lose=true
(3)設定不是lose的條件
若lose=false,讓lose00→wait00
點選transition(from lose00→wait00)
點按屬性面板的conditions→+
出現lose=false
成果圖片
(4)問題:按了lose=true後,要等一段時間才會反應(等到動作做完)
改善:如何馬上反應?
方法:把兩條transition連結的has exit time都取消勾選
成果圖片

10.設定人機互動=向前走(三種複合動作):
(1)向前走有三個動作:
向左前方走
向正前方走
向右前方走
☎注意:所以必須用混合樹blend tree來製作
(2)在動作控制器animator:建立blend tree
滑鼠右鍵→create state→from new blend Tree
成果圖片
修改名稱:walk
成果圖片
(3)在wait與walk之間,建立來回transiton 成果圖片
(4)建立判別前進後退的變數:speed
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:float變數:speed
成果圖片
(2)設定向前走的條件
點選transition(from wait00→walk)
點按屬性面板的conditions→+
設定spped greater:0.1
成果圖片
(3)設定停止向前走的條件
點選transition(from walk0→wait00)
點按屬性面板的conditions→+
設定spped less:0.1
成果圖片
(4)建立判別左右方向的變數:direction
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:float變數:direction
成果圖片
(5)設定walkback混合樹內的三種動作motion:
double click/walkback
點選blend tree→新增三種動作動畫→+
add motion field
成果圖片
設定direction的parameter的數值:-1,0,1 成果圖片
(6)結果測試:
參數測試,向右走:成果圖片
參數測試,向左走:成果圖片
blend tree parameter測試:成果圖片
(7)如何馬上反應?
方法:把兩條transition連結的has exit time都取消勾選
成果圖片
(8)☎問題:unity chan只能夠原地走,無法前進

11.☎如何讓unity chan走,能夠前進:
(1)☎方法:使用c#程式碼:UnityChanControlScriptWithRgidBody.cs
程式碼內容
檔案:asset/unity-chan!/Unity-chan! Model/Scripts/UnityChanControlScriptWithRgidBody.cs
拖曵到unitychan的add component→
成果圖片
(2)測試play:
先在animator設定speed=1,讓主角原地走
然後再Game視窗,點按一下→然後用鍵盤上下左右鍵:WS,AD來控制移動
上下鍵:WS(↑↓)
左右鍵:AD(及←→)
成果圖片
成果圖片
成果圖片
(3)☎結論:
(A).舊版的unity chan:只要打勾角色的Apply Root Motion,就可以動畫+移動了
(B).但新版的unity chan:其動畫不具有RootMotion效果, 所以移動的效果沒有,要自己寫c#程式才能移動, 可以參看它附的Script
☎新版:動作動畫:用動作控制器animator控制
☎新版:位移移動:要用c#程式碼控制

11.☎注意:asset store下載的3D角色有兩類:
(1)只要設定animator(不需要程式碼),就可以移動+動作動畫
(2)需要設定animator+程式碼,才能夠:移動+動作動畫,例如:unity chan

12.設定跑步的動畫(根據speed的大小,分為走路動畫,跑步動畫):
(1)把animator裡面的walk改成Locomotion(複合動作)
成果圖片
double click Locomotion→刪除三個walk的動作
在blend tree→滑鼠右鍵→add blend tree→新增兩個blend Texture→
成果圖片
(2)設定walk blend tree
修改名稱:walk
選擇parameter=direction
點選blend tree→新增三種動作動畫→+
add motion field
拖曵三個動作動畫(walk_L,walk_F,walk_R)
成果圖片
設定direction的parameter的數值:-1,0,1
成果圖片
(3)設定run blend tree
修改名稱:run
選擇parameter=direction
點選blend tree→新增三種動作動畫→+
add motion field
拖曵三個動作動畫(run_L,runk_F,run_R)
設定direction的parameter的數值:-1,0,1
成果圖片
測試結果:
成果圖片

範例4-6:正確鍵盤控制角色運動的第一種方法(local坐標控制:↑ ↓前進後退。 → ←控制旋轉)

成果圖片
下載動畫播放檔
下載本project成果檔案
範例4-6:正確鍵盤控制角色運動的第一種方法(local坐標控制:↑ ↓前進後退。 → ←控制旋轉)結合Input Manager控制walk,run,back


1.官網範例教學:
C:\Users\user\Downloads\unity\exp4-6\Assets\unity-chan!\Unity-chan! Model\Scripts
參考:UnityChanControlScriptWithRgidBody.cs

1.下載:
(1).第二個角色asset store的下載網址
(2).第二個場景asset store的下載網址

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import
成果圖片
(2)import後如何使用
在assets裡面→POLYGON city pack目錄→double click:DemoScene
(3)新增一個camera,調整位置,角度:
成果圖片
(4)另存場景:scenes1
File/save as/scenes1
成果圖片

2.到asset store,下載3D角色
(1)到asset store下載各種角色: 方法1:Unity官方所提供的3D角色(已經套好骨架):unity chan(唸做jan=醬)
到assets store,輸入unity chan
download/import
成果圖片
方法2:找各種character
成果圖片
(3)下載角色有兩種主要部分:模型/動作動畫
模型: 成果圖片
動作動畫:(例如run動作動畫): 成果圖片

3.建立unity chan prefab到場景內:
(1)拖曵prefab到場景內:asset/unity-chan!/Unity-chan! Model/Art/Models/unitychan
成果圖片
播放play,並不會動

4.設定角色的兩個物理特性:重力rigidbody,膠囊碰撞器capsule collider
5.設定重力rigidbody:
(1)新增物理特性:重力rigidbody
點選unityChan→add component→physics→rigidbody
(2)設定人的重量:45
成果圖片
(3)設定碰撞時不不旋轉:rigidbody→constrains on x,y,z of rotation
成果圖片
☎出現問題:有重力後,會向下跌落地板
☎原因:角色沒有設定碰撞器collider,碰到地板,無法產生碰撞效果,才會穿越跌落

6.設定碰撞器collider:
(1)新增第二個物理特性:碰撞器collider:
點選unityChan→add component→physics→膠囊碰撞器capsule collider
(☎注意:人的碰撞器一般用capsule collider)
(2)調整膠囊碰撞器capsule collider的四周size,涵蓋到完整的一個人:
成果圖片
或是用editor去編輯碰撞器的端點:
成果圖片
☎出現問題:角色移動後,最後會跌到,並旋轉
☎解決辦法:要勾選角色unity chan的Rigidbody/Is Kinematic屬性
成果圖片

7.設定動作控制器animator:
(1)在asset建立目錄:animation
成果圖片
(2)建立動作控制器animator:
在asset/animation目錄
create→animator controller:New Animator Controller
修改名稱:AnimatorController1
成果圖片
(3)瀏覽各種animation動作的全名:
方法:拖曵檔案大小軸,到最小
成果圖片
(4)建立待(閒置,待機狀態idle)動作
拖曵等待(閒置,待機狀態idle)動作動畫物件
→asset/unity-chan!/Unity-chan! Model/Art/Animations/tunitychan_WAIT00
→拖曵到AnimatorController1
成果圖片
(5)連結:角色vs動作控制器animator Controller
點選unitychan物件→
拖曵asset/animation目錄→裡面的AnimatorController1→拖曵到角色的Controller參數欄位內
成果圖片
測試play:結果可以移動了
成果圖片
(6)建立高興跳躍動作
拖曵unitychan_WIN00動作動畫物件
→asset/unity-chan!/Unity-chan! Model/Art/Animations/unitychan_WIN00
→拖曵到AnimatorController1
設定mame transition
成果圖片
測試play:結果可以高興跳躍
成果圖片

8.如何設定人機互動=win(符合某條件(按了某按鈕, win=true),才會跳躍)
(1)建立判別是否win的變數:win
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:bool變數:win
成果圖片
(2)設定win的條件
若win=true,才讓wait00→win00
點選transition(from wait00→win00)
點按屬性面板的conditions→+
出現win=true
成果圖片
(3)設定不是win的條件
若win=false,讓win00→wait00
點選transition(from win00→wait00)
點按屬性面板的conditions→+
出現win=false
成果圖片
手動測試play:勾選win=true,結果可以高興跳躍
成果圖片
(4)問題:按了win=true後,要等一段時間才會反應(等到動作做完)
改善:如何馬上反應?
方法:把兩條transition連結的has exit time都取消勾選
成果圖片

9.設定人機互動=lose(符合某條件(按了某按鈕, lose=true),才會出現懊惱動作)
(1)建立判別是否lose的變數:lose
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:bool變數:lose
(2)設定lose的條件
若lose=true,才讓wait00→lose00
點選transition(from wait00→lose00)
點按屬性面板的conditions→+
出現lose=true
(3)設定不是lose的條件
若lose=false,讓lose00→wait00
點選transition(from lose00→wait00)
點按屬性面板的conditions→+
出現lose=false
成果圖片
(4)問題:按了lose=true後,要等一段時間才會反應(等到動作做完)
改善:如何馬上反應?
方法:把兩條transition連結的has exit time都取消勾選
成果圖片

10.設定人機互動=向前走(三種複合動作):
(1)向前走有三個動作:
向左前方走
向正前方走
向右前方走
☎注意:所以必須用混合樹blend tree來製作
(2)在動作控制器animator:建立blend tree
滑鼠右鍵→create state→from new blend Tree
成果圖片
修改名稱:walk
成果圖片
(3)在wait與walk之間,建立來回transiton 成果圖片
(4)建立判別前進後退的變數:speed
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:float變數:speed
成果圖片
(2)設定向前走的條件
點選transition(from wait00→walk)
點按屬性面板的conditions→+
設定spped greater:0.1
成果圖片
(3)設定停止向前走的條件
點選transition(from walk0→wait00)
點按屬性面板的conditions→+
設定spped less:0.1
成果圖片
(4)建立判別左右方向的變數:direction
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:float變數:direction
成果圖片
(5)設定walkback混合樹內的三種動作motion:
double click/walkback
點選blend tree→新增三種動作動畫→+
add motion field
成果圖片
設定direction的parameter的數值:-1,0,1 成果圖片
(6)結果測試:
參數測試,向右走:成果圖片
參數測試,向左走:成果圖片
blend tree parameter測試:成果圖片
(7)如何馬上反應?
方法:把兩條transition連結的has exit time都取消勾選
成果圖片
(8)☎問題:unity chan只能夠原地走,無法前進

11.☎如何讓unity chan走,能夠前進:
(1)☎自行開發寫程式碼(不是複製官網的程式碼):
簡易版程式碼內容
詳細版程式碼內容
(2)拖曵到unitychan的add component→
成果圖片
(3)測試play:
先在animator設定speed=1,讓主角原地走
然後再Game視窗,點按一下→然後用鍵盤上下左右鍵:WS,AD來控制移動
上下鍵:WS(↑↓)
左右鍵:AD(及←→)
成果圖片
成果圖片
成果圖片
(3)☎結論:
(A).舊版的unity chan:只要打勾角色的Apply Root Motion,就可以動畫+移動了
(B).但新版的unity chan:其動畫不具有RootMotion效果, 所以移動的效果沒有,要自己寫c#程式才能移動, 可以參看它附的Script
☎新版:動作動畫:用動作控制器animator控制
☎新版:位移移動:要用c#程式碼控制

11.☎注意:asset store下載的3D角色有兩類:
(1)只要設定animator(不需要程式碼),就可以移動+動作動畫
(2)需要設定animator+程式碼,才能夠:移動+動作動畫,例如:unity chan

12.設定跑步的動畫(根據speed的大小,分為走路動畫,跑步動畫):
(1)把animator裡面的walk改成Locomotion(複合動作)
成果圖片
double click Locomotion→刪除三個walk的動作
在blend tree→滑鼠右鍵→add blend tree→新增兩個blend Texture→
成果圖片
(2)設定walk blend tree
修改名稱:walk
選擇parameter=direction
點選blend tree→新增三種動作動畫→+
add motion field
拖曵三個動作動畫(walk_L,walk_F,walk_R)
成果圖片
設定direction的parameter的數值:-1,0,1
成果圖片
(3)設定run blend tree
修改名稱:run
選擇parameter=direction
點選blend tree→新增三種動作動畫→+
add motion field
拖曵三個動作動畫(run_L,runk_F,run_R)
設定direction的parameter的數值:-1,0,1
成果圖片
測試結果:
成果圖片

範例4-7:正確鍵盤控制角色運動的第二種方法(global坐標控制:↑ 往北,↓往南, →往東,←往西)結合Input Manager

成果圖片
下載動畫播放檔
下載本project成果檔案
範例4-7:正確鍵盤控制角色運動的第二種方法(global坐標控制:↑ 往北,↓往南, →往東,←往西)結合Input Manager

1.官網範例教學:
https://learn.unity.com/tutorial/player-character-part-2-the-script?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb#5caf7217edbc2a08d53c87f3
https://www.youtube.com/watch?v=8kl0qdgGuYs&list=PLsEC4qT8YxBJ2jR0epcQTnUh89OOFpZ-I&index=8

1.下載:
(1).第二個角色asset store的下載網址
(2).第二個場景asset store的下載網址

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import
成果圖片
(2)import後如何使用
在assets裡面→POLYGON city pack目錄→double click:DemoScene
(3)新增一個camera,調整位置,角度:
成果圖片
(4)另存場景:scenes1
File/save as/scenes1
成果圖片

2.到asset store,下載3D角色
(1)到asset store下載各種角色: 方法1:Unity官方所提供的3D角色(已經套好骨架):unity chan(唸做jan=醬)
到assets store,輸入unity chan
download/import
成果圖片
方法2:找各種character
成果圖片
(3)下載角色有兩種主要部分:模型/動作動畫
模型: 成果圖片
動作動畫:(例如run動作動畫): 成果圖片

3.建立unity chan prefab到場景內:
(1)拖曵prefab到場景內:asset/unity-chan!/Unity-chan! Model/Art/Models/unitychan
成果圖片
播放play,並不會動

4.設定角色的兩個物理特性:重力rigidbody,膠囊碰撞器capsule collider
5.設定重力rigidbody:
(1)新增物理特性:重力rigidbody
點選unityChan→add component→physics→rigidbody
(2)設定人的重量:45
成果圖片
(3)設定碰撞時不不旋轉:rigidbody→constrains on x,y,z of rotation
成果圖片
☎出現問題:有重力後,會向下跌落地板
☎原因:角色沒有設定碰撞器collider,碰到地板,無法產生碰撞效果,才會穿越跌落

6.設定碰撞器collider:
(1)新增第二個物理特性:碰撞器collider:
點選unityChan→add component→physics→膠囊碰撞器capsule collider
(☎注意:人的碰撞器一般用capsule collider)
(2)調整膠囊碰撞器capsule collider的四周size,涵蓋到完整的一個人:
成果圖片
或是用editor去編輯碰撞器的端點:
成果圖片
☎出現問題:角色移動後,最後會跌到,並旋轉
☎解決辦法:要勾選角色unity chan的Rigidbody/Is Kinematic屬性
成果圖片

7.設定動作控制器animator:
(1)在asset建立目錄:animation
成果圖片
(2)建立動作控制器animator:
在asset/animation目錄
create→animator controller:New Animator Controller
修改名稱:AnimatorController1
成果圖片
(3)瀏覽各種animation動作的全名:
方法:拖曵檔案大小軸,到最小
成果圖片
(4)建立待(閒置,待機狀態idle)動作
拖曵等待(閒置,待機狀態idle)動作動畫物件
→asset/unity-chan!/Unity-chan! Model/Art/Animations/tunitychan_WAIT00
→拖曵到AnimatorController1
成果圖片
(5)連結:角色vs動作控制器animator Controller
點選unitychan物件→
拖曵asset/animation目錄→裡面的AnimatorController1→拖曵到角色的Controller參數欄位內
成果圖片

8.建立move(new blend tree),可以走或跑)
成果圖片

9.如何設定人機互動=IsWalking(符合某條件(按了某按鈕, IsWalking=true),才會開始走,或跑)
(1)建立判別是否win的變數:IsWalking
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:bool變數:IsWalking
成果圖片
(2)設定IsWalking的條件
若IsWalking=true,才讓wait02→move
點選transition(from wait02→move)
點按屬性面板的conditions→+
出現IsWalking=true
(3)設定不是IsWalking的條件
若IsWalking=false,讓move→wait02
點選transition(from move→wait02)
點按屬性面板的conditions→+
出現IsWalking=false
成果圖片
(4)問題:按了IsWalking=true後,要等一段時間才會反應(等到動作做完)
改善:如何馬上反應?
方法:把兩條transition連結的has exit time都取消勾選
成果圖片

10.在move blend tree裡面,新增2個blend tree(walk,run)
成果圖片
成果圖片
(1)建立判別前進後退的變數:speed
在動作控制器animator:
切換到parameters面板:
新增參數:+
選擇:float變數:speed
(2)設定向前走/跑的條件
speed=0~0.5:走路walk
speed=0.5~1:跑run
(2)☎問題:unity chan只能夠原地走,無法前進

11.☎如何讓unity chan走,能夠前進:
(1)☎自行開發寫程式碼(不是複製官網的程式碼):
簡易版程式碼內容
詳細版程式碼內容
拖曵到unitychan的add component→
成果圖片
(2)測試play:
先在animator設定speed=1,讓主角原地走
然後再Game視窗,點按一下→然後用鍵盤上下左右鍵:WS,AD來控制移動
上下鍵:WS(↑↓)
左右鍵:AD(及←→)
成果圖片

(3)☎結論:
(A).舊版的unity chan:只要打勾角色的Apply Root Motion,就可以動畫+移動了
(B).但新版的unity chan:其動畫不具有RootMotion效果, 所以移動的效果沒有,要自己寫c#程式才能移動, 可以參看它附的Script
☎新版:動作動畫:用動作控制器animator控制
☎新版:位移移動:要用c#程式碼控制

11.☎注意:asset store下載的3D角色有兩類:
(1)只要設定animator(不需要程式碼),就可以移動+動作動畫
(2)需要設定animator+程式碼,才能夠:移動+動作動畫,例如:unity chan

【chp6.程式碼建立節點物件,改變節點組件參數】
範例6-1:程式碼建立一個新的cube物件

範例6-1:程式碼建立一個新的cylinder物件

1.如何在程式碼裡面產生一個cylinder物件
GameObject circle1;
circle1 = GameObject.CreatePrimitive(PrimitiveType.Cylinder);

成果圖片程式碼
官網教學:程式碼產生一個cube

範例6-2:程式碼修改一個cube物件,材質為紅色,透明度為90(1~255)

1.第1種做法(最好,推薦):設定顏色透明度四個參數(完全程式碼控制)
範例: //設定button_fire為淡綠藍色
GameObject.Find("button_fire").GetComponent<Renderer>().material.color = new Color32(123, 202, 194, 100);

官網教學:Color32
官網教學:Color32


2.第2種簡單做法:範例6-2a:程式碼修改一個cube物件,材質為紅色
成果圖片程式碼
10.如何程式碼設定一個cube的材質
(1)先在aseet➜建立material(yellow):mat1➜設定黃色,透明度100
(2)程式碼設定物件的材質:circle1.GetComponent<Renderer>().material = mat1;
public Material mat1;
void Start()
{
circle1 = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
circle1.GetComponent<Renderer>().material = mat1;
}


3.第3種一般做法:範例6-2a:程式碼修改一個cube物件,材質為紅色
成果圖片程式碼
官網教學:程式碼改變材質顏色


4.第4種做法:修改材質透明度做法1:範例6-2c:建立一個material,再程式碼修改一個cube物件,材質為紅色,透明度為90(1~255)
成果圖片程式碼
影片教學:程式碼改變材質透明度
☎注意:
(1)要先建立一個紅色材質material
(2)確定material的alpha = 255
(3)把material的render mode設定為:transparent渲染模式(不可以設定Opaque渲染模式),才能夠讓程式修改alpah而渲染成透明
☎若是沒有把render mode改成transparent,那麼就算改了alpha,也沒有辦法渲染成透明的
成果圖片


5.第5種做法:修改材質透明度做法2:範例6-2d:完全程式碼控制,程式碼修改一個cube物件,材質為紅色,透明度為0.05(0~1)
成果圖片程式碼
影片教學:程式碼改變材質透明度
☎注意:
(1)不需要先建立一個紅色材質material
(2)完全用程式碼控制
(3)要用程式碼設定material的render mode設定為:transparent渲染模式(不可以設定Opaque渲染模式),才能夠讓程式修改alpah而渲染成透明
(4)設定顏色與透明度:this.GetComponent<Renderer>().material.SetColor("_Color", new Color(1, 0, 0, 0.05f))


範例6-3:點按一個cube物件,播放音效

成果圖片
下載本project成果檔案
範例6-2:建立主角john及其動作動畫

範例教學:
2.The Player Character: Part 1:
https://learn.unity.com/tutorial/the-player-character-part-1?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb#5caf6520edbc2a08d53c79fa

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-4:一個cube物件,再程式碼隱藏

11.如何程式碼設定物件隱藏:
circle1.SetActive(false);
成果圖片程式碼
官網教學:隱藏物件

範例6-5:先隱藏一個cube物件,再程式碼顯示


☎注意:若是先隱藏cube物件,再用程式碼讓它setActive(true),則無法顯示
因為:若是先隱藏,那麼就無法找到這個物件來(GameObjectg.fidn("cube")....找不到)
解決方法:不要用GameObject.find來尋找物件,而用public GameObject obj1來設定這個cube

成果圖片程式碼

☎注意:隱藏cube物件的方法:成果圖片

6-7:程式碼建立的物件節點,如何自動產生某個組件,例如navMeshAgent(RequireComponent)

參考影片:RPG Enemy Set States 設置敵人的基本屬性和狀態

1.目的:在程式碼加載的物件建,自動產生navMeshAgent組件
目的:在程式碼建立的物件建,自動產生rigidBody組件
☎方法:
//1.強迫該程式碼加載的物件,自動加入組件Rigidbody
[RequireComponent(typeof(Rigidbody))]

//2.強迫該程式碼加載的物件,自動加入組件navMeshAgent
//注意:要執行run一次,才會主動在前台面板產生navMeshAgent組件
[RequireComponent(typeof(NavMeshAgent))]

成果圖
步驟圖步驟圖步驟圖
程式碼

【chp7.滑鼠事件,觸控事件】
7-1:觸控事件的程式碼有兩種寫法

3.觸控程式碼有兩種寫法:
☎(1)方法1:一物件一個程式碼寫法:
架構:
點按物件用onMouseDown()......
Ray ray1 = Camera.mian.ScreenPointToRay(input.MousePosition)....
RayCastHit hit1....
if (Physics.Raycast(ray1, out hit1)..

☎缺點:若是地形是3個複合物件(cube1,cube2....),就會有三個程式碼,就會有三個相同變數
☎結果:造成結果產生不穩定的衝突
☎適合:只適合單一物件,點按的程式

範例程式碼


☎(2)方法2:一個程式碼監測全部文件寫法:
架構:程式碼加入任一物件,即可偵測全部的物件
架構:
update....
if(input.GetMouseButtonDown(0)......
Ray ray1 = Camera.main.ScreenPointToRay(input.MousePosition)....
RaycastHit hit1....
if (Physics.Raycast(ray. out hit1)....

☎結論1:一般的點按按鈕:用onMouseDown...即可
☎結論2:若要射線觸碰Ray:必須用方法2

➜update....
if(input.GetMouseButtonDown(0)....
Ray ray1 = Camera.mian.ScreenPointToRay(input.MousePosition)...

範例程式碼

7-2:如何做『ray射線』檢測(紅外線)

6.如何做『射線』檢測(紅外線)
程式碼

參考影片:射線檢測

☎常見應用:RPG遊戲,用滑鼠,點按某個地面點,主角就會移動到該點,
☎方法:它們都是使用『射線檢測』法,來偵測點按的坐標,然後再移動到該點
☎原理:就是從camera發出射線,打到第一個對象物件(按cube),就是觸控點的位置,可以取得該點的坐標
(1)前提:被射線發射碰到的物體,必須有碰撞器(coliider),才會發生hit,才能知道坐標
射線到plane場外,沒有碰撞器,就不會感應

(2)幾個步驟:
(2-1)如果按了滑鼠才檢測
if(Input.GetMouseButtonDown(0))
{
(2-2)按下左鍵滑鼠,則發射射線(由攝影機發出,到螢幕screen
Ray ray1 = Camera.main.ScreenPointToRay(Input.mouse.Position);
(2-3)宣告一個射線碰撞hit變數
RaycastHit hit1;
(2-4)宣告一個偵測是否碰撞變數res(射線檢測)
bool res = Physics.Raycast(ray1, out hit1);
//out hit1:若是有碰撞,會把射線碰撞參數訊息,放到hit1裡面(out = output)
(2-5)如何有射線碰撞(res = ture),hit1就會有參數,例如碰撞坐標 = hit1.point
if(res==true){
(2-6)輸出設想碰撞坐標
Debug.log(hit1.point);
this.transform.position = hit1.point;
}
}

7-3:如何取得射線ray,點按觸碰點的物件的資料(名稱,位置)

12.如何取得射線ray,點按觸碰點的物件的資料(名稱,位置)
(1)觸碰點的物件名稱 = hit1.collider.gameObject.name
(2)射線觸碰點的物件坐標 = hit1.point

(3)射線觸碰的程式碼:
void Update()
{
//全局偵測,是否按下滑鼠左鍵
if (Input.GetMouseButtonDown(0))
{
//發出射線(滑鼠點-camera射線)
Ray ray1 = Camera.main.ScreenPointToRay(Input.mousePosition);
//宣告碰撞變數
RaycastHit hit1;
//判別是否射線碰到物件,發生碰撞了
if (Physics.Raycast(ray1, out hit1) == true)
{
//射線觸碰點的物件坐標 = hit1.point
agent1.SetDestination(hit1.point);
//觸碰點的物件名稱 = hit1.collider.gameObject.name
string name1 = hit1.collider.gameObject.name;
}
}

7-4:如何在程式碼,顯示觸控射線點位置圓圈(以淡黃色,透明100圓圈顯示)

12.如何在程式碼,顯示觸控點位置圓圈(以淡黃色,透明100圓圈顯示)

(1)在aseet➜建立material(yellow)➜設定黃色,透明度100
(2)程式碼產生腳踩圓圈
腳踩圓圈
GameObject circle1;
//圓圈材質
public Material mat1;
void Start()
{
circle1 = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
circle1.transform.localScale = new Vector3(1.5f, 0.01f, 1.5f);
circle1.GetComponent<Renderer>().material = mat1;
circle1.SetActive(false);
}
void onMouseDown()
{
circle1.transform.position = hit1.point;
}

7-5:如何觸控射線,讓角色unityChan緩動有各種動作動畫(idle,walk,jump)

☎關鍵指令:設定animtor的參數status=2,agent1.GetComponent<Animator>().SetInteger("status", 2);

(1)先建立地形的多物件➜導航網格(navigation static,navigation bake)
(2)再建立角色unityChan➜加入navMesh Agent
(3)asset➜建立animator (名稱:player_Animator)
(4)再加入角色unityChan➜加入animator = player_Animator
(5)設定player_Animator:
加入wait_00動畫(idle)
加入walk_F動畫(設定參數status=1,則走路,把hasExitTime取消勾選)
加入jump_04動畫(設定參數status=2,則走路,把hasExitTime取消勾選)
(6)設定角色unityChan➜程式碼:agent_move.cs
如果觸控點物件名稱=jump2/jump3,則跳躍
否則走路
if (hit1.collider.gameObject.name == "jump2")
{
agent1.GetComponent<Animator>().SetInteger("status", 2);
}
else if (hit1.collider.gameObject.name == "jump3")
{
agent1.GetComponent<Animator>().SetInteger("status", 2);
}
else
{
agent1.GetComponent<Animator>().SetInteger("status", 1);
}

7-6:複合物件(小蜜蜂)如何觸控點按能夠有反應

成果影片


☎重要觀念1:複合物件(小蜜蜂)很容易加上程式碼組件,結果沒有反應:
原因1:複合物件(小蜜蜂)必須加入box collider組件,才能觸控反應
原因2:複合物件(小蜜蜂),必須使用rays射線觸控檢測法,才能觸控到複合物件(onMouseDown無法觸控到複合物件,只能單一物件)

☎重要觀念2:觸控事件有兩種:
(1)方法1:OnMouseDown():這個方法只適合單一物件的觸控點按,複合物件無法響應。

(2)方法2:一個程式碼監測全部文件寫法:
使用射線發出後檢查碰到的物件名稱,位置
update....
if(input.GetMouseButtonDown(0)......
Ray ray1 = Camera.main.ScreenPointToRay(input.MousePosition)....
RaycastHit hit1....
if (Physics.Raycast(ray. out hit1)....

☎注意:方法2的射線觸控檢測法,能夠控制複合物件(小蜜蜂)的移動。
☎但是有個前提條件:必須要加入box collider組件,才能成功運行。

☎結論:複合物件(小蜜蜂)的觸控事件,必須使用方法2的射線觸控檢測法,但是必須要加入box collider組件,才能成功運行。


成果影片

下載小蜜蜂素材:
方法1:到asset store,輸入bee,下載小蜜蜂
方法2:下載小蜜蜂 prefabs

成果圖
步驟圖步驟圖
程式碼cs01程式碼cs02

【chp8.節點物件的運動方法1:移動,旋轉,縮放】
範例8-1:如何程式碼設定一個cube的大小


9.如何程式碼設定一個cube的大小:
circle1.transform.localScale = new Vector3(1.5f, 0.01f, 1.5f);

8-2:移動,有兩種位移法:(1)再移動dx,(2)移動到某坐標點

1.移動,有兩種位移法:(1)再移動dx,(2)移動到某坐標點
(1).再移動dx:目前位置再新增個deltaD位移
(2).移動到某處:是直接到目標坐標

2.方法1:目前位置再新增個deltaD位移(相對位移量):translate(Vector3)
當前位置再新增個位移(translate(Vector3),表示在當前位置移動一個向量):
this.gameObject.transform.Translate(new Vector2(-5, 0) * Time.deltaTime)
this.gameObject.transform.Translate(Vector2.up * Time.deltaTime);

3.方法2:瞬間快速移動方法,移動到某個坐標(.position = new Vector3(..):
若要當前位置位移(.position += new Vector3(..)
this.gameObject.transform.position -= new Vector3(5, 0, 0);

4.沿著方向和距離移動變換translation。
(1)Translate的向量寫法有三種:
(1-1)可以直接寫向量:transform.Translate(0,0,1*Time.deltaTime);
(1-2)可以寫new Vector3:transform.Translate(new Vector3(0,0,1)*Time.deltaTime);
(1-3)可以寫單位向量Vector3.up:transform.Translate(Vector3.up*Time.deltaTime);

(2)以某個點為中心去移動,有三種:
注意:Space.Self只針對Translate才能用,但是不能用在position
(2-1)註明以自己為軸心去移動:transform.Translate(Vector3.up*Time.deltaTime,Space.Self)
(2-2)註明以世界坐標軸去心移動:transform.Translate(Vector3.up*Time.deltaTime,Space.World)
(2-3)註明以當前Camera為軸心去移動:transform.Translate(Vector3.up*Time.deltaTime,Camera.main.transform)

//(3)沿z軸向前移動對象1個單位/秒。
transform.Translate(0,0,1*Time.deltaTime);

//(4)在世界空間中向上移動對象1個單位/秒。
transform.Translate(0,Time.deltaTime,0,Space.World);

//(5)沿z軸向前移動對象1個單位/秒。(p.s. forward 寫作的簡寫Vector3(0, 0, 1))
transform.Translate(Vector3.forward* Time.deltaTime);

//(6)在世界空間中向上移動對象1個單位/秒。
transform.Translate(Vector3.up* Time.deltaTime,Space.World);

//(7)相對於相機向右移動對象1個單位/秒。
transform.Translate(Time.deltaTime,0,0,Camera.main.transform);

8-3.移動,有兩種速度呈現法:(1)緩動,(2)瞬間移動到某坐標點

8-3.移動,有兩種速度呈現法:(1)緩動,(2)瞬間移動到某坐標點
(1)緩動:慢慢位移方法:
例如:緩動,每次再移動dx,
在update(){
this.gameObject.transform.Translate(new Vector2(-5, 0) * Time.deltaTime)
this.gameObject.transform.Translate(Vector2.up * Time.deltaTime);
}

(2)瞬間快速移動方法:
例如:
移動到某個坐標:this.transform.position = new Vector3(3,0,0):
若要當前位置再位移:this.transform.position += new Vector3(3,0,0)
this.gameObject.transform.position -= new Vector3(5, 0, 0);

2.Transform類別:
參考網頁:Transform類別

(1)**常用屬性**
transform.Position = new Vector3(0, 0, 0); //以世界為中心的座標
transform.localPosition = new Vector3(0, 0, 0); //以父物件為中心的座標

(2)**常用方法**
transform.Translate(Vector3.forward * Time.deltaTime);//位移方法
transform.Rotate(xAngle, yAngle, zAngle, Space.Self); //以自身為軸心旋轉
transform.Rotate(xAngle, yAngle, zAngle, Space.World);//軸心取決於世界(scene)
☎※Time.deltaTime(幀數之間的時差)


3.利用transform.Translate移動(使用位移方法)
☎translagte方法的優點:可以控制每秒慢慢移動,不會瞬間移動

private void movement()//方法
{ //採用直接改變物件座標的方式
(1)直接改變物件座標(速度很快,瞬間移動)
//一、向右走
if (Input.GetKey("d"))//輸入.來自鍵盤(“d”)
{
this.gameObject.transform.Translate(new Vector2(5, 0));
} //此類別.這個物件.座標系統.位移(delta向量)

(2)依照一、的作法會發現物件飆很快,因此要乘上Time.deltaTime來延遲。
二、向左走;
if (Input.GetKey("a"))
{
this.gameObject.transform.Translate(new Vector2(-5, 0) * Time.deltaTime);
}

(3)可以直接使用Vector的屬性Vector2.up,就不需要new一個變數
向上走
if (Input.GetKey("w"))
{
this.gameObject.transform.Translate(Vector2.up * Time.deltaTime);
}

(4)直接使用Vector的屬性Vector2.down,就不需要new一個變數
//向下走
if (Input.GetKey("s"))
{
this.gameObject.transform.Translate(Vector2.down * Time.deltaTime);
}
}

4.利用transform.position(改變物件座標)
☎position方法的缺點:無法控制每秒慢慢移動,只會瞬間移動

public float speed; //設公開的數度變數,可在unity中設值調整
private void movement()//方法
{ //採用直接改變物件座標的方式

(1)移動方法:transform.position += new Vector3(....)
//向右走
if (Input.GetKey("d"))//輸入.來自鍵盤(“d”)
{
this.gameObject.transform.position += new Vector3(speed, 0, 0);
} //此類別.這個物件.座標系統.位置(為一個向量值x,y,z)+=這個向量

//向左走
if (Input.GetKey("a"))
{
this.gameObject.transform.position -= new Vector3(speed, 0, 0);
}

//向上走
if (Input.GetKey("w"))
{
this.gameObject.transform.position += new Vector3(0, speed, 0);
}
//向下走
if (Input.GetKey("s"))
{
this.gameObject.transform.position -= new Vector3(0, speed, 0);
}
}

8-4.Vector有兩種:單位向量Vector3.left,new Vedtor3(2,2,0)

8-4.Vector有兩種:單位向量Vector3.left,new Vedtor3(2,2,0)

(1)向量的寫法有兩種,一種要new Vedtor3(),另外一種不需要new
(1-1)要new:new Vector3(1.0f, 0.0f, 0.5f)
(1-2)不需要new:Vector3.left,就是單位向量

Vector2.up ====Vector(0,1)
Vector3.left ===== Vector(-1,0,0)
Vector3.up ===== Vector(0,1,0)
Vector3.forward ===== Vector(0,0,1)
Vector3.back === Vector(0,0,-1)

(2)向量是在坐標系中有方向、大小的值。
Vector2,二維向量,在平面座標系中,與原點的差值。Vector2(x, y)。
Vector3,三維向量,在三維空間中,與原點的差值。Vector3(x, y, z)。
x,y,z是數字,可以寫成整數(int)或浮點數(float ※數字後要加 f,例如 0.0f)。

(3)向量變數基本用法
Vector2 vec2 = new Vector2(1, 0);//int x=1 , int y=0
Vector3 vec3 = new Vector3(1.0f, 0.0f, 0.5f);//float x=1.0 , float y=0.0 , float z=0.5

Debug.Log(vec2.x); //1
Debug.Log(vec3.z); //0.5
另外補充,Vector有屬性可以使用,直接呼叫就不用設值。(請參閱unity官方文件)

(4)不需要進行new Vector,可直接呼叫的屬性
Debug.Log(Vector2.up.y); // 1
Debug.Log(Vector2.up); // (0.0,1.0)
Vector2.left 就是new Vector2(-1,0)
Vector2.right 就是new Vector2(1,0)
Vector2.up 就是new Vector2(0,1)
Vector2.down 就是new Vector2(0,-1)
Vector2.zero 就是new Vector2(0,0)
Vector2.one 就是new Vector2(1,1)

Vector3.left 就是new Vector3(-1,0,0)
Vector3.right 就是new Vector3(1,0,0)
Vector3.up 就是new Vector3(0,1,0)
Vector3.down 就是new Vector3(0,-1,0)
Vector3.forward 就是new Vector3(0,0,1)
Vector3.back 就是new Vector3(0,0,-1)

8-5.unity的角度有5種,unity的旋轉方式有5種

1.unity的角度有5種,unity的旋轉方式有5種
(1)unity 五種旋轉方式:localEulerAngles、eulerAngles、rotation、localRotation、Rotate

(1-1)Transform.localEulerAngles 自身欧拉角(var localEulerAngles : Vector3
參考網頁:Transform.localEulerAngles 自身欧拉角
範例:// Print the rotation around the parent's X Axis(打印绕父级的X轴的旋转角度
print(transform.localEulerAngles.x);

(1-2)Transform.eulerAngles 欧拉角(var eulerAngles : Vector3
參考網頁:Transform.eulerAngles 欧拉角
範例:// Print the rotation around the global X Axis(绕世界x轴的旋转角度
print(transform.eulerAngles.x);

(1-3)Transform.rotation 旋转角度(var rotation : Quaternion
參考網頁:Transform.rotation 旋转角度
原理:在世界空间坐标物体变换的旋转角度作为Quaternion储存。
/原理:Untiy作为四元数内部储存旋转角度。旋转一个物体,
/方法1:使用Transform.Rotate➜用四元数内部储存旋转角度。旋转一个物体
/方法1:使用Transform.eulerAngles➜用欧拉角➜來旋转角度。
範例1://重设世界的旋转角度 :transform.rotation = Quaternion.identity;
範例2:
//平滑倾斜物体向一个target旋转
var smooth = 2.0;
var tiltAngle = 30.0;
function Update () {
var tiltAroundZ = Input.GetAxis("Horizontal") * tiltAngle;
var tiltAroundX = Input.GetAxis("Vertical") * tiltAngle;
var target = Quaternion.Euler (tiltAroundX, 0, tiltAroundZ);
// Dampen towards the target rotation
//向target旋转阻尼
transform.rotation = Quaternion.Slerp(transform.rotation, target,
Time.deltaTime * smooth);;
}

(1-4)Transform.localRotation 自身旋转角度(四元数)
參考網頁:Transform.localRotation 自身旋转角度(四元数)
var localRotation : Quaternion
物体变换的旋转角度相对于父级的物体变换的旋转角度。
範例:
设置旋转角度同父级一样。
transform.localRotation = Quaternion.identity;

(1-5)Transform.Rotate 旋转函數
參考網頁:Transform.Rotate 旋转函數
function Rotate(eulerAngles : Vector3, relativeTo: Space = Space.Self) : void
应用一个欧拉角的旋转角度,eulerAngles.z度围绕z轴,eulerAngles.x度围绕x轴,eulerAngles.y度围绕y轴(这样的顺序)
範例:沿着x轴每秒1度慢慢的旋转物体
transform.Rotate(Vector3.right * Time.deltaTime);

範例:相对于世界坐标沿着y轴每秒1度慢慢的旋转物体
transform.Rotate(Vector3.up * Time.deltaTime, Space.World);

範例://围绕x轴每秒1度,慢慢的旋转物体
transform.Rotate(Time.deltaTime, 0, 0);

範例:相对于世界坐标,围绕y轴每秒1度,慢慢的旋转物体
transform.Rotate(0, Time.deltaTime, 0, Space.World);

☎☎☎2.設定旋轉角度,最常設定的方法:transform.localEulerAngles
原因1:相對於父節點的xyz軸,旋轉角
原因2:localEulerAngles = Vector3(10, 20, 45),歐拉角是我們常用角度
範例:node.transform.localEulerAngles = new Vector3(0, 90, 0);
原因3:localRotation是個四元數Quaternion,不好用

範例8-6:用幀動畫來控制直升機移動:上下、左移右移、左轉右轉

1.直升機向上移動的方法:採用幀動畫(frame animation)
原理:
(1)設定udapte()幀動畫:使用SpeedY * Time.deltaTime
void Update()
{
float dx = SpeedX * Time.deltaTime;
float dy = SpeedY * Time.deltaTime;
float dz = SpeedZ * Time.deltaTime;
this.gameObject.transform.Translate(dx, dy, dz, Space.Self);

float ry = RotateY * Time.deltaTime;
this.gameObject.transform.Rotate(0, ry, 0, Space.Self);
}
(2)按了按鈕(向上):
原理:一開始向上速度=2,但10s後後就啟動一個計時器,執行moveY,讓速度=0
public void MoveUp()
{
SpeedY = 2;
Invoke("moveY", 10);
}
void moveY()
{
SpeedY = 0;
}

2.直升機啟動螺旋槳動畫,播放音效的方法:
原理:
(1)如何把節點的component<Animation>打勾:
方法:this.gameObject.GetComponent<Animation>().enabled = true;
public void TurnOn()
{
this.gameObject.GetComponent<Animation>().enabled = true;
this.gameObject.GetComponent<AudioSource>().Play();
}

3.成果:
(1)成果影片

(2)參考影片:無人機飛行
參考影片:第16章調用component(無人機飛行)

(3)下載素材資源:
直升機的asset store
Unity UI Menu的asset store

(4)步驟圖:
步驟圖1步驟圖2步驟圖3步驟圖4步驟圖5

程式碼

8-7:AddForce(單位向量)來施力讓物體移動

參考網頁:Addforce,RequireComponent
參考影片:RPG Enemy Set States 設置敵人的基本屬性和狀態

☎注意:AddForce(方向向量),這個方法不實用,因為必須將物件節點加入rigidbody,造成力學效果。
☎但是:我們的遊戲程式很少會用力學模式(例如重力),而是用動力學kinematic模式(只有碰撞,沒有力學效果)。

1.本題目的:一顆足球,四個按鈕,前後左右施力移動

☎注意1:施力移動,乃是針對rigidbody來施力(myrigidbody.AddForce(Vector3.right))
☎注意2:施力的單位,乃是單位向量(前後左右:Vector3.right....)
☎注意3:可以使用RequireComponent方法,來強迫該程式碼加載的物件,自動加入組件Rigidbody
也可以自己手動加入組件(add component)。

2.程式碼:
//強迫該程式碼加載的物件,自動加入組件Rigidbody
[RequireComponent(typeof(Rigidbody))]

public class csMove : MonoBehaviour
{
Rigidbody myrb;
float forceFactor = 20;

private void Start()
{
myrb = this.gameObject.GetComponent<Rigidbody>(); }
public void moveRight()
{
myrb.AddForce(Vector3.right* forceFactor);
}
public void moveLeft()
{
myrb.AddForce(Vector3.left* forceFactor);
}
public void moveForward()
{
myrb.AddForce(Vector3.forward * forceFactor);
}
public void moveBack()
{
myrb.AddForce(Vector3.back * forceFactor);
}

成果影片

成果圖
步驟圖步驟圖步驟圖
程式碼

範例8-8:複合物件(小蜜蜂)如何觸控點按後就能向上移動1秒

成果影片

☎重要觀念1:點按物件移動,不建議用AddForce(方向向量),這個方法不實用,因為必須將物件節點加入rigidbody,造成力學效果。
但是:我們的遊戲程式很少會用力學模式(例如重力),而是用動力學kinematic模式(只有碰撞,沒有力學效果)。

☎重要觀念2:觸控事件有兩種:
(1)方法1:OnMouseDown():這個方法只適合單一物件的觸控點按,複合物件無法響應。

(2)方法2:一個程式碼監測全部文件寫法:
使用射線發出後檢查碰到的物件名稱,位置
update....
if(input.GetMouseButtonDown(0)......
Ray ray1 = Camera.main.ScreenPointToRay(input.MousePosition)....
RaycastHit hit1....
if (Physics.Raycast(ray. out hit1)....

☎注意:方法2的射線觸控檢測法,能夠控制複合物件(小蜜蜂)的移動。
☎但是有個前提條件:必須要加入box collider組件,才能成功運行。

☎結論:複合物件(小蜜蜂)的觸控事件,必須使用方法2的射線觸控檢測法,但是必須要加入box collider組件,才能成功運行。

☎重要觀念3:點按物件後移動1秒的最好方法
(1)不建議用:AddForce()函數,這個屬於力學模式(rigidbody),我們很少用力學模式。

(2)控制移動1秒:必須用計時器Invoke("StopMoveY", 1);
1秒後把幀動畫的位移分量speedY = 0

(3)幀動畫的做法(在update裡面)
float dx = speedX * Time.deltaTime;
float dy = speedY * Time.deltaTime;
float dz = speedZ * Time.deltaTime;
this.gameObject.transform.Translate(dx, dy, dz, Space.Self);


成果影片

下載小蜜蜂素材:
方法1:到asset store,輸入bee,下載小蜜蜂
方法2:下載小蜜蜂 prefabs

成果圖
步驟圖步驟圖
程式碼cs01程式碼cs02

範例8-9:複合物件(小蜜蜂)如何觸控點按後就以鏡頭camera垂直方向forward遠離鏡頭1秒

成果影片

☎(1)重要觀念1:觸控物件被點擊後,以當下鏡頭的法向方向移動:
☎鏡頭的法向方向:Camera.main.transform.forward;
原理:Camera is simply a Component attached to a GameObject. It's orientated using the relative Transform.
Main Camera forward direction in world space can be accessed this way:Camera.main.transform.forward;


☎(2)重要觀念2:小蜜蜂物件如何以鏡頭camera的法向forwrad進行幀動畫:
幀動畫:
speedCameraForward = -1*Camera.main.transform.forward;
......
this.gameObject.transform.Translate(speedCameraForward*Time.deltaTime, Space.Self);
範例:
Vector3 speedCameraForward;
void Update()
{
//判別按下滑鼠左鍵
if (Input.GetMouseButtonDown(0))
{
//(1)射線取得點按位置的坐標
Ray ray1 = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit1;
//射線檢測
if (Physics.Raycast(ray1, out hit1) == true)
{
//觸碰點的物件名稱 = hit1.collider.gameObject.name
string name1 = hit1.collider.gameObject.name;
if(name1== "FantasyBee")
{
//1秒後執行StopMoveCameraForwar()函數,讓相機法向向量速度speedCameraForward=0
speedCameraForward = -1*Camera.main.transform.forward;
Invoke("StopMoveCameraForwar", 1);
}
}
}//endi if 判別滑鼠左鍵
//(2)幀動畫
this.gameObject.transform.Translate(speedCameraForward*Time.deltaTime, Space.Self);
}
void StopMoveCameraForwar()
{
speedCameraForward = Vector3.zero;
}


成果影片

下載小蜜蜂素材:
方法1:到asset store,輸入bee,下載小蜜蜂
方法2:下載小蜜蜂 prefabs

成果圖
步驟圖步驟圖
程式碼cs01

範例8-15:計算兩個物件(agent1與圓圈)的距離

13.計算兩個物件(agent1與圓圈)的距離:
float distance1 = Vector3.Distance(agent1.transform.position, circle1.transform.position);

【chp9.節點物件的運動方法2:緩動移動(導航網格navMesh,Time.deltaTime)】
範例9-1:要讓角色緩動(在一段時間內移動到目的地),有兩種方法:導航網格navMesh,Time.deltaTime

1.要讓角色緩動(在一段時間內移動到目的地),有兩種方法:Time.deltaTime法,導航網格法

☎(1)方法1:在update內...使用Time.deltaTime來移動Translate,或旋轉Rotate
void Update()
{
float dx = SpeedX * Time.deltaTime;
float dy = SpeedY * Time.deltaTime;
float dz = SpeedZ * Time.deltaTime;
this.gameObject.transform.Translate(dx, dy, dz, Space.Self);

float ry = RotateY * Time.deltaTime;
this.gameObject.transform.Rotate(0, ry, 0, Space.Self);
}
☎(2)方法2:導航網格系統(navMesh)
(2-1)把地形物件➜設定navigation Static
(2-2)開啟Navigation 視窗(Windows➜AI➜navigation)
(2-3)建立導航網格➜navigation視窗➜Bake➜Bake,就會建立導航網格了
(2-4)新增角色物件➜加入程式碼,讓角色緩動到觸控點
代理人(角色)
using UnityEngine.AI;
NavMeshAgent agent1;
void Start()
{
agent1 = GameObject.Find("unitychan").GetComponent<NavMeshAgent>();
}
void Update()
{
//全局偵測,是否按下滑鼠左鍵
if (Input.GetMouseButtonDown(0))
{
//發出射線(滑鼠點-camera射線)
Ray ray1 = Camera.main.ScreenPointToRay(Input.mousePosition);
//宣告碰撞變數
RaycastHit hit1;
//判別是否射線碰到物件,發生碰撞了
if (Physics.Raycast(ray1, out hit1) == true)
{
//讓agent1移動到hit1.point
agent1.SetDestination(hit1.point);
}
}
(2-5)緩動到目的地的關鍵指令:agent1.SetDestination(hit1.point);
☎錯誤寫法:agent1.transform.position = hit1.point(這個是瞬間移動,不是緩動)

9-2:導航網格navMesh

☎導航網格navMesh

1.導航網格,navMesh, navMeshAgent:
參考影片:Unity零基础系统教学(Gamer飞羽)54-57章節教程(导航网格的使用)

2.nav = 導航 = navigation
agent = 代理人 = 行走的角色
mesh = 地板上可以行走的網格

3.設定導航網格的幾點:
(1)角色。。。都不需要設定rigidbody(也不需要勾選istrigger, iskinematic)
(2)何謂自動導航:

(A)只要滑鼠在畫面上觸控一點,角色就會自動以某個速度,結果看行走網格,走到那個地方
(B)它會根據最低成本路徑,走到目的地
(C)它可以設定:高處,跳下點
(D)它可以設定:兩處,跳遠點
(E)它可以適當:兩處,連接點(飛行)
(F)它可以設定,怪物,朝向角色而來

成果圖片
步驟圖1步驟圖2步驟圖3步驟圖4步驟圖5步驟圖6
程式碼

4.設定角色在地板網格行走的步驟:
(1)先建立地形(plane,cube。。。)
(2)建立角色
(3)設定地形的導航網格
(3-1)選取全部的地形➜右邊static➜navigation static(靜態導航)
(3-2)然後到右邊的一個『navigation』視窗➜bake(就會產生導航網格了)
但是要先設定能夠通過導航行走agent的4個基本參數(半徑,身高,agent爬斜坡的斜率上限,agent跨階梯的step上限)
經驗:這些網格的➜bake➜step height要設定高點,例如0.9(發現,若是設定0.4,則待會的主角,無法爬上階梯)
(3-3)最後按下方:bake➜產生導航網格(淺藍色網格,代表成本1的網格)
(4)設定主角為agent➜add component➜navMesh agent
(5)建立主角的程式碼➜add component➜playerControl.cs
using UnityEngine.AI;
抓取代理組件
agent1 = this.GetComponent<NavMeshAgent>();

void Update()//{
//手觸控某個位置,agent1就會朝點的位置走過去
//判別按下滑鼠左鍵
if (Input.GetMouseButtonDown(0))
{
//射線取得點按位置的坐標
Ray ray1 = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit1;
//射線檢測
if (Physics.Raycast(ray1, out hit1) == true)
{
//取得點擊位置
Vector3 point1 = hit1.point;
//設定point1為導航目標點
agent1.SetDestination(point1);
}
}
}

9-3:導航網格的特殊功能1:兩點之間跳躍(等高點的跳躍)

☎5.導航網格的特殊功能1:兩點之間跳躍(等高點的跳躍)
(1)建立兩個等高的物件,cube1,cube2
(2)???在navigation視窗➜Object標籤➜勾選 Generate offMeshlinks ???
(3)在navigation視窗➜Bake標籤➜設定 jump distance = 100
(4)在navigation視窗➜Bake標籤➜bake(結果:產生link連線)

成果影片
成果圖片
步驟圖7步驟圖8步驟圖9步驟圖10

9-4:導航網格的特殊功能2:兩點之間跳躍(高低點的跳躍)

☎6.導航網格的特殊功能2:兩點之間跳躍(高低點的跳躍)
(1)建立兩個不等高的物件,jump2,jump3
(2)在navigation視窗➜Object標籤➜勾選 Generate offMeshlinks
(3)jump3物件➜加入offMeshLinks組件
設定start = jump2
設定end = jump3
(4)在navigation視窗➜Bake標籤➜bake(結果:產生link連線)
成果影片
成果圖片

步驟圖7步驟圖8步驟圖9步驟圖10

9-5:如何修正:導航網格轉成AR(Vuforia)的錯誤:角色會浮在空中

☎如何修正:導航網格轉成AR(Vuforia)的錯誤:角色會浮在空中
4.設定可以自動觸控導航後,若是應用Vuforia,會出現,角色懸浮在空中的問題:
解決方法1:參考:修正導航網格在AR的錯誤

Click on AR Camera which is on your scene,
then there is a script attached to the AR Camera which is "Vuforia Behaviour" script.
It has "World Center Mode" option and "DEVICE" is selected as default. You need to change it from "DEVICE" to "SPECIFIC_TARGET" and as a target you should choose your "Image Target". After that, your Nav Mesh Agent should be working very well in AR as it works with normal camera.
步驟1:選擇 ARCamera➜World Center Mode:選:SPECIFIC_TARGET
步驟2:選擇 ARCamera➜World Center:target選:Image Target
測試:成功

步驟圖1

範例9-6:實作主角膠囊在導航網格內,自由觸控移動

參考影片:导航网格的使用

成果影片

成果圖片
步驟圖1步驟圖2步驟圖3步驟圖4步驟圖5步驟圖6
程式碼
下載專案檔案

範例9-7:實作主角unityChan在導航網格內,自由觸控移動+動作(idle,walk,jump)

成果影片
成果圖片
步驟圖1步驟圖2步驟圖3步驟圖4步驟圖5步驟圖6
步驟圖7步驟圖8步驟圖9步驟圖10
程式碼
下載專案檔案

9-8:unity的導航網格無法做到移動,如何修正

☎注意:unity的官網說明,導航網格navMesh,是無法支援移動中的網格。

(1)方法1:複雜法
教學影片:Yes You CAN Have Moving NavMesh Platforms
下載程式碼

(2)方法2:簡易法
(2-1)導航網格的瓶頸:若是物件移動,navMesh導航網格不會跟著移動
(2-2)修正:
☎方法:當主角agent1,觸碰移動物件cube1後,就把agent1加入cube1內(成為子節點)
☎主要程式碼:
private void OnTriggerEnter(Collider other)
{ if(other.name == "cube1")
{ this.transform.SetParent(other.transform);
}
}
程式碼

9-9:導航網格的主角,如何不動就idle,特定位置則jump,否則walk

(0)舉例:主角unitychan,觸碰link2就跳躍jump,導航就walk,到了目的地就idle
程式碼

☎步驟:
(1)設定導航網格navMesh,設定跳躍連接點offMeshLink,
(2)在主角unitychan設定程式碼playerControl.cs

☎(3)判別原地不動,顯示idle的程式思路:
(3-1)宣告prev_position變數:代表前一個幀率時,主角unitychan的位置
Vector3 prev_position = new Vector3(0,0,0);
(3-2)原理:在update裡面➜若主角最新的位置 = prev_position➜表示主角沒有移動了➜播放idle動畫(設定status=0)
if (GameObject.Find("unitychan").transform.position == prev_position)
{
GameObject.Find("unitychan").GetComponent<Animator>().SetInteger("status", 0);
}
...............
//最後一行,設定prev_position
prev_position = GameObject.Find("unitychan").transform.position;

(3-3)程式碼:
void Update()
{
bool isjump = false;
if (Input.GetMouseButtonDown(0))
{
Debug.Log(GameObject.Find("unitychan").GetComponent<Animator>().GetInteger("status"));
//射線取得點按位置的坐標
Ray ray1 = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit1;
//射線檢測
if(Physics.Raycast(ray1,out hit1)==true)
{
//取得點擊位置
Vector3 point1 = hit1.point;
//設定point1為導航目標點
agent1.SetDestination(point1);
//如果jump to (link2)則jump
if(hit1.collider.gameObject.name=="link2" || hit1.collider.gameObject.name == "door3")
{
...............
}
}
}
//注意:要先判斷Jump的case,否則永遠不會執行jump
if (isjump == true)
{
GameObject.Find("unitychan").GetComponent<Animator>().SetInteger("status", 2);
}
//如果原地不動,則status =0
else if (GameObject.Find("unitychan").transform.position == prev_position)
{
GameObject.Find("unitychan").GetComponent<Animator>().SetInteger("status", 0);
}
else//否則walk
{
GameObject.Find("unitychan").GetComponent<Animator>().SetInteger("status", 1);
}
//設定prev_position
prev_position = GameObject.Find("unitychan").transform.position;
}

☎(4)判別jump,顯示jump動畫的程式思路:
(4-1)宣告isjump變數:代表主角unitychan與特定link2物件是否碰撞,若是則jump
bool isjump = false;
(4-2)原理:在update裡面➜射線檢測if(Physics.Raycast(ray1,out hit1)➜若碰到link2➜if(hit1.collider.gameObject.name=="link2")➜則isjump = true
(4-3)程式碼:
void Update()
{
bool isjump = false;
if (Input.GetMouseButtonDown(0))
{
Debug.Log(GameObject.Find("unitychan").GetComponent<Animator>().GetInteger("status"));
//射線取得點按位置的坐標
Ray ray1 = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit1;
//射線檢測
if(Physics.Raycast(ray1,out hit1)==true)
{
//取得點擊位置
Vector3 point1 = hit1.point;
//設定point1為導航目標點
agent1.SetDestination(point1);
//如果jump to (link2)則jump
if(hit1.collider.gameObject.name=="link2")
{
//設定主角jump動畫(但是沒有效果),可能是update馬上被改成status=1
//GameObject.Find("unitychan").GetComponent<Animator>().SetInteger("status", 2);
//所以用一個isjump變數
isjump = true;
}
}
}
//注意:要先判斷Jump的case,否則永遠不會執行jump
if (isjump == true)
{
GameObject.Find("unitychan").GetComponent<Animator>().SetInteger("status", 2);
}

☎(5)判別碰撞物件,顯示過關win動畫的程式思路:
(5-1)宣告iscollide變數:代表主角unitychan與特定door3物件是否碰撞
bool iscollide = false;
(5-2)原理:在OnTriggerEnter裡面➜若主角最新的位置 = prev_position➜表示主角沒有移動了➜播放idle動畫(設定status=0)
(5-3)程式碼:
bool iscollide = false;
Vector3 prev_position = new Vector3(0,0,0);
private void OnTriggerEnter(Collider other)
{
if(other.name == "door3" && iscollide==false)
{
iscollide = true;
//播放過關音效
other.GetComponent<AudioSource>().Play();
//顯示過關畫面
img_Win.SetActive(true);
}
.............
}
☎(6)playerControl程式碼:
程式碼

範例9-10:實作主角unityChan的極限體能王過關遊戲

成果影片成果影片+製作步驟
AR走桌上的衛生紙

下載素材檔案
成果圖片1成果圖片2成果圖片3成果圖片4

步驟圖1步驟圖2步驟圖3步驟圖4步驟圖5步驟圖6步驟圖7步驟圖8步驟圖9步驟圖10步驟圖11步驟圖12步驟圖13

doormove程式碼
playerControl程式碼
gameover_manager程式碼

下載專案檔案

【chp10.射擊遊戲,不斷生成的prefab】
10-1.如何設定怪物不斷生成產生

10-1.如何設定怪物不斷生成產生

MonsterCreator程式碼
步驟圖1-MonsterFolder-MonsterCreator

(1)把已經建立好的怪物monster物件(可以左右隨機前進)➜拖曵成prefab
(2)建立一個空的gameObject(命名monster_Foler➜位置重置歸零(transform/Reset)後,才能再移動、)

(3)monster_Foler➜加上程式碼(怪物生成器):add component➜MonsterCreator.cs
☎程式碼1:使用計時器,不斷產生怪物:InvokeRepeating("MonsterCreat", 0.1f, 1.0f);
void MonsterCreat()
{
//方法2:使用目前this節點的transform變動組件
GameObject node = Instantiate(MonsterPrefab, this.transform);
//設定節點生成位置
node.transform.position = this.transform.position;
}

☎程式碼2:讓怪物monster prefab不要在原點建立(會被子彈打到,在原點的z左右隨機偏移第一次出現)
float dz = Random.Range(-30, 30);
node.transform.Translate(0, 0, dz, Space.Self);
}

☎程式碼3:設定怪物prefab的生命週期=300秒
Invoke("MonsterEnd", 300);
void MonsterEnd()
{
Destroy(this.gameObject);
}

monster-(MonsterCreator.cs)程式碼

10-2.兩種計時器(Invoke,InvokeRepeating)與各種計時器指令

☎計時器的各種指令用法:
1.Invoke是延時調用函數,在用Invoke函數之前需要引入命名空間using UnityEngine.Events;

發現:Invoke類似計時器setInterval("show",3) = Invoke("show", 3)
差異:InvokeRepeating更為進階,可以設定兩個時間參數 = (幾秒後,重複時間)
差異:Invoke,可以設定一次時間參數 = (幾秒後)
(1)InvokeRepeating("show", 2, 3) :2秒後,每隔三秒執行一次show
(2)Invoke("show", 2) :2秒後,執行一次show
(3)javascript:setInterval("show",3):每隔3秒執行一次show

2.各種計時器範例:
(1).Invoke("MethodName", 2)
這個比較簡單,寫在c#腳本中,意為兩秒之后調用一次,MethodName方法。

(2).InvokeRepeating("MethodName", 1, 2)
這個方法就是多次調用Invoke,即理解為一秒后,每隔兩秒調用MethodName方法。

(3).CancelInvoke("MethodName")
取消MethodName方法的調用。

(4)如何:關閉計時器
(4-1)關閉某個定時器(執行fire函數)
CancelInvoke("fire");

(4-2)關閉全部定時器
CancelInvoke();

3.MonoBehaviour裏面有兩個內置的延時方法
(1)InvokeRepeating(methodName: string, time: float, repeatRate: float): void;
methodName: 方法名
time:多少秒後執行
repeatRate:重復執行間隔

(2)Invoke(methodName: string, time: float): void;
methodName: 方法名
time:多少秒後執行

(3)還有兩個重要的方法:
IsInvoking:用來判斷某方法是否被延時,即將執行
CancelInvoke:取消該腳本上的所有延時方法

10-3.使用生成指令Instantiate(實例),在某物件A的位置,生成新物件B

☎生成指令Instantiate的用法:

(1)語法:Instantiate實例化(要生成的物件, 物件位置, 物件旋轉值);
範例:Instantiate(gameObject, transform.position, transform.rotation);

(2)自訂生成位置:
自訂Position : new Vector3(3,0,0)
自訂Rotation : new Quaternion(0,90,0,0)
範例:Instantiate (gameObject, new Vector3(3,0,0), new Quaternion(0,90,0,0));

(3)生成新物件在場景內的目前節點位置
範例:使用目前this節點的transform變動組件
GameObject node = Instantiate(MonsterPrefab, this.transform);

(4)生成在場景內的某個資料夾物件
範例:
[Tooltip("子彈目錄")]
public Transform bulletFolder;
void fire()
{
GameObject node = Instantiate(bulletPrefab, bulletFolder);
node.transform.position = bulletFirePoint.position;
}

(5)生成在場景scenes內的根目錄
範例:
//產生爆炸預鑄體prefab,放在根目錄(null)
GameObject node1 = Instantiate(bulletExplosion, null);

10-4.如何讓怪物monster亂數左右移動(蛇形走位)

☎如何讓怪物monster亂數左右移動(蛇形走位):

1.參考教程(無人機,射擊遊戲)
(1)參考影片:射擊遊戲
第25章1-10(射擊遊戲)

(2)參考影片:無人機飛行
參考影片:第16章調用component(無人機飛行)

2.設定步驟:
(1)怪物monster外層加個空的gameObject➜位置重置歸零(transform/Reset)後,才能再移動、
➜add box collider(is triggeer)
➜add rigidbody(is kenematic)

(2)怪物monster➜add monsterLogic.cs
☎程式碼1:設定怪物monste移動(前進dx,左右dz)
➜void Update()
{
this.transform.Translate(dx, 0, dz, Space.Self);
}

☎程式碼2:設定怪物monster每隔MonsterMoveInterval時間,就改變左右dz移動
➜InvokeRepeating("moveZRandom", 0.1f, MonsterMoveInterval);

void moveZRandom()
{
float[] zspeed = { -10, 5, -5, 10 };
int zindex = Random.Range(0, 4);
MonsterZSpeed = zspeed[zindex];
}

MonsterLogic程式碼
步驟圖1-monster-(MonsterLogic.cs)


12.設定怪物monster碰撞到player玩家時,的爆炸粒子,與音效,注意事項:
(1)會發現沒有爆炸效果:
原因:player玩家節點,要有兩個組件(且打勾動態運動學的碰撞):
(1-1)player玩家節點➜加入box collider(打勾is trigger)
(1-2)player玩家節點➜加入rigid body(打勾is kenematic)

10-5.從某個角色物件Cube-player,如何不斷發射子彈prefab(Sphere-bullet)


1.參考教程(無人機,射擊遊戲)
(1)參考影片:射擊遊戲
第25章1-10(射擊遊戲)

(2)參考影片:無人機飛行
參考影片:第16章調用component(無人機飛行)

2.重要原理:
☎本題的碰撞是兩種方法之一:只接觸沒有物理力學效果:iskenematic(運動學),istrigger(接觸,觸發器)
☎碰撞的前提:必須有box collider,必須有rigidbox,必須有接觸設定(iskenamatic,istrigger)

3.步驟:
(1)在場景先建立子彈物件(Sphere-bullet)位置重置歸零(transform/Reset)後,才能再移動、
(1-1)➜要能夠碰撞,必須加上rigidbody➜打勾is kinematic(有動力學碰撞效果,但沒有重力修改)
(1-2)➜ 打勾 is kinematic(運動學,只有移動運動,但是沒有物理力學效果)

(2)sphere collider ➜ 打勾 is trigger(觸發器,只是判斷接觸,沒有物理力學碰撞)

(3)add component ➜ bulletLogic.cs
☎程式碼1:bullet持續往前移動:
update
....
this.transform.Translate()

☎程式碼2:bullet的生命週期5秒:
Invoke("selfdestory",5)
....
selfdestory()
{
Destroy(this.gameObject);
}

☎程式碼3:接觸其它物件則彼此銷毀:
OnTriggerEnter()
{
Destroy(this.gameObject);
Destroy(other.gameObject);
}

(4)把子彈物件(Sphere-bullet)➜拖曵到asset
➜建立prefabg Sphere-bullet

(5)如何不斷呼叫產生大量的子彈
(5-1)在攻擊玩家player物件(Helicopter)➜add component➜playerLogic.cs
☎程式碼1:定時不斷開火,產生子彈:
InvokeRepeating("fire",0.1,0.5)

☎程式碼2:產生子彈prefabs:
fire()
{
GameObject node = Instantiate(子彈prefabs,子彈群目錄)
}

☎程式碼3:鍵盤ad,控制玩家player物件,左右移動:
update()
{
if(Input.GetKey(KeyCode.A))
......
this.transform.position += Vector3.back* playerSpeed;
}

☎.注意:
➜建立一個空的節點monster_Foler,要注意位置會自動亂設定,不在原點:
➜位置要先重置歸零(transform/Reset)後,才能再移動

bullet_logic程式碼
playerLogic程式碼

步驟圖1-(Sphere-bullet)-(bullet_logic.cs)
步驟圖2-(Helicopter)-(playerLogic.cs)-(helicopterControl.cs)


4.如果發現沒有出現子彈的,真正原因:
原因:若有修正,要更新子彈bullet節點時➜overridder➜apply all
注意:要setactiv(打勾顯示)時,才➜overridder➜apply all
沒有出現子彈的原因:因為是在隱藏子彈時去apply all的,所以當然不會顯示子彈

10-6.按鈕fire才開火(會飛的子彈),按鈕取消開火

11.如何按鈕fire,才開火(會飛的子彈)
public void FireOn()
{
InvokeRepeating("fire", 0.01f, bulletInterval);
}
void fire()
{
GameObject node = Instantiate(bulletPrefab, bulletFolder);
node.transform.position = bulletFirePoint.position;
}

12.如何按鈕取消開火
public void FireOff()
{
//關閉某個定時器(fire)
CancelInvoke("fire");
}

範例10-7.直升機fire攻擊不斷來襲的敵機

成果影片
1.參考教程(無人機,射擊遊戲)
(1)參考影片:射擊遊戲
第25章1-10(射擊遊戲)

(2)參考影片:無人機飛行
參考影片:第16章調用component(無人機飛行)

2.下載素材資源:
(1).直升機的asset store
(2).敵機的asset store
(3).下載asset store粒子動畫
打到敵機爆炸的粒子動畫:WFX_ExplosiveSmoke Big Alt
玩家被敵軍碰撞的爆炸(核子爆炸)動畫:War FX:WFX_Nuke
子彈飛出去的粒子動畫:flame:WFX_FlameThrower Big Alt Looped

(4).下載爆炸音效
角色被撞爆炸:mixkit-gun-explosion-with-long-echo-1700
子彈打到敵機:mixkit-fire-explosion-1343

3.程式碼:
MonsterCreator程式碼
MonsterLogic程式碼
bullet_logic程式碼
playerLogic程式碼
helicopterControl程式碼
4.步驟圖:
步驟圖1-MonsterFolder-(MonsterCreator.cs)
步驟圖2-monster-(MonsterLogic.cs)
步驟圖3-(Sphere-bullet)-(bullet_logic.cs)
步驟圖4-(Helicopter)-(playerLogic.cs)-(helicopterControl.cs)
步驟圖5-場景的物件

5.專案檔案:
下載專案檔案

10-8.在dx=(-30, 30)之間產生隨機亂數,移動dx位移


1.參考教程(無人機,射擊遊戲)
(1)參考影片:射擊遊戲
第25章1-10(射擊遊戲)

(2)參考影片:無人機飛行
參考影片:第16章調用component(無人機飛行)

2.隨機亂數設定方法:
(1)在dx=(-30, 30)之間產生隨機亂數,移動dx位移
//在原點的x左右隨機偏移第一次出現
float dx = Random.Range(-30, 30);
node.transform.Translate(dx, 0, 0, Space.Self);

程式碼


10-9.如何讓產生的生成物件Instantiate,在5秒後消失


1.參考教程(無人機,射擊遊戲)
(1)參考影片:射擊遊戲
第25章1-10(射擊遊戲)

2.5秒後消失物件的設定方法:Destroy(this.gameObject)
(1)5秒後消失:
Invoke("removeObject", 5.0f);
.....
private void removeObject()
{
Destroy(this.gameObject);
}

程式碼


10-10.在原地不斷生成怪物

1.從asset讀入怪物prefab
[Tooltip("enemy_green_prefab")]
public GameObject enemy_green_prefab;

2.在場景建立怪物目錄folder
[Tooltip("enemy_green_folder")]
public GameObject enemy_green_folder;

3.從0.01s開始,每隔2秒執行show函數
void Start()
{
InvokeRepeating("show", 0.01f, 3.0f);
}

4.建立怪物物件實體(產生一個怪物物件)
注意:第二個參數,是enemy_green_folder的transform組件
void show()
{
//第二個參數,是enemy_green_folder的transform組件
Instantiate(enemy_green_prefab, enemy_green_folder.transform);
}

成果影片
成果圖片1

步驟圖2
enemy_green_Creator.cs程式碼

【chp11.節點物件的碰撞事件1】
11-1:碰撞事件有2種處理方式:Collision碰撞,Trigger觸發

☎ 碰撞的觀念:
(1)參考資料網址

(2)有 2 種碰撞方式:
一、Collision碰撞,造成物理碰撞,可以在碰撞時執行OnCollision函式。
( 接觸 + 物理碰撞)
二、Trigger觸發,取消所有物理碰撞,可以在觸發時執行OnTrigger函式。
(接觸,但是不發生物理力學的碰撞)

所以兩個物件A跟B接觸時,不可能同時產生碰撞 + 觸發,最多產生其中一種,
但是可以辦到讓A跟B產生碰撞,A跟C產生觸發。

(3)碰撞需要 2 個條件:Collider,Rigidbody
(3-1)想要讓程式判斷兩個物件有接觸,則雙方都必需要有Collider(碰撞器),
(3-2)並且正在動的一方一定要有Rigidbody(剛體)才有效,另一方有沒有剛體無所謂。
※也就是說,如果動的一方沒有剛體,它去撞的靜止一方即使有剛體,也是當作沒撞到。

(4)產生接觸的設定方式如下:
一、Collision碰撞:雙方都有碰撞器collider,並且至少動的一方有剛體rigidbody,
就會造成碰撞,可以執行OnCollision函式。
※但若雙方都勾了Kinematic運動學,或任一方勾了Trigger觸發器,則碰撞無效。

二、Trigger觸發:雙方都有碰撞器,並且至少動的一方有剛體,
並且至少其中一方的碰撞器有勾觸發器,就會造成觸發,可以執行OnTrigger函式。

(5)接觸後的函式又細分為Enter、Stay、Exit三種
以Trigger為例,就是OnTriggerEnter、OnTriggerStay、OnTriggerExit
(Collision依此類推)。
Enter函式是當兩個物件接觸的瞬間,會執行一次這個函式;
Stay函式是當兩個物件持續接觸時,會不斷執行這個函式;
Exit函式是當兩個物件分開的瞬間,會執行一次這個函式。

(6)詳細解釋:
【Collider碰撞器】:
最重要的核心!只要有碰撞器就會對其他物件產生碰撞;
若自身要受到碰撞的話,則需要碰撞器 + 剛體,缺一不可。
若自身要受到程式Translate位移或Rotate旋轉,也至少需要碰撞器。

(7)【IsTrigger觸發器】:
勾了就不允許自身受到/造成碰撞,也不會受到重力等物理作用力影響,
而是改為Trigger觸發,雙方碰到時會直接穿越並執行Trigger函式。
但自身還是可以受到程式位移或旋轉。

(8)【Rigidbody剛體】:
允許自身受到碰撞,且動的一方要有剛體才允許產生Trigger觸發。
加了剛體的物件才會受到物理作用力,如受到重力而落下、被物理作用力推動/旋轉,
也無法主動穿越其他碰撞器,這都是受到剛體的影響。
而對方若是沒加剛體,對方就不會受到碰撞的作用力推擠,但仍然可以判斷雙方有碰撞。

(9)【IsKinematic運動學】:
不允許自身受到碰撞,但還是會對其他物件造成碰撞。
也不會受到重力等物理作用力影響。
※雙方都勾運動學的話,雙方都不會受到碰撞,會直接穿越,
 因此會被視為沒有碰撞到,無法執行OnCollision函式。
※對自身而言,剛體+運動學的效果,就等同於不加剛體,
 唯一差異是「剛體+運動學」去撞「靜止的碰撞體」時,
 仍可以執行碰撞、觸發函式;
 但雙方都不加剛體的話,則無法執行碰撞、觸發函式。

(10)【Constraints限制】:
自身受到碰撞時,勾選的位置(Position)、角度(Rotarion)不受力。
很類似把運動學拆成六個細項來設定,但唯一差別在於仍然算有碰撞,
可以照常執行OnCollision函式。

(11)【Drag空氣阻力】:提高數值可減少落下速度、被撞飛距離。

(12)【Angular Drag角阻力】:提高數值可減少旋轉速度。

11-2:Trigger觸發碰撞事件的設定方法(最常用的碰撞方式)

(1)Trigger觸發碰撞的特色:
☎只是兩個物件有發生『接觸』,但是不發生物理力學的碰撞(只是單純的相觸,沒有力學效果)
☎Trigger觸發,會取消所有物理碰撞,可以在觸發時執行OnTrigger函式。

(2)碰撞需要 2 個條件:Collider,Rigidbody
(2-1)想要讓程式判斷兩個物件有接觸,則雙方都必需要有Collider(碰撞器),
(2-2)並且正在動的一方一定要有Rigidbody(剛體)才有效,另一方有沒有剛體無所謂。
※也就是說,如果動的一方沒有剛體,它去撞的靜止一方即使有剛體,也是當作沒撞到。

(3)產生接觸的設定方式如下:
(3-1)Trigger觸發:雙方都有碰撞器collider(勾選IsTrigger),並且至少動的一方有剛體rigidboy(勾選IsKinematic),
並且至少其中一方的碰撞器有勾觸發器IsTrigger,就會造成觸發,可以執行OnTrigger函式。
步驟圖1
(5)接觸後的函式又細分為Enter、Stay、Exit三種
以Trigger為例,就是OnTriggerEnter、OnTriggerStay、OnTriggerExit
(Collision依此類推)。
Enter函式是當兩個物件接觸的瞬間,會執行一次這個函式;
Stay函式是當兩個物件持續接觸時,會不斷執行這個函式;
Exit函式是當兩個物件分開的瞬間,會執行一次這個函式。

OnTriggerEnter程式碼

11-3:如何設定碰撞時的粒子動畫效果(例如,顯示爆炸prefab)

9.如何設定子彈打到怪物爆炸效果,顯示爆炸prefab

(1)asset store尋找爆炸物件(War, explode, explosion)
(2)下載到asset/prefab,(例如:WFX_ExplosiveSmoke Big Alt)
(3)在子彈bulletLogic.cs➜public public GameObject bulletExplosion;
(4)打開bullet prefab物件➜拖曵(WFX_ExplosiveSmoke Big Alt)➜到bulletExplosion
(5)碰撞時顯示爆炸(注意:爆炸prefab,放在根目錄(null)
[Tooltip("子彈爆炸prefab")]
public GameObject bulletExplosion;
private void OnTriggerEnter(Collider other)
{
//產生爆炸預鑄體prefab,放在根目錄(null)
GameObject node1 = Instantiate(bulletExplosion, null);
}

程式碼

11-4:被關卡撞到,如何顯示煙霧動畫

[Tooltip("敵方被KO的煙霧動畫prefab")]
public GameObject somke_prefab;
private GameObject node_smoke;

private void OnTriggerEnter(Collider other)
{
if (other.name == "door2" || other.name == "door1")
{ //顯示煙霧動畫,放在根目錄,但是只有出現2秒(粒子系統只設定2秒),粒子會自動消失,不需要刪除
node_smoke = Instantiate(somke_prefab, null);

//設定動畫顯示的坐標
node_smoke.transform.position = this.transform.position;

//播放音效(在前台somke_prefab物件,就進入audioSource組件)
node_smoke.GetComponent<AudioSource>().Play();
}
}

程式碼

11-5:為什麼設定碰撞的音效,沒有出現,如何解決(子彈打到怪物播放爆炸聲音)

(1)錯誤做法:若在bullet_prefab裡面加上audioSource組件,拖曵到clip,在程式碼裡面讓getComponent<AudioSource>().plaey
結果:沒有聲音
原因:子彈碰撞時因為會destory,若是先播放音效,馬上就被destory,所以不會有聲音

(2)正確做法:把聲音clip拖曵到爆炸粒子動畫prefab才對
原因:在用 Instantiate(bulletExplosion, null)顯示爆炸粒子時,會完整顯示完畢,才會消失,所以就可以用這個來播放音效(不會被destory刪除)
private void OnTriggerEnter(Collider other)
{
//刪除this,other
if (other.gameObject.name != "Monster(Clone)") return;

//刪除物件
Destroy(this.gameObject);
Destroy(other.gameObject);

//產生爆炸預鑄體prefab,放在根目錄(null)
GameObject node1 = Instantiate(bulletExplosion, null);

//播放爆炸音效
//注意:爆炸音效要放在爆炸預鑄件prefab,不要放在子彈或主角(因為被destory了,就無法播放音效)
node1.GetComponent<AudioSource>().Play();
//設定爆炸的位置
node1.transform.position = this.transform.position;
}

程式碼

11-6:開啟爆炸範圍,任何進入範圍內的怪物都會被爆炸

1.顯示爆炸動畫/播放音效,打開爆炸box collider,3秒後關閉

//大爆炸動畫prefab
public GameObject WFX_Nuke;
//大爆炸音效
private GameObject wfx1;

bool isfire = false;

private void OnTriggerEnter(Collider other)
{
if (other.name == "button_fire" && isfire == false)
{
isfire = true;

//爆炸畫面(顯示在根目錄null)
wfx1 = Instantiate(WFX_Nuke, null);
//設定爆炸畫面的位置
wfx1.transform.position = GameObject.Find("Bomb").transform.position;

//把炸彈的box_collider打開,好讓炸彈碰撞怪物,但是只有打開3秒
GameObject.Find("Bomb").GetComponent<BoxCollider>().enabled = true;

//3秒後,關閉炸彈的box_collider
Invoke("TurnOffBoxCollider", 3);
}
}

2.怪物碰撞到Bomb的box collider,就設定狀態status = die
private void OnTriggerEnter(Collider other)
{
if (other.name == "Bomb" && isDie == false)
{
//顯示煙霧動畫,放在根目錄,但是只有出現2秒(粒子系統只設定2秒),粒子會自動消失,不需要刪除
node_smoke = Instantiate(somke_prefab, null);

//設定動畫顯示的坐標
node_smoke.transform.position = this.transform.position;
//播放音效
node_smoke.GetComponent<AudioSource>().Play();

//設定animator的status=4,躺下
this.gameObject.GetComponent<Animator>().SetInteger("status", 4);

//死亡
isDie = true;
}


成果影片

下載爆炸prefab動畫(WFX_Nuke)下載爆炸音效(nuclear_explode_aduio)
成果圖片1

步驟圖2步驟圖3步驟圖4步驟圖5步驟圖6步驟圖7步驟圖8步驟圖9
playerControl.cs程式碼
enemy_greenp_manager.cs程式碼


【chp13.切換場景】
13-1:切換場景的基本指令

☎ 10.如何切換場景:
成果圖片1成果圖片2

步驟圖2步驟圖3步驟圖4步驟圖5步驟圖6步驟圖7
程式碼
(1)先using UnityEngine.SceneManagement;
(2)建立gameObject01➜加上cs06.cs
(3)cs06:建立函數:gotoNextScene(s2)
public void gotoNextScene(string name1)
{
SceneManager.LoadScene(name1);
}
(4)場景的按鈕➜onclick➜設定gameObject01➜function = cs06.cs → gotoNextScene() → 設定參數 = s2(注意:不需要加上"")
(5)☎注意:要執行前,要先把2個場景都加入Build Scene內,才能build,才能執行
(File/Build Settings➜Scene to Build:s1,s2)

(6)按鈕要加上音效:https://www.soundjay.com/button-sounds-1.html

範例13-2:遊戲失敗產生Game Over畫面,方法1:切換場景

參考影片:Creating a Game Over Scene in Unity

成果影片
成果圖片成果圖片
步驟圖1步驟圖2步驟圖3步驟圖4
程式碼
1.範例13-2:遊戲失敗產生Game Over畫面,方法1:切換場景
(1)建立兩個場景:s1,s2
(2)在s2場景2:
(2-1)如何讓整個畫面背景色都是黑色:
方法:把main camera➜Clear Flags:solid Color➜設定背景色backgroun:黑色
(2-2)建立UI/Text_Infor:Game Over
(2-3)建立UI/Text_replay:再玩一次(R)
(2-4)建立UI/Text_Quit:關閉程式(Q)
(2-5)建立Empty Object:script_Manager➜加入程式碼:gameOver.cs
using UnityEngine.SceneManagement;
public void gotoscene(string s1)
{
SceneManager.LoadScene(s1);
}
public void myQuit()
{
Application.Quit();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.R))
{
SceneManager.LoadScene("s1");
}
else if (Input.GetKeyDown(KeyCode.Q))
{
Application.Quit();
}
else if (Input.GetKeyDown(KeyCode.E))
{
SceneManager.LoadScene("s2");
}
}
(2-6)把Text_replay➜加入UI/button組件:結束(E)
Button➜設定hightlight color
Button➜設定onclick➜物件=script_Manage➜function=gameOver/gotoscene,s1
(2-7)把Text_Quit➜加入UI/button組件
Button➜設定hightlight color
Button➜設定onclick➜物件=script_Manage➜function=gameOver/myQuit
(3)在s1場景1:建立按鈕(結束)
(3-1)建立Empty Object:script_Manager➜加入程式碼:gameOver.cs
(3-2)Button➜設定hightlight color
(3-3)Button➜設定onclick➜物件=script_Manage➜function=gameOver/gotoscene,s2

範例13-3:遊戲失敗產生Game Over畫面,方法2:顯示圖片(隱藏的圖片,用public讀入後顯示)

☎若用Image當作GameOver畫面,要replay時,不可以把image隱藏
原因:不會從頭開始執行,而是接著剛剛的進度執行
(1)錯誤做法:把img1隱藏(如此,不會重新開始)
img1.SetActive(false);

(2)正確做法:
SceneManager.LoadScene("SampleScene");

參考影片:Create great GAME OVER screen in Unity UI

成果影片
成果圖片成果圖片
步驟圖1步驟圖2步驟圖3步驟圖4步驟圖5

ButtonEnd2程式碼showGameOverScreen程式碼
下載專案檔案
1.範例13-3:遊戲失敗產生Game Over畫面,方法2:顯示圖片(隱藏的圖片,用public讀入後顯示)
(1)建立1個場景:s1
(2)建立UI/Button:結束(E)
(3)建立UI/image(背景圖)
(3-1)建立UI/Text_Infor:Game Over
(3-2)建立UI/Button-replay:再玩一次(R)
(3-3)建立UI/Button-Quit:關閉程式(Q)
(4)UI/Button➜加入程式碼:ButtonEnd2.cs
UI/Button➜onclick:物件=button,function=ButtonEnd2➜buttonEnd()
public GameObject img1;
public void buttonEnd()
{
img1.SetActive(true);
}
void Update()
{
if(Input.GetKeyDown(KeyCode.E))
{
img1.SetActive(true);
}
}

(5)背景圖➜加入程式碼:showGameOverScreen.cs
(5-1)UI/Button-replay➜onclick:物件=背景圖,function=showGameOverScreen➜replay()
(5-2)UI/Button-Quit➜➜onclick:物件=背景圖,function=showGameOverScreen➜Quit()
public void replay()
{
//(1)錯誤做法:把this.gameObject隱藏(結果,不會重新開始)
//隱藏目前這個物件(背景圖)
//gameObject.SetActive(false);
//(2)正確做法
SceneManager.LoadScene("SampleScene");
}
public void myquit()
{
Application.Quit();
}
void Update()
{
if(Input.GetKeyDown(KeyCode.R))
{
//隱藏目前這個物件(背景圖)
gameObject.SetActive(false);
}
else if(Input.GetKeyDown(KeyCode.Q))
{
Application.Quit();
}
}

範例13-4:遊戲失敗產生Game Over畫面,方法3:顯示圖片(隱藏圖片物件,用程式碼類別物件顯示)

參考影片:Create great GAME OVER screen in Unity UI

成果影片
成果圖片成果圖片
步驟圖1步驟圖2步驟圖3步驟圖4步驟圖5

ButtonEnd2程式碼showGameOverScreen程式碼
下載專案檔案
1.範例13-4:遊戲失敗產生Game Over畫面,方法3:顯示圖片(隱藏圖片物件,用程式碼類別物件顯示)
(1)建立1個場景:s1
(2)建立UI/Button:結束(E)
(3)建立UI/image(背景圖)
(3-1)建立UI/Text_Infor:Game Over
(3-2)建立UI/Button-replay:再玩一次(R)
(3-3)建立UI/Button-Quit:關閉程式(Q)
(4)UI/Button➜加入程式碼:ButtonEnd2.cs➜showscreen1 = 背景圖
UI/Button➜onclick:物件=button,function=ButtonEnd➜buttonEnd()

public showGameOverScreen showscreen1;
public void buttonEnd()
{
//錯誤做法:無法顯示
//GameObject.Find("背景圖").SetActive(true);

//正確做法:可以顯示背景圖片
showscreen1.show();
}

(5)背景圖➜加入程式碼:showGameOverScreen.cs
(5-1)UI/Button-replay➜onclick:物件=背景圖,function=showGameOverScreen➜replay()
(5-2)UI/Button-Quit➜➜onclick:物件=背景圖,function=showGameOverScreen➜Quit()

public void show()
{
//顯示目前這個物件(背景圖)
gameObject.SetActive(true);
}
public void replay()
{
//隱藏目前這個物件(背景圖)
gameObject.SetActive(false);
}
public void myquit()
{
Application.Quit();
}
void Update()
{
if(Input.GetKeyDown(KeyCode.R))
{
//隱藏目前這個物件(背景圖)
gameObject.SetActive(false);
}
else if(Input.GetKeyDown(KeyCode.Q))
{
Application.Quit();
}
}

9-2:導航網格navMesh

☎導航網格navMesh

1.導航網格,navMesh, navMeshAgent:
參考影片:Unity零基础系统教学(Gamer飞羽)54-57章節教程(导航网格的使用)

2.nav = 導航 = navigation
agent = 代理人 = 行走的角色
mesh = 地板上可以行走的網格

3.設定導航網格的幾點:
(1)角色。。。都不需要設定rigidbody(也不需要勾選istrigger, iskinematic)
(2)何謂自動導航:

(A)只要滑鼠在畫面上觸控一點,角色就會自動以某個速度,結果看行走網格,走到那個地方
(B)它會根據最低成本路徑,走到目的地
(C)它可以設定:高處,跳下點
(D)它可以設定:兩處,跳遠點
(E)它可以適當:兩處,連接點(飛行)
(F)它可以設定,怪物,朝向角色而來

成果圖片
步驟圖1步驟圖2步驟圖3步驟圖4步驟圖5步驟圖6
程式碼

4.設定角色在地板網格行走的步驟:
(1)先建立地形(plane,cube。。。)
(2)建立角色
(3)設定地形的導航網格
(3-1)選取全部的地形➜右邊static➜navigation static(靜態導航)
(3-2)然後到右邊的一個『navigation』視窗➜bake(就會產生導航網格了)
但是要先設定能夠通過導航行走agent的4個基本參數(半徑,身高,agent爬斜坡的斜率上限,agent跨階梯的step上限)
經驗:這些網格的➜bake➜step height要設定高點,例如0.9(發現,若是設定0.4,則待會的主角,無法爬上階梯)
(3-3)最後按下方:bake➜產生導航網格(淺藍色網格,代表成本1的網格)
(4)設定主角為agent➜add component➜navMesh agent
(5)建立主角的程式碼➜add component➜playerControl.cs
using UnityEngine.AI;
抓取代理組件
agent1 = this.GetComponent<NavMeshAgent>();

void Update()//{
//手觸控某個位置,agent1就會朝點的位置走過去
//判別按下滑鼠左鍵
if (Input.GetMouseButtonDown(0))
{
//射線取得點按位置的坐標
Ray ray1 = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit1;
//射線檢測
if (Physics.Raycast(ray1, out hit1) == true)
{
//取得點擊位置
Vector3 point1 = hit1.point;
//設定point1為導航目標點
agent1.SetDestination(point1);
}
}
}

【chp14.分數計算,記分系統】
範例14-1:呼叫另外c#檔案的show()函數顯示分數score(方法1:public拖曵設定cs程式碼掛載的物件)

☎ 兩個cs程式碼檔案,都可以顯示分數score
==>方法:呼叫另外c#檔案的show()函數顯示分數score
參考影片:How to Pass Variables Between Scripts in C#
參考網頁(附上程式碼):How to Pass Variables Between Scripts in C#

成果影片

1.如何兩個cs程式碼檔案,都可以顯示分數score
(1).錯誤做法:cs02程式碼,讀取cs01程式碼的public變數score
結果:只能夠讀取到score的起始值(0)
(2)正確做法:cs02程式碼,讀取cs01程式碼的public函數show1(-1)

2.如何cs02程式碼,讀取cs01程式碼的public函數show1()
設定另外一個cs01檔案物件
public cs01 readCs;
readCs.show1(-1);

3.如何設定UI/Text的值(score)
(1)注意:抓取UI物件,要先using UnityEngine.UI;
GameObject.Find("TextScore").GetComponent<Text>().text = "Score : " + score.ToString();

成果圖片1

步驟圖2步驟圖3

cs01程式碼
cs02程式碼

範例14-2:呼叫另外c#檔案的show()函數顯示分數score(方法2:GameObject.FindObjectOfType)

☎ 兩個cs程式碼檔案,都可以顯示分數score
==>方法:呼叫另外c#檔案的show()函數顯示分數score
參考影片:How to Pass Variables Between Scripts in C#
參考網頁(附上程式碼):How to Pass Variables Between Scripts in C#

成果影片

1.如何找到掛載某個Script腳本的GameObject?
Unity 提供了幾個方法可以找到關於是誰引用了物件(透過程式碼搜尋)
方法(1):一種是GameObject.FindGameObjectWithTag,此法可以根據GamObject所設定的Tag,直接把物件搜尋出來

方法(2):GameObject.FindObjectOfType<T>(),此法根據元件的類別直接搜尋,如果是Script腳本就直接輸入對應名稱
功能:根據型別(元件/自定義指令碼)查詢,並返回這個類。
如果沒有任何匹配該類型的物件,則返回 null。

方法(3):使用 gameObject.GetComponent,這種方法則要先理解子母物件的關係

2.如何查詢到專案裡面的cs01程式碼物件?
☎方法:GameObject.FindObjectOfType<程式碼名稱>()
☎範例:
private cs01 readCs;
readCs = GameObject.FindObjectOfType<cs01>();
.....
readCs.show1(-1);
☎優點:
若要搜尋程式碼物件(cs01),用FindObjectOfType<程式碼名稱>()是最簡單的方法

成果圖片1

步驟圖2步驟圖3

cs01程式碼
cs02程式碼

範例14-3:很多怪物攻擊主角,計算同一個score變數(方法3:GameObject.FindObjectOfType)

☎ 多個怪物的攻擊主角,都可以修改分數score
==>方法:呼叫另外c#檔案的show()函數顯示分數score
成果影片

1.如何找到掛載某個Script腳本的GameObject?
方法(2):GameObject.FindObjectOfType<T>(),此法根據元件的類別直接搜尋,如果是Script腳本就直接輸入對應名稱
功能:根據型別(元件/自定義指令碼)查詢,並返回這個類。
如果沒有任何匹配該類型的物件,則返回 null。

2.如何查詢到專案裡面的程式碼score.cs物件?
☎方法:GameObject.FindObjectOfType<程式碼名稱>()
☎範例:
//若是多個怪物prefabs,改成呼叫score.cs裡面的showScore()
GameObject.FindObjectOfType<score>().showScore(-3);

☎3.統一計算分數的程式碼score.cs:
using UnityEngine.UI;

public int score2 = 30;
public GameObject img_Over;
bool gameover = false;
public void showScore(int point)
{
score2 += point;
if(score2 < 0 && gameover ==false)
{
gameover = true;
//播放過關失敗音效
this.GetComponent<AudioSource>().Play();
img_Over.SetActive(true);
}
//注意:如果沒有using UnityEngine.UI;就無法抓到參數Text
GameObject.Find("Text_energy").GetComponent<Text>().text = "體力:" + score2.ToString();
}

成果影片
成果圖片1

步驟圖2步驟圖3

score.cs程式碼
enemy_greenp_manager.cs程式碼

【chp15.RPG的狀態機,主角攻擊怪物,怪物攻擊主角】
15-1:狀態機:設定角色的5種狀態

參考影片:RPG Enemy Set States 設置敵人的基本屬性和狀態

1.RPG的角色狀態設定:準備idle,走路walk,跳躍jump,攻擊attack,死亡die

(1).專業做法:使用列舉變數enum
範例:enum EnemyStatus {IDLE,WALK,JUMP,ATTACK,DIE}
應用方法:EnemyStatus.WALK
☎注意:enum的內容項目文字,前後不需要""
☎注意:設定enum,不需要=

2.☎狀態機的程式碼結構:
//設定角色的狀態列舉
public enum EnemyStatus { IDLE, WALK, JUMP,ATTACK, DIE };

public class enemy_greenp_manager : MonoBehaviour
{
//宣告一個public的狀態機變數
public EnemyStatus itsStatus;

//判被角色狀態函數
void SwitchStatus()
{
switch(itsStatus)
{
case EnemyStatus.IDLE:
break;
case EnemyStatus.WALK:
break;
case EnemyStatus.JUMP:
break;
case EnemyStatus.ATTACK:
break;
case EnemyStatus.DIE:
break;
}
}

void Update()
{
//隨時判別角色狀態
SwitchStatus();
}

步驟圖程式碼

15-2:如何判斷角色的狀態是預備態idle

(0)舉例:主角unitychan,觸碰link2就跳躍jump,導航就walk,到了目的地就idle
程式碼

☎步驟:
(1)設定導航網格navMesh,設定跳躍連接點offMeshLink,
(2)在主角unitychan設定程式碼playerControl.cs

☎(3)判別原地不動,顯示idle的程式思路:
(3-1)宣告prev_position變數:代表前一個幀率時,主角unitychan的位置
Vector3 prev_position = new Vector3(0,0,0);
(3-2)原理:在update裡面➜若主角最新的位置 = prev_position➜表示主角沒有移動了➜播放idle動畫(設定status=0)
if (GameObject.Find("unitychan").transform.position == prev_position)
{
GameObject.Find("unitychan").GetComponent<Animator>().SetInteger("status", 0);
}
...............
//最後一行,設定prev_position
prev_position = GameObject.Find("unitychan").transform.position;

(3-3)程式碼:
void Update()
{
bool isjump = false;
if (Input.GetMouseButtonDown(0))
{
Debug.Log(GameObject.Find("unitychan").GetComponent<Animator>().GetInteger("status"));
//射線取得點按位置的坐標
Ray ray1 = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit1;
//射線檢測
if(Physics.Raycast(ray1,out hit1)==true)
{
//取得點擊位置
Vector3 point1 = hit1.point;
//設定point1為導航目標點
agent1.SetDestination(point1);
//如果jump to (link2)則jump
if(hit1.collider.gameObject.name=="link2" || hit1.collider.gameObject.name == "door3")
{
...............
}
}
}
//注意:要先判斷Jump的case,否則永遠不會執行jump
if (isjump == true)
{
GameObject.Find("unitychan").GetComponent<Animator>().SetInteger("status", 2);
}
//如果原地不動,則status =0
else if (GameObject.Find("unitychan").transform.position == prev_position)
{
GameObject.Find("unitychan").GetComponent<Animator>().SetInteger("status", 0);
}
else//否則walk
{
GameObject.Find("unitychan").GetComponent<Animator>().SetInteger("status", 1);
}
//設定prev_position
prev_position = GameObject.Find("unitychan").transform.position;
}

☎(4)判別jump,顯示jump動畫的程式思路:
(4-1)宣告isjump變數:代表主角unitychan與特定link2物件是否碰撞,若是則jump
bool isjump = false;
(4-2)原理:在update裡面➜射線檢測if(Physics.Raycast(ray1,out hit1)➜若碰到link2➜if(hit1.collider.gameObject.name=="link2")➜則isjump = true
(4-3)程式碼:
void Update()
{
bool isjump = false;
if (Input.GetMouseButtonDown(0))
{
Debug.Log(GameObject.Find("unitychan").GetComponent<Animator>().GetInteger("status"));
//射線取得點按位置的坐標
Ray ray1 = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit1;
//射線檢測
if(Physics.Raycast(ray1,out hit1)==true)
{
//取得點擊位置
Vector3 point1 = hit1.point;
//設定point1為導航目標點
agent1.SetDestination(point1);
//如果jump to (link2)則jump
if(hit1.collider.gameObject.name=="link2")
{
//設定主角jump動畫(但是沒有效果),可能是update馬上被改成status=1
//GameObject.Find("unitychan").GetComponent<Animator>().SetInteger("status", 2);
//所以用一個isjump變數
isjump = true;
}
}
}
//注意:要先判斷Jump的case,否則永遠不會執行jump
if (isjump == true)
{
GameObject.Find("unitychan").GetComponent<Animator>().SetInteger("status", 2);
}

☎(5)判別碰撞物件,顯示過關win動畫的程式思路:
(5-1)宣告iscollide變數:代表主角unitychan與特定door3物件是否碰撞
bool iscollide = false;
(5-2)原理:在OnTriggerEnter裡面➜若主角最新的位置 = prev_position➜表示主角沒有移動了➜播放idle動畫(設定status=0)
(5-3)程式碼:
bool iscollide = false;
Vector3 prev_position = new Vector3(0,0,0);
private void OnTriggerEnter(Collider other)
{
if(other.name == "door3" && iscollide==false)
{
iscollide = true;
//播放過關音效
other.GetComponent<AudioSource>().Play();
//顯示過關畫面
img_Win.SetActive(true);
}
.............
}
☎(6)playerControl程式碼:
程式碼

15-3:如何判斷角色的狀態是攻擊態ATTACK

1.問題點:自動導航navMesh,navMeshAgent的角色攻擊,遇到的問題:
☎問題:enemy敵人若是由自動導航,這個agent_enemy,遇到目標物會自動避開,不會碰撞到
(1)遇到目標主角:會自動剎車,距離0,就會停止,所以不會碰撞
(2)遇到移動式的障礙物/牆壁,agent_enemy也會自動避開

2.RPG遊戲,如何在自動導航內,靠近時就攻擊➜要符合三個條件
(1)條件1:只要距離distance1 <2.5f,就攻擊
☎方法:在update內要隨時計算兩者的距離:float distance1 = Vector3.Distance(agentChan.transform.position, agentGreen.transform.position);

☎遇到新的問題:但是若是距離一旦靠近了,就會不斷攻擊(在update內,一秒內連續攻擊60次)
修改:要加上一個冷卻時間lastattackTime變數(例如2.0),每隔2秒才能再攻擊一次
☎方法:在update裡面:lastattackTime -= Time.deltaTime;

(2)條件2:只要冷卻時間已經小於0:lastattackTime < 0

(2)條件3:只要還沒有死:this.gameObject.GetComponent<Animator>().GetInteger("status") != 4) 就可以,開始攻擊
(4)程式碼架構:
if (lastattackTime < 0 && distance1 < 2.5f && this.gameObject.GetComponent<Animator>().GetInteger("status") != 4)
{
....
}

3.RPG的角色如何攻擊對方
(1)關鍵問題:在udapte裡面若是設定距離小2.5就攻擊,那麼1秒內會連續攻擊60次
改善方法:宣告一個lastattackTime變數,超過這個時間再攻擊第二次

(2)方法:
(A)宣告變數lastattackTime:攻擊冷卻時間(攻擊一次,必須再等幾秒才能再攻擊)
public float lastattackTime = 1.5f;

(B)在update裡面判別,計算enemy與主角unityChan的距離,靠近就刺

float distance1 = Vector3.Distance(agentChan.transform.position, agentGreen.transform.position);
if (lastattackTime < 0 && distance1 < 2.5f && this.gameObject.GetComponent<Animator>().GetInteger("status") != 4)
{
靠近主角,就刺 status = 14(或12)
this.gameObject.GetComponent<Animator>().SetInteger("status", 14);
//降低主角的體力
energy -= 3;
//顯示在畫面Text_energy
GameObject.Find("Text_energy").GetComponent<Text>().text = "體力:" + energy.ToString();
//播放hit/punch音效
this.GetComponent<AudioSource>().Play();
//重新設定lastattackTime = 0.5f
lastattackTime = 1.5f;
}

☎4.enemy_greenp_manager程式碼:
程式碼

範例15-4:實作enemy的四種狀態(預備idle,走路walk,攻擊attack,死亡die)

1.問題點:自動導航navMesh,navMeshAgent的角色攻擊,遇到的問題:
☎問題:enemy敵人若是由自動導航,這個agent_enemy,遇到目標物會自動避開,不會碰撞到
(1)遇到目標主角:會自動剎車,距離0,就會停止,所以不會碰撞
(2)遇到移動式的障礙物/牆壁,agent_enemy也會自動避開

2.RPG遊戲,如何在自動導航內,靠近時就攻擊➜要符合三個條件
(1)條件1:只要距離distance1 <2.5f,就攻擊
☎方法:在update內要隨時計算兩者的距離:float distance1 = Vector3.Distance(agentChan.transform.position, agentGreen.transform.position);

☎遇到新的問題:但是若是距離一旦靠近了,就會不斷攻擊(在update內,一秒內連續攻擊60次)
修改:要加上一個冷卻時間lastattackTime變數(例如2.0),每隔2秒才能再攻擊一次
☎方法:在update裡面:lastattackTime -= Time.deltaTime;

(2)條件2:只要冷卻時間已經小於0:lastattackTime < 0

(2)條件3:只要還沒有死:this.gameObject.GetComponent<Animator>().GetInteger("status") != 4) 就可以,開始攻擊
(4)程式碼架構:
if (lastattackTime < 0 && distance1 < 2.5f && this.gameObject.GetComponent<Animator>().GetInteger("status") != 4)
{
....
}

3.RPG的角色如何攻擊對方
(1)關鍵問題:在udapte裡面若是設定距離小2.5就攻擊,那麼1秒內會連續攻擊60次
改善方法:宣告一個lastattackTime變數,超過這個時間再攻擊第二次

(2)方法:
(A)宣告變數lastattackTime:攻擊冷卻時間(攻擊一次,必須再等幾秒才能再攻擊)
public float lastattackTime = 1.5f;

(B)在update裡面判別,計算enemy與主角unityChan的距離,靠近就刺

float distance1 = Vector3.Distance(agentChan.transform.position, agentGreen.transform.position);
if (lastattackTime < 0 && distance1 < 2.5f && this.gameObject.GetComponent<Animator>().GetInteger("status") != 4)
{
靠近主角,就刺 status = 14(或12)
this.gameObject.GetComponent<Animator>().SetInteger("status", 14);
//降低主角的體力
energy -= 3;
//顯示在畫面Text_energy
GameObject.Find("Text_energy").GetComponent<Text>().text = "體力:" + energy.ToString();
//播放hit/punch音效
this.GetComponent<AudioSource>().Play();
//重新設定lastattackTime = 0.5f
lastattackTime = 1.5f;
}

☎4.成果影片
成果+設定步驟影片

5.下載素材檔案:
enemy角色下載(Battle Wizard Poly Art)
手榴彈grenade物件(asset store)
Effect textures and prefabs(煙霧動畫prefabs物件)asset store

氣化聲音(hiss)
揮擊木棍聲音(Whoosh)
過關成功聲音(win)

成果圖片
步驟圖1步驟圖2步驟圖3步驟圖4步驟圖5步驟圖6步驟圖7步驟圖8步驟圖9

5.程式碼:
doormove程式碼
playerControl程式碼
enemy_greenp_manager程式碼
gameover_manager程式碼

15-5:如何怪物死亡後,不再繼續自動導航追踪主角(還要設定animator狀態,設定5秒後消失)

1.當怪物死亡後,除了要設定Animator的狀態外,還要取消追踪主角,否則死亡的怪物,還好繼續移動:
☎(1)當怪物死亡後,要設定Animator的狀態:
this.gameObject.GetComponent<Animator>().SetInteger("status", 4);

☎(2)當怪物死亡後,還要取消自動導航追踪主角,否則死亡的怪物,還好繼續移動
方法1:把原本追逐主角(SetDestination),改成追踪自己的位置
agentGreen.SetDestination(agentGreen.transform.position);

方法2:把navMeshAgent.Stop()
agentGreen.Stop();

方法3:不設定,就是還是繼續追踪主角
原因:有時候很多怪物同時死亡,就會造成道路堵塞,後面的怪物就無法追踪主角


☎(3)當怪物死亡後,可以設定怪物在5秒後消失
☎5秒後消失物件的設定方法:Destroy(this.gameObject)

Invoke("removeObject", 5.0f);
.....
private void removeObject()
{
Destroy(this.gameObject);
}


2.程式碼:
enemy_greenp_manager程式碼

範例15-6:兩種怪物攻擊主角,主角按炸彈來引爆炸彈

1.顯示爆炸動畫/播放音效,打開爆炸box collider,3秒後關閉

//大爆炸動畫prefab
public GameObject WFX_Nuke;
//大爆炸音效
private GameObject wfx1;

bool isfire = false;

private void OnTriggerEnter(Collider other)
{
if (other.name == "button_fire" && isfire == false)
{
isfire = true;

//爆炸畫面(顯示在根目錄null)
wfx1 = Instantiate(WFX_Nuke, null);
//設定爆炸畫面的位置
wfx1.transform.position = GameObject.Find("Bomb").transform.position;

//把炸彈的box_collider打開,好讓炸彈碰撞怪物,但是只有打開3秒
GameObject.Find("Bomb").GetComponent<BoxCollider>().enabled = true;

//3秒後,關閉炸彈的box_collider
Invoke("TurnOffBoxCollider", 3);
}
}

2.怪物碰撞到Bomb的box collider,就設定狀態status = die
private void OnTriggerEnter(Collider other)
{
if (other.name == "Bomb" && isDie == false)
{
//顯示煙霧動畫,放在根目錄,但是只有出現2秒(粒子系統只設定2秒),粒子會自動消失,不需要刪除
node_smoke = Instantiate(somke_prefab, null);

//設定動畫顯示的坐標
node_smoke.transform.position = this.transform.position;
//播放音效
node_smoke.GetComponent<AudioSource>().Play();

//設定animator的status=4,躺下
this.gameObject.GetComponent<Animator>().SetInteger("status", 4);

//死亡
isDie = true;
}


下載爆炸prefab動畫(WFX_Nuke)
下載爆炸音效(nuclear_explode_aduio)
成果影片
成果圖片1

步驟圖2步驟圖3步驟圖4步驟圖5步驟圖6步驟圖7步驟圖8步驟圖9
playerControl.cs程式碼
enemy_greenp_manager.cs程式碼



【chp36.實作打怪的3D遊戲】
範例6-1:建立3D場景

成果圖片
下載本project成果檔案
範例6-1:建立3D場景

範例教學:
1.Setting up 3D Beginner:
https://learn.unity.com/tutorial/setting-up-3d-beginner?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-2:建立主角john及其動作動畫

成果圖片
下載本project成果檔案
範例6-2:建立主角john及其動作動畫

範例教學:
2.The Player Character: Part 1:
https://learn.unity.com/tutorial/the-player-character-part-1?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb#5caf6520edbc2a08d53c79fa

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-3:用Unity動作控制器Animator Controller來設定主角john

成果圖片
下載本project成果檔案
範例6-3:用Unity動作控制器Animator Controller來設定主角john

範例教學:
3.Player Character: Part 2:
https://learn.unity.com/tutorial/player-character-part-2-the-script?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-4:建立環境,與複雜場景的地形

成果圖片
下載本project成果檔案
範例6-4:建立環境,與複雜場景的地形

範例教學:
4.The Environment:
https://learn.unity.com/tutorial/the-environment?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-5:三種追踪角色的攝影機技巧:攝影機追踪法,程式碼追踪法,還Cinemachine套件追踪法)

成果圖片
下載本project成果檔案
範例6-5:三種追踪角色的攝影機技巧:攝影機追踪法,程式碼追踪法,還Cinemachine套件追踪法)

範例教學:
5.The Camera:
https://learn.unity.com/tutorial/the-camera?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-6:遊戲結束的設定

成果圖片
下載本project成果檔案
範例6-6:遊戲結束的設定

範例教學:
6.Ending the Game:
https://learn.unity.com/tutorial/ending-the-game?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-7: 建立建立怪物及其動作動畫,寫c#程式碼控制主角joh與怪物的移動與旋轉

成果圖片
下載本project成果檔案
範例6-7: 建立建立怪物及其動作動畫,寫c#程式碼控制主角joh與怪物的移動與旋轉

範例教學:
7.Enemies, Part 1: Static Observers:
https://learn.unity.com/tutorial/enemies-part-1-static-observers?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-8:設定怪物的移動路徑(設定導航網格)

成果圖片
下載本project成果檔案
範例6-8:設定怪物的移動路徑(設定導航網格)

範例教學:
8.Enemies, Part 2: Dynamic Observers:
https://learn.unity.com/tutorial/enemies-part-2-dynamic-observers?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-9:使用導航網格代理(NavMeshAgent),讓怪物自動行走

成果圖片
下載本project成果檔案
範例6-9:使用導航網格代理(NavMeshAgent),讓怪物自動行走

範例教學:
9.Audio:
https://learn.unity.com/tutorial/audio-ayf?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-10:C#程式碼設定打擊的武器與子彈顯示方式

成果圖片
下載本project成果檔案
範例6-10:C#程式碼設定打擊的武器與子彈顯示方式

範例教學:
1.Setting up 3D Beginner:
https://learn.unity.com/tutorial/setting-up-3d-beginner?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb 2.The Player Character: Part 1:
https://learn.unity.com/tutorial/the-player-character-part-1?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb#5caf6520edbc2a08d53c79fa
3.Player Character: Part 2:
https://learn.unity.com/tutorial/player-character-part-2-the-script?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
4.The Environment:
https://learn.unity.com/tutorial/the-environment?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
5.The Camera:
https://learn.unity.com/tutorial/the-camera?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
6.Ending the Game:
https://learn.unity.com/tutorial/ending-the-game?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
7.Enemies, Part 1: Static Observers:
https://learn.unity.com/tutorial/enemies-part-1-static-observers?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
8.Enemies, Part 2: Dynamic Observers:
https://learn.unity.com/tutorial/enemies-part-2-dynamic-observers?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
9.Audio:
https://learn.unity.com/tutorial/audio-ayf?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
10.Build, Run, Distribute:
https://learn.unity.com/tutorial/build-run-distribute-1?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
11.youtube:
https://www.youtube.com/watch?v=wH-CQsrZF4U&list=PLsEC4qT8YxBJ2jR0epcQTnUh89OOFpZ-I&index=9
1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-11:C#程式碼設定打擊怪物時分數計算與遊戲結束判斷

成果圖片
下載本project成果檔案
範例6-11:C#程式碼設定打擊怪物時分數計算與遊戲結束判斷

範例教學:
1.Setting up 3D Beginner:
https://learn.unity.com/tutorial/setting-up-3d-beginner?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb 2.The Player Character: Part 1:
https://learn.unity.com/tutorial/the-player-character-part-1?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb#5caf6520edbc2a08d53c79fa
3.Player Character: Part 2:
https://learn.unity.com/tutorial/player-character-part-2-the-script?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
4.The Environment:
https://learn.unity.com/tutorial/the-environment?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
5.The Camera:
https://learn.unity.com/tutorial/the-camera?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
6.Ending the Game:
https://learn.unity.com/tutorial/ending-the-game?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
7.Enemies, Part 1: Static Observers:
https://learn.unity.com/tutorial/enemies-part-1-static-observers?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
8.Enemies, Part 2: Dynamic Observers:
https://learn.unity.com/tutorial/enemies-part-2-dynamic-observers?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
9.Audio:
https://learn.unity.com/tutorial/audio-ayf?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
10.Build, Run, Distribute:
https://learn.unity.com/tutorial/build-run-distribute-1?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
11.youtube:
https://www.youtube.com/watch?v=wH-CQsrZF4U&list=PLsEC4qT8YxBJ2jR0epcQTnUh89OOFpZ-I&index=9
1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-12:音效設定

成果圖片
下載本project成果檔案
範例6-12:音效設定

範例教學:
9.Audio:
https://learn.unity.com/tutorial/audio-ayf?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-13:輸出成最後的各種平台遊戲執行檔(視窗版,android版,網頁版)

成果圖片
下載本project成果檔案
範例6-13:輸出成最後的各種平台遊戲執行檔(視窗版,android版,網頁版)

範例教學:
10.Build, Run, Distribute:
https://learn.unity.com/tutorial/build-run-distribute-1?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb

1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

範例6-14:用Unity動作控制器Animator Controller來設定主角joh與怪物的各種動作Animations動畫

成果圖片
下載本project成果檔案
範例6-4:用Unity動作控制器Animator Controller來設定主角joh與怪物的各種動作Animations動畫

官網範例教學:
1.Setting up 3D Beginner:
https://learn.unity.com/tutorial/setting-up-3d-beginner?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb 2.The Player Character: Part 1:
https://learn.unity.com/tutorial/the-player-character-part-1?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb#5caf6520edbc2a08d53c79fa
3.Player Character: Part 2:
https://learn.unity.com/tutorial/player-character-part-2-the-script?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
4.The Environment:
https://learn.unity.com/tutorial/the-environment?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
5.The Camera:
https://learn.unity.com/tutorial/the-camera?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
6.Ending the Game:
https://learn.unity.com/tutorial/ending-the-game?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
7.Enemies, Part 1: Static Observers:
https://learn.unity.com/tutorial/enemies-part-1-static-observers?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
8.Enemies, Part 2: Dynamic Observers:
https://learn.unity.com/tutorial/enemies-part-2-dynamic-observers?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
9.Audio:
https://learn.unity.com/tutorial/audio-ayf?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
10.Build, Run, Distribute:
https://learn.unity.com/tutorial/build-run-distribute-1?uv=2020.2&projectId=5caf65ddedbc2a08d53c7acb
11.youtube:
https://www.youtube.com/watch?v=wH-CQsrZF4U&list=PLsEC4qT8YxBJ2jR0epcQTnUh89OOFpZ-I&index=9
1.建立場景
(1)下載city場景
到asset store/輸入搜尋:city
設定price=0的過濾條件
找到:CITY package
download/import

 
應用部分
chp2.第一個3D專案

觀看

本範例的成果圖片

下載

下載本章project成果檔案

1.new project
類型:選3D

2.在Assects
滑鼠右鍵:create→Folder:image

3.下載素材圖片

4.把pic目錄裡面的檔案拉到image裡面
成果圖片

5.建立一個3D平面(背板)
GameObject→3D Object→plane
修改名稱 = BG
調整位置,大小
Position(x,y,z) = 0,1,0
Rotation(x,y,z) = 90,180,0
Scale(x,y,z) = 2.3,1,1.2
成果圖片

6.把3D文件BG加上材質圖片
把image/bg1.png拖曵到inspector屬性表最下面的add component
成果圖片

7.觀看目前效果
按:Game
或按:▶play

8.建立一個3D平面(title)
GameObject→3D Object→plane
修改名稱 = title
調整位置,大小
Position(x,y,z) = 0,3.3,-0.01
Rotation(x,y,z) = 90,180,0
Scale(x,y,z) = 1.024,1,0.128

成果圖片

9.觀看目前效果
按:Game
或按:▶play

10.把招牌材質去背
title→Inspector→屬性表最下面的地球→三角形
修改rendering mode→Cutout模式
成果圖片

8.加入一個按鈕:start
建立一個3D平面(Button_start)
GameObject→3D Object→plane
修改名稱 = Button_start
調整位置,大小
Position(x,y,z) = 0,0.46,-0.01
Rotation(x,y,z) = 90,180,0
Scale(x,y,z) = 0.512,1,0.126
成果圖片

9.加入一個按鈕:about
建立一個3D平面(Button_about)
GameObject→3D Object→plane
修改名稱 = Button_about
調整位置,大小
Position(x,y,z) = 0,-1.14,-0.01
Rotation(x,y,z) = 90,180,0
Scale(x,y,z) = 0.512,1,0.126
成果圖片

10.加入一個按鈕:about
建立一個3D平面(Button_about)
GameObject→3D Object→plane
修改名稱 = Button_about
調整位置,大小
成果圖片

10.加入一個卡通主角:act1
建立一個3D平面
GameObject→3D Object→plane
修改名稱 = act1
調整位置,大小
Position(x,y,z) = 4.72,-2.25,-0.01
Rotation(x,y,z) = 90,180,0
Scale(x,y,z) = 0.512,1,0.512

把材質去背
title→Inspector→屬性表最下面的地球→三角形
修改rendering mode→Cutout模式
成果圖片

11.修正圖片顯示時模糊
方法:設定材質壓縮和大小
(1)先點選assets/images/裡面的button_end
(2)inspector找default;
max Size = 256
Format = Truecolor(或32bits Color)
按Apply

12.儲存遊戲場景
File→Save
若是有錯誤信息:you must exit play mode to save the scene
原因:要取消play 模式▶

13.調整main camera攝影機的位置與角度
注意兩個物件:攝影機坐標物件,聚焦點符號
可以點選右上坐標軸,切換xyz的各種平面
成果圖片

13.調整Directional Light方向太陽光的位置與角度
功用:可以用來設定環境太陽光
設定燈光強度:intensity=2(稍強)
設定燈光色彩:紅色
成果圖片

14.增加一個spot light
(先把Directional Light的intensity=1)
功用:可以用來設定探照燈
GameObject→3D Object→light→spont Light
設定燈光強度:intensity=2(稍強)
移動位置,調整角度
成果圖片
成果圖片

注意:中心點切換
(1)Pivot/Center:切換成透過『樞軸』/『中心點』來影響物件
(2)Local/Global:切換成透過『以此物件』/『或是世界』作為主視角

 
 
chp3.籃球遊戲的材質貼圖

觀看

本範例的成果圖片

下載

下載本章project成果檔案

1.new project
類型:選3D
name:exp3-basketball

2.在Assects加入3D模型與圖片
滑鼠右鍵:create→Folder:models

3.下載素材圖片

4.把裡面的檔案拉到models目錄裡面
籃框3D模型:hoop.obj
籃球3D模型:basketball.FBX
背景圖片:bg.jpg
籃球圖片:basketball-texture.jpg

5.把籃框3D模型:hoop.obj拉到場景scene的Hierarchy層次視窗內

6.設定籃框3D模型:hoop
修改名稱 = BG
調整位置,大小
Position(x,y,z) = 0,3.45,0
Rotation(x,y,z) = 270,180,0
Scale(x,y,z) = 0.01,0.01,0.01
成果圖片

7.加入籃球(basketball.FBX)並設定位置大小
調整位置,大小
Position(x,y,z) = 0,0,0
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 0.005,0.005,0.005
成果圖片

8.修正籃球材質圖片的壓縮
(1)先點選assets/models/裡面的basketball-texture.jpg
(2)inspector找default;
max Size = 256
Format = Truecolor
按Apply

9.把籃球材質圖片拖曵到籃球物件(basketball.FBX)
(1)先放大zoom in(使用滑鼠中鍵滾動)
(2)把籃球材質圖片拖曵到籃球物件
成果圖片

但是籃球的紋路貼法很奇怪
(目前像是金屬材質,會反光,要改成橡膠材質)

10.設定籃球物件(basketball.FBX)的材質是橡膠
(1)hierarchy點選basketball下方的三角形▼
(1)inspector找basketball-texture→三角形▼
橡膠材質 = 反光度0 = smoothness = 0
籃球模型因為被縮小0.05
設定titling (x=0.05,y=0.05)

成果圖片

11.觀看目前效果
按:Game
或按:▶play

成果圖片

12.儲存專案

13.設定背景平面
(1)建立一個3D平面(title)
GameObject→3D Object→plane
修改名稱 = BG
調整位置,大小
Position(x,y,z) = 0,0,37.2
Rotation(x,y,z) = 90,180,0
Scale(x,y,z) = 14,7,7

(2)把背景圖片bg.jpg拖曵到BG平面
成果圖片

14.調整Directional Light方向太陽光的位置與角度
功用:可以用來設定環境太陽光
成果圖片
成果圖片

15.設定籃球為自由落體的物理動作
選取basketball物件→component→Physics→Rigidbody(物理剛體)
成果圖片
按:▶play
成果圖片
籃球會落下

16.移動籃球到籃框上方,自由落下卻沒有反彈
成果圖片

15.設定籃球有碰撞外框的特性
選取basketball物件→component→Physics→Sphere Collider(球體碰撞)
設定Radius半徑 = 100
成果圖片

16.設定籃框有碰撞外框的特性
選取hoop物件→component→Physics→Mesh Collider(3D網狀碰撞)
設定Radius半徑 = 100
成果圖片

17.測試,按:▶play
成果圖片
籃球會反彈向旁邊移動

18.偵測籃球若是投入藍框,就加1分
方法:加入一個看不見(透明)的cube物件,若是cube被碰撞了,就表示有得分
(1)新增GameObject→3D Object→cube
設定名稱:PointEvent
調整位置,大小
Position(x,y,z) = -0.12,0.53,0
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 1,1,1

(2)設定碰撞事件
is Trigger打勾

(3)設定不顯示
Mesh Renderer取消打勾

成果圖片

19.開始寫程式:替籃球加上score.cs
選取basketball物件→Add component→Scripts→選取Score
成果圖片

20.測試
在畫面點按一下,籃球就會被投出
左上角會顯示成績score分數
成果圖片
成果圖片

21.score.cs程式說明
程式碼內容

22.輸出成pc版本的遊戲
File→Bulid Settings
設定參數
x86-24
成果圖片
成果圖片
build and Run
選擇輸出的目錄:exp3-basketball
成果圖片

23.輸出成web版本的遊戲
File→Bulid Settings
設定參數
成果圖片
build and Run

結果:打開I.E.
Please note that your browser is not currently supported for this Unity WebGL content.
Press OK if you wish to continue anyway.
Your browser does not support WebAssembly.

打開chrome
成果圖片
成果圖片

 
 
chp4.使用c#寫程式碼:在label顯示(新年快樂,計算器,目前日期時間)

觀看

本範例的成果圖片

下載

下載本章project成果檔案

1.new project
類型:選3D
name:exp4-3d-label

2.在Assects
滑鼠右鍵:create→Folder:image

3.下載素材圖片

4.把pic目錄裡面的background檔案拉到image裡面

5.儲存場景名稱
File→Save Scene As:主畫面
成果圖片

6.建立一個3D平面(背板)
GameObject→3D Object→plane
修改名稱 = 背景
調整位置,大小
Position(x,y,z) = 0,1,0
Rotation(x,y,z) = 90,180,0
Scale(x,y,z) = 1,1,1

6.把3D文件BG加上材質圖片
把image/background.png拖曵到inspector屬性表最下面的add component
成果圖片

7.觀看目前效果
按:Game
或按:▶play
成果圖片

5.下載 visual studio code
https://code.visualstudio.com/download

6.安裝 .NET Core SDK
(1)因為我們的 Unity 腳本使用 C# 語言來開發,所以必須安裝 .NET Core SDK 才能讓 VS Code 正常運作。
(2)前往 .NET Core SDK 官網下載執行檔,完成安裝。
https://dotnet.microsoft.com/download
成果圖片

6.在Visual Studio Code 擴充功能
(1)到 Extensions 頁面,
(2)分別搜尋並安裝 C# 與 Debugger for Unity 兩項插件。
成果圖片
成果圖片

6.在Unity設定擴充功能
Edit > Preferences > External Tools,
將 External Script Editor 的設定值修改為 Visual Studio Code

成果圖片

如果找不到 Visual Studio Code 選項的話,可以手動指定執行檔,路徑位於:
%appdata%/../Local/Programs/Microsoft VS Code

7.在unity的主畫面場景新增一個Text(ui物件)
(1)在hierarchy視窗的空白處,滑鼠右鍵→UI→Text
修改名稱=Textbox1
Position(x,y,z) = -10,50,0
FontSize= 20
Color = red
成果圖片
成果圖片

8.在unity裡面寫一個c#程式
(1)在Assets視窗裡面,滑鼠右鍵→Create→c# script
一個c#也是一個component
(2)名稱:script1

9.在unity建立一個UI控制物件
(1)在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty
修改名稱:UIObject
把Assets視窗裡面的script1,拖曵到UIObject的add component
(2)結果:場景裡面的UIObject,就會連結到c# script1程式

10.開始寫script1程式
(1)到Assets視窗的script1
(2)double click這個程式物件(script1)
結果
(4)打開vs code
程式碼內容

(5)宣告一個Text類別的變數:label1
(注意:但是因為Text是顯示在畫面的UI變數,所以要先using UnityEngine.UI;)
using UnityEngine.UI;
...
...
public Text lable1;
void Start()

(6)顯示新年快樂
程式碼內容

11.把場景裡面的textbox1,連結到UIscript1裡面的label1 原理:因為script1裡面宣告為public的變數,都會顯示到場景裡面的UIobject 方法:把textbox1拖曵到label1裡面 成果圖片
12.觀看結果 (1)新年快樂: lable1.text = "新年快樂"; (注意:text要小寫) play: 成果圖片

(2)若是顯示目前計算器的數字 lable1.text = Time.time.ToString(); (注意:text,time要小寫) 成果圖片

(3)若是顯示目前日期時間 lable1.text = System.DateTime.Now.ToString(); 成果圖片
(或是先using System)

 
 
chp5.使用c#寫程式碼:顯示兩數相加的結果(三個InputField)

觀看

本範例的成果圖片

下載

下載本章project成果檔案

1.new project
類型:選3D
name:exp5-3d-add

2.在Assects
滑鼠右鍵:create→Folder:image

3.下載素材圖片

4.把pic目錄裡面的background檔案拉到image裡面

5.儲存場景名稱
File→Save Scene As:主畫面

6.建立一個3D平面(背板)
GameObject→3D Object→plane
修改名稱 = 背景
調整位置,大小
Position(x,y,z) = 0,1,0
Rotation(x,y,z) = 90,180,0
Scale(x,y,z) = 2,1,1

7.把3D文件BG加上材質圖片
把image/background.png拖曵到inspector屬性表最下面的add component
成果圖片

8.在unity的主畫面場景新增1個InputField(ui物件)
(1)在hierarchy視窗的空白處,滑鼠右鍵→UI→InputField
成果圖片

修改名稱=InputField-num1
Position(x,y,z) = -140,20,0
width = 60
text = +
成果圖片

(2)在hierarchy視窗的空白處,滑鼠右鍵→UI→Text
修改名稱=add
Position(x,y,z) = -25,15,0
FontSize= 25
Color = red
成果圖片

(3)在hierarchy視窗的空白處,滑鼠右鍵→UI→InputField
修改名稱=InputField-num2
Position(x,y,z) = -40,20,0
width = 60
成果圖片

(4)在hierarchy視窗的空白處,滑鼠右鍵→UI→Text
修改名稱=equal
Position(x,y,z) = 90,15,0
FontSize= 25
Color = red
text = =
成果圖片

(5)在hierarchy視窗的空白處,滑鼠右鍵→UI→InputField
修改名稱=InputField-num3
Position(x,y,z) = 80,20,0
width = 60
成果圖片

9.在unity裡面寫一個c#程式
(1)在Assets視窗裡面,滑鼠右鍵→Create→c# script
一個c#也是一個component
(2)名稱:script1

10.在unity建立一個UI控制物件
(1)在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty
修改名稱:UIscript
把Assets視窗裡面的script1,拖曵到UIscript的add component
(2)結果:場景裡面的UIscript,就會連結到c# script1程式

11.開始寫script1程式
(1)到Assets視窗的script1
(2)double click這個程式物件(script1)
結果
(4)打開vs code

(5)宣告三個InputField類別的變數:num1,num2,num3
(注意:但是因為Text是顯示在畫面的UI變數,所以要先using UnityEngine.UI;)
程式碼內容

12.把場景裡面的InputField-num1~3,連結到UIscript1裡面的num1,num2,num3
原理:因為script1裡面宣告為public的變數,都會顯示到場景裡面的UIscript
方法:把InputField-num1拖曵到num1裡面
成果圖片

12.計算相加
void Update()
{
int a1 = int.Parse(num1.text);
int a2 = int.Parse(num2.text);
int a3 = a1 + a2;
num3.text = a3.ToString();
}
注意1:Parse,P大寫

13.測試結果:
成果圖片

14.加上按鈕
在hierarchy視窗的空白處,滑鼠右鍵→UI→button
Position(x,y,z) = 0,-30,0
normal color顏色=黃色
press color顏色=綠色
修改名稱=計算(在hierarchy視窗的button→下一個階層text)
成果圖片

15.設定button的on click事件程式是UIscript物件
(1)先點選button→找on click事件區域
(2)拉UIscript物件→到button的on click事件
成果圖片

16.寫script1程式碼
程式碼內容

17.到button的on click事件程式,選取doadd()
(1)先點選button→找on click事件區域
(2)點選no function→找script1→doadd()
成果圖片

18.測試play
成果圖片

 
 
chp6.使用c#寫程式碼:兩個數字if比較大小(2個inputField,一個button)

觀看

本範例的成果圖片

下載

下載本章project成果檔案

1.new project
類型:選3D
name:exp6-3d-if

2.在Assects
滑鼠右鍵:create→Folder:image

3.下載素材圖片

4.把pic目錄裡面的background檔案拉到image裡面

5.儲存場景名稱
File→Save Scene As:主畫面

6.建立一個3D平面(背板)
GameObject→3D Object→plane
修改名稱 = 背景
調整位置,大小
Position(x,y,z) = 0,1,0
Rotation(x,y,z) = 90,180,0
Scale(x,y,z) = 2,1,1

7.把3D文件BG加上材質圖片
把image/background.png拖曵到inspector屬性表最下面的add component

8.在unity的主畫面場景新增1個InputField(ui物件)
(1)在hierarchy視窗的空白處,滑鼠右鍵→UI→InputField
修改名稱=InputField-num1
Position(x,y,z) = -140,0,0
width = 80

(3)加上按鈕
在hierarchy視窗的空白處,滑鼠右鍵→UI→button
改變名稱=Buttoncompare
Position(x,y,z) = 0,0,0
normal color顏色=黃色
press color顏色=紫色
text = 比較大小

(4)在hierarchy視窗的空白處,滑鼠右鍵→UI→InputField
在hierarchy視窗的空白處,滑鼠右鍵→UI→InputField
修改名稱=InputField-num2
Position(x,y,z) = 140,0,0
width = 80

成果圖片

9.在unity裡面寫一個c#程式
(1)在Assets視窗裡面,滑鼠右鍵→Create→c# script
一個c#也是一個component
(2)名稱:script1

10.在unity建立一個UI控制物件
(1)在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty
修改名稱:UIscript
把Assets視窗裡面的script1,拖曵到UIscript的add component
(2)結果:場景裡面的UIscript,就會連結到c# script1程式

11.開始寫script1程式
(1)到Assets視窗的script1
(2)double click這個程式物件(script1)
結果
(4)打開vs code

(5)宣告三個InputField類別的變數:num1,num2,num3
宣告一個Button類別的變數:btn
宣告一個Button子類別的文字Text變數:btn_text

(注意:但是因為Text是顯示在畫面的UI變數,所以要先using UnityEngine.UI;)
程式碼內容

12.把場景裡面的InputField-num1~3,連結到UIscript1裡面的num1,num2,num3
把場景裡面的Buttoncompare,連結到UIscript1裡面的Btn
把場景裡面的Buttoncompare-Text,連結到UIscript1裡面的btn_txt
原理:因為script1裡面宣告為public的變數,都會顯示到場景裡面的UIscript
方法:把InputField-num1拖曵到num1裡面.....

成果圖片

13.比較大小 程式碼內容
注意1:若要設定按鈕的文字,
(1)錯誤方法:
public Button btn;
btn.text = "大於";

(2)正確方法1:
public Button btn;
public Text btn_text;

到Scene
把場景裡面的Buttoncompare,連結到UIscript1裡面的Btn
把場景裡面的Buttoncompare-Text,連結到UIscript1裡面的btn_txt

然後
btn_text.text = "大於";

(3)正確方法2:
完全不需要宣告public Button btn;
只要寫這行即可
GameObject.Find("ButtonCompare").GetComponentInChildren<Text>().text = "大於";

14.設定Buttoncompare的on click事件程式是UIscript物件
(1)先點選Buttoncompare→找on click事件區域
(2)拉UIscript物件→到Buttoncompare的on click事件
(3)no function→選script1→選comparenum()

15.測試結果:
成果圖片

 
 
chp7.使用c#寫程式碼:不宣告public變數,計算圓周長(1個inputField,一個button,一個Text)

觀看

本範例的成果圖片

下載

下載本章project成果檔案

1.new project
類型:選3D
name:exp7-3d-circle

2.在unity的主畫面場景新增1個InputField(ui物件)
(1)在hierarchy視窗的空白處,滑鼠右鍵→UI→InputField
修改名稱=InputField-num1
Position(x,y,z) = 0,40,0

(3)加上按鈕
在hierarchy視窗的空白處,滑鼠右鍵→UI→button
改變名稱=Button
Position(x,y,z) = 0,0,0
子層-text = 計算圓周長

(4)在hierarchy視窗的空白處,滑鼠右鍵→UI→Text
修改名稱=Text-result
Position(x,y,z) = 0,-40,0
成果圖片

3.在unity裡面寫一個c#程式
(1)在Assets視窗裡面,滑鼠右鍵→Create→c# script
一個c#也是一個component

(2)名稱:script1

4.在unity建立一個UI控制物件
(1)在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty
修改名稱:UIscript
把Assets視窗裡面的script1,拖曵到UIscript的add component
(2)結果:場景裡面的UIscript,就會連結到c# script1程式

5.開始寫script1程式
(1)到Assets視窗的script1
(2)double click這個程式物件(script1)
結果
(4)打開vs code

(5)寫一個函數docircle()
程式碼內容

6.設定Button的on click事件程式是UIscript物件
(1)先點選Button→找on click事件區域
(2)拉UIscript物件→到Button的on click事件
(3)no function→選script1→選docircle()

7.計算圓周長script1
程式碼內容

8.注意1:不需要宣告public變數
(1)如何取得場景裡面的InputField-num1物件:
GameObject.Find("InputField-num1").GetComponent()

(2)如何取得場景裡面的Text-result物件:
GameObject.Find("Text-result").GetComponent<Text>();

(3)如何取得場景裡面的Button-do物件:
GameObject.Find("Button-do").GetComponent

 
 
chp8.在OnGUI圖形使用者介面顯示元件
目錄 GUI常見基礎控制項 exp8_1:顯示目前日期時間 exp8_2:驗證登入的帳號密碼 exp8_3:計算兩個數字相加
GUILayout自動佈局常用指令 exp8_4:GUILayout自動佈局

1.GUI功能:
(1)GUI是圖形使用者介面 GraphicUser Interface的縮寫,經常簡稱為UI,是遊戲互動不可缺少的設計元素。
(2)遊戲透過 UI 傳遞各種訊息給玩家,例如目前的分數、擁有多少金錢或物品,也可以製作供操作的選單。
(3)GUI技術是古老的技術,但Unity5.x之後並沒有取消這種UI傳統的技術。
(4)Unity4.6出現的新的UI技術稱之為UGUI,主要是為了重新定義UI的技術規範,統一之前UI外掛程式繁多,混雜,標準不統一的混亂局面。
(5)UI是遊戲組成的重要部分,遊戲的很多操作直接通過UI控制。無論攝像機拍到的圖像怎麼變幻,GUI永遠顯示在螢幕上,不受變形,碰撞,光照等資訊影響。
(6)寫GUI腳本,必須注意兩個重要特徵:
(7)GUI腳本控制項必須定義在指令檔的OnGUI事件函數中
(8)架構如下
程式碼內容

2.常見基礎控制項使用
GUI基本的控制項如下圖所示:
GUI基本的控制項
程式碼內容

3.範例exp8-1:顯示成績分數,顯示目前日期時間
本範例的成果圖片
下載成果範例檔案

(1)在unity裡面寫一個c#程式
在Assets視窗裡面,滑鼠右鍵→Create→c# script
名稱:script1
(2)在unity建立一個UI控制物件
在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty
修改名稱:UI
(3)把Assets視窗裡面的script1,拖曵到UI的add component
成果圖片

(4)撰寫程式碼:
程式碼內容
(5)觀看目前效果,按:▶play
成果圖片

4.範例exp8-2:驗證登入的帳號密碼
本範例的成果圖片
下載成果範例檔案

(1)在unity裡面寫一個c#程式
在Assets視窗裡面,滑鼠右鍵→Create→c# script
名稱:script1
(2)在unity建立一個UI控制物件
在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty
修改名稱:UI
(3)把Assets視窗裡面的script1,拖曵到UI的add component
成果圖片

(4)撰寫程式碼:
程式碼內容

(5)觀看目前效果,按:▶play
成果圖片

5.範例:exp8-3計算兩個數字相加
本範例的成果圖片
下載成果範例檔案

(1)在unity裡面寫一個c#程式
在Assets視窗裡面,滑鼠右鍵→Create→c# script
名稱:script1
(2)在unity建立一個UI控制物件
在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty
修改名稱:UI
(3)把Assets視窗裡面的script1,拖曵到UI的add component
成果圖片

(4)撰寫程式碼:
方法1:
程式碼內容

方法2:
程式碼內容

(5)觀看目前效果,按:▶play
成果圖片

6.GUILayout自動佈局
(1)優點:
A.前面我們進行佈局的時候,會發現每次都需要輸入new Rect(),裡面包含四個座標。
B為了解決這個煩人的問題,Unity公司提供了一個相對簡單的佈局方案:即每個控制項的寬頻高度按照一些字體的大小進行統一計算。
位置採取靠左對齊,一個控制項佔據一行的原則。
C.GUILayout採用線性佈局,類似於StackPanel,預設是縱向佈局。
D.可以通過GUILayout.BeginHorizontal();開啟
和GUILayout.EndHorizontal()結束一個橫向排列區域,
同理BeginVertical() 、EndVertical()。

(2)官網:https://docs.unity3d.com/ScriptReference/GUILayout.html
各種GUILayout的方法:
Static Methods
BeginArea:Begin a GUILayout block of GUI controls in a fixed screen area.
BeginHorizontal:Begin a Horizontal control group.
BeginScrollView:Begin an automatically laid out scrollview.
BeginVertical:Begin a vertical control group.
Box:Make an auto-layout box.
Button:Make a single press button.
EndArea:Close a GUILayout block started with BeginArea.
EndHorizontal:Close a group started with BeginHorizontal.
EndScrollView:End a scroll view begun with a call to BeginScrollView.
EndVertical:Close a group started with BeginVertical.
ExpandHeight:Option passed to a control to allow or disallow vertical expansion.
ExpandWidth:Option passed to a control to allow or disallow horizontal expansion.
FlexibleSpace:Insert a flexible space element.
Height:Option passed to a control to give it an absolute height.
HorizontalScrollbar:Make a horizontal scrollbar.
HorizontalSlider:A horizontal slider the user can drag to change a value between a min and a max.
Label:Make an auto-layout label.
MaxHeight:Option passed to a control to specify a maximum height.
MaxWidth:Option passed to a control to specify a maximum width.
MinHeight:Option passed to a control to specify a minimum height.
MinWidth:Option passed to a control to specify a minimum width.
PasswordField:Make a text field where the user can enter a password.
RepeatButton:Make a repeating button. The button returns true as long as the user holds down the mouse.
SelectionGrid:Make a Selection Grid.
Space:Insert a space in the current layout group.
TextArea:Make a multi-line text field where the user can edit a string.
TextField:Make a single-line text field where the user can edit a string.
Toggle:Make an on/off toggle button.
Toolbar:Make a toolbar.
VerticalScrollbar:Make a vertical scrollbar.
VerticalSlider:A vertical slider the user can drag to change a value between a min and a max.
Width:Option passed to a control to give it an absolute width.
Window:Make a popup window that layouts its contents automatically.

(3)常用GUI控制項
(1)密碼框:pwd = GUILayout.PasswordField(pwd,‘*’),第二個參數為遮罩字元,注意幀刷新的問題。
(2)Button:只有滑鼠抬起才會返回true,這樣用Button做發射子彈就不能按下一直發射,可以使用RepeatButton,這樣按下期間會一直返回true。案例:Button和RepeatButton實現遊戲物件移動。
(3)Tab頁:electedToolBarId = GUILayout.Toolbar(selectedToolBarId,new string[]{“裝備”,“經驗”,“隊友”}); 返回值為啟動的按鈕的序號。
(4)核取方塊Toggle:isMuted = GUILayout.Toggle(isMuted,“靜音”);
(5)多行文本區TextArea:msgBody = GUILayout.TextArea(msgBody,GUILayout.Width(300),GUILayout.Height(300));
(6)滑動條VerticalSlider:縱向,sliderValue = GUILayout.VerticalSlider(sliderValue,0,100);返回值為當前值,第二個參數為最小值,第二個為最大值。 HorizontalSlider()橫向
(7)區域Area,相當於一個控制項的盒子, Area中的控制項跟著Area移動,
BeginArea()開始一個區域,參數指定區域的大小和座標,
EndArea()結束區域;
(8)視窗Window:區域是沒有邊框和標題的,也不可以拖放。 GUILayout.Window(0, new Rect(50,50,200,200),AddWindow1,“我的窗口”); 第一個參數為視窗的編號,第二個為視窗大小,第三個為void WindowFunction(int windowId)委託,用來繪製視窗內容。
窗口拖拽,在WindowFunction的最後調用GUI.DragWindow()可以啟用全屏拖放(給DragWindow傳Rect參數可以設定可拖放的區域)。考慮幀刷新的問題,要在OnGUI把Window()的返回Rect保存才可以可拖動,Start()中設定初始位置。

7.範例:exp8-4-GUILayout
本範例的成果圖片
下載成果範例檔案

(1)在unity裡面寫一個c#程式
在Assets視窗裡面,滑鼠右鍵→Create→c# script
名稱:script1
(2)在unity建立一個UI控制物件
在hierarchy視窗的空白處,滑鼠右鍵→CreateEmpty
修改名稱:UI
(3)把Assets視窗裡面的script1,拖曵到UI的add component
pic08-01.png

(4)撰寫程式碼:
A.重點1:同一行水平排版
GUILayout.BeginHorizontal("box1");
...
...
GUILayout.EndHorizontal();

B.常用元件:
顯示label:GUILayout.Label("現在日期時間:" + nowtime);
輸入文字方塊:n1 = GUILayout.TextField(n1, 20);
按鈕:GUILayout.Button("Login")
按了按鈕的事件:
if (GUILayout.Button("Login"))
{
}

C.如何設定Label為紅色:
var style2 = new GUIStyle(GUI.skin.label);
style2.normal.textColor = Color.red;
GUILayout.Label(output, style2);

D.完整程式碼:
程式碼內容

(5)觀看目前效果,按:▶play
成果圖片

 
 
chp9.幽浮2D遊戲

觀看

本範例的成果圖片1圖片2

下載

下載本章project成果檔案

1.new project
類型:選2D
name:exp9-2d-ufo

2.下載素材圖片

3.在Assets新增images目錄
拖曵圖片進入

3.建立新場景
File→New Scene
File→Save As:主畫面

4.拖曵background到hierarchy
選擇background到hierarchy
修改名稱:背景
調整位置,大小
Position(x,y,z) = 0,0,-10
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 1,1,1

5.拖曵ufo到hierarchy
調整位置,大小
Position(x,y,z) = 0,0,0
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 0.75,0.75,1

6.Add Soring Layer
成果圖片

Default
Background
Pickups
Player
成果圖片

6.設定背景的所在圖層為background
背景→inspector→sorting Layer = background

7.設定ufo的所在圖層為player
ufo→inspector→sorting Layer = player
結果:終於可以看到ufo了
成果圖片

8.設定攝影機main camera的位置
先捲動滑鼠放大
再修改四個角落的白點
成果圖片

10.設定攝影機main camera的背景顏色為黑色
RGB=32,32,32

11.設定ufo是剛體(rigidbody)
功用1:可以自由落體
功用2:可以有碰撞效果(反彈,碰撞,阻力)
ufo→inspector→add component → physics 2D →rigidbody
成果圖片

12.測試play
結果:ufo會自由落體下降

13.把重力消除
gravity scale = 0
成果圖片
結果:ufo漂浮,不會自由落體下降

14.在unity裡面寫一個c#程式
(1)在Assets視窗裡面,滑鼠右鍵→Create→c# script
一個c#也是一個component
(2)名稱:script1
(3)在hierarchy視窗→UFO
把Assets視窗裡面的script1,拖曵到UFO的add component

16.開始寫script1程式
(1)到Assets視窗的script1
(2)double click這個程式物件(script1)
結果
(4)打開vs code
(5)寫程式碼
//設定ufo移動速度: float speed1=15.0f
//宣告一個個體物件: Rigidbody2D ufo1;
(為什麼要宣告剛體rigidbody2d,因為若是要施力移動,必須是剛體物件rigidbody)
//截取場景裡面名稱為UFO的剛體:ufo1 = GameObject.Find("UFO").GetComponent();
//截取使用者水平按鍵的值(+1或-1):float x1 = Input.GetAxis("Horizontal");
//截取使用者垂直按鍵的值(+1或-1):float y1 = Input.GetAxis("Vertical");
//由水平按鍵,垂直按鍵來換算移動的2D向量:Vector2 movement = new Vector2(x1,y1);
//用(移動向量x速度) 來施力:ufo1.AddForce(movement * speed1);
程式碼內容
(6)測試結果:ufo會移動到框框的外面去
成果圖片

17.在背景的四邊加上圍牆,ufo遇到圍牆會反彈
(1)先設定ufo的碰撞器性質狀態=Circle Collider 2D
ufo→inspector→add component → physics 2D →Circle Collider 2D
設定碰撞器的半徑radius = 2.1
成果圖片

(2)設定『背景』的碰撞器性質狀態=盒狀box Collider 2D
背景→inspector→add component → physics 2D →Box Collider 2D→Edit Collider
調整四邊的位置,變成上方的圍牆
成果圖片
再建立三個圍牆,分別在左右下邊
背景→inspector→add component → physics 2D →Box Collider 2D→Edit Collider
背景→inspector→add component → physics 2D →Box Collider 2D→Edit Collider
背景→inspector→add component → physics 2D →Box Collider 2D→Edit Collider
成果圖片

(3)測試結果:ufo會遇到框框會停止,但ufo當鍵盤放開時還會繼續滑行

18.當鍵盤放開,就讓ufo停止(寫程式碼)
//if(Input.GetKey("up")) = if(Input.GetKey("up")==true) 若是按了向上鍵
//設定讓ufo移動的兩種方法
(1)等速運動:ufo1.velocity = new Vector2(x1,y1)*speed1;
(2)給定一個推力運動:ufo1.AddForce(new Vector2(x1,y1) * speed1);
//設定讓ufo停止:ufo1.velocity = new Vector2(0,0);
程式碼內容

19.放置1顆障礙石頭
(1)拖曵Pickup到hierarchy
選擇Pickup到hierarchy
修改名稱:石頭
(2)調整layer位置(soring layer):Pickup
(3)設定『石頭』是剛體(rigidbody)
石頭→inspector→add component → physics 2D →rigidbody
(4)設定『石頭』的重力gravity scale = 0
(5)設定『石頭』具有碰撞效果(會阻擋別人)
先設定『石頭』的碰撞器性質狀態=Circle Collider 2D
『石頭』→inspector→add component → physics 2D →Circle Collider 2D
設定碰撞器的半徑radius = 0.95
(6)測試結果:
ufo遇到石頭會碰撞,但是石頭不會消失

20.(寫程式碼)ufo碰撞到石頭,石頭會消失
(1)先把石頭設定tag標籤 = Pickup
成果圖片

(2)寫程式碼:當遇到Pickup就會把該石頭消失
固定套路寫法(可以直接複製)
程式碼內容

21.把1顆石頭製作成prefab,然後複製成一樣性質參數的12顆石頭
(1)製作prefab方法:直接把hierarchy裡面的石頭 → 拖移到assets裡面
成果圖片
(2)把assets裡面的石頭,拖移到場景裡面
成果圖片
(3)測試play

22.讓攝影機跟著ufo移動
(1)這個功能,要專門寫一個c#程式碼來追踪攝影機
(2)在Assets視窗裡面,滑鼠右鍵→Create→c# script
一個c#也是一個component
名稱:script2
(3)在hierarchy視窗鍵→Main Camera
把Assets視窗裡面的script2,拖曵到Main Camera的add component
成果圖片

(4)開始寫script2程式
(5)打開vs code
關鍵重點:
//如何找到場景裡面的UFO物體
方法1:object1 = GameObject.Find("UFO");
方法2:object1 = GameObject.FindGameObjectsWithTag("UFO")[0];
//如何知道目前camera的位置 = gameObject.transform.position
(注意:小寫g的gameObject代表是目前物件(camera))
//camera如何追踪ufo
camera的位置= UFO位置 + 距離(camera vs UFO)
gameObject.transform.position = object1.transform.position + movement
(movement距離 = gameObject.transform.position - object1.transform.position)
程式碼內容

測試結果:移動上下左右鍵盤時,攝影機camera會跟著UFO而移動
成果圖片

23.在Text顯示目前殘存石頭數量
(1)在unity的主畫面場景新增一個Text(ui物件)
在hierarchy視窗的空白處,滑鼠右鍵→UI→Text
修改名稱=Num
Position(x,y,z) = -50,140,0
FontSize= 20
Color = yellow
成果圖片

(2)在unity裡面修改scirpt1程式,顯示目前最新的殘存石頭數量
名稱:script1
打開vs code
關鍵重點:
(3)如何抓取場景的文字Num
using UnityEngine.UI;
Text txtnum;
txtnum = GameObject.Find("Num").GetComponent<Text>();
(4)當觸碰到石頭,num要--
if(object1.gameObject.CompareTag("Pickup"))
{
Destroy(object1.gameObject);
num --;
txtnum.text = "Num = " + num;
}
(5)完整程式碼:
程式碼內容

24.當石頭全部消失時,顯示『你獲勝』
(1)在unity的主畫面場景新增一個Text(ui物件)
在hierarchy視窗的空白處,滑鼠右鍵→UI→Text
修改名稱=Win
Position(x,y,z) = 50,140,0
FontSize= 20
Color = red
成果圖片

(2)在unity裡面修改scirpt1程式,顯示目前最新的殘存石頭數量
名稱:script1
打開vs code
關鍵重點:
(3)如何在文字Win顯示結果
using UnityEngine.UI;
Text txtwin;
txtwin = GameObject.Find("Win").GetComponent<Text>();
if(num==0)
{
txtwin.text = "你獲勝";
}
(4)完整程式碼:
程式碼內容
(5)測試結果:
成果圖片

 
 
chp10.幽浮3D遊戲(撿寶物)

觀看

本範例的成果圖片1圖片2

下載

下載本章project成果檔案
目錄 1.建立馬路Road 9.建立Turn轉角物件 12.建立一個球ball 14.用上下左右鍵(或滑桿)移動ball
15.補充:unity中讓Rigidbody移動的方式 16.補充:給剛體物體施力,Rigidbody.AddForce(),有四個方法 17.補充:unity施力的四種ForceMode 18.設定攝影機跟著Ball移動
19.到Asset Store線上商店下載Gem Shader寶石 21.(寫程式碼)Ball碰撞到寶石,寶石會消失 22.(寫程式碼)在OnGUI()顯示目前得到寶石幾個 23.(寫程式碼)在OnGUI()顯示你贏了後,出現按鈕(是否要再玩一次?),若要,則重新開始
24.若是Ball掉落,就結束遊戲Game Over 25.設定天空背景圖片

1.new project
類型:選3D
name:exp10-3d-ufo

2.下載圖片檔案
下載圖片檔案

3.在Assets新增images目錄
拖曵圖片進入
道路3D模型:Ballance.obj
道路材質圖片1:texture1.jpg
道路材質圖片2:texture2.jpg
彈珠圖片:glass-texture.jpg

5.匯入3D模型:Straight拉到場景scene內
(1)先打開Ballance的階層◄
(2)把Straight模型拖曵到Scene(白色那個Straight,不是黑色的Straight)
(3)修改名稱 = Road
(4)調整位置,大小
Position(x,y,z) = 0,0,0
Rotation(x,y,z) = 270,0,0
Scale(x,y,z) = 1,1,1
成果圖片

(5)把camera視角改成右上往下看(y在上)
Position(x,y,z) = 0,5,0
Rotation(x,y,z) = -270,0,0
成果圖片

6.修正材質圖片的壓縮
(1)先點選assets/models/裡面的texture1.jpg
(2)inspector
max Size = 256
Format = Truecolor/或是32bits/或是16bits全彩圖片
按Apply
(3)點選assets/models/裡面的texture2.jpg
(4)inspector
max Size = 256
Format = Truecolor/或是32bits/或是16bits全彩圖片
按Apply

成果圖片

7.設定3D模型Road的材質(雙材質)
(1)點選Road
(2)先把texture1, texture2拖曵到Add Component
成果圖片

(3)inspector→Materials→Size:2
(4)Element 0:指定材質為:Texture1
(5)Element 1:指定材質為:Texture2
成果圖片

8.設定Road有碰撞效果
選取Road物件→component→Physics→Mesh Collider(網格碰撞)
成果圖片

9.新增Prefab預製物件(但是教育版,似乎沒有這個功能,disable了)
功用1:prefab乃是預製物件,若是先預製好,以後就可以直接重複不斷使用
功用2:Prefab最強大的地方並不是只有生成物件而已,而是當Prefab有做任何修改時可以即時的反應到物件上。
當你有任何一個GameObject是透過Prefab產生時,此時只要在Project視窗針對Prefab進行修改,那麼參考到這個Prefab的物件就會直接被修改。
功用3:Prefab是一個放在資料夾裡的檔案,是用來描述物件的構成。而GameObject是存在於記憶體裡的遊戲物件

(1)製作prefab方法:直接把hierarchy裡面的『Road』 → 拖移到assets裡面『Road』
(1)把Project→Assets→『Road』
於是在Hierarchy就會出現一個新的Prefab物件『Road』
(2)把Road拖曵到場景中

成果圖片

10.使用prefab拖曵到場景,總共建立4個連接的Road
(1)把Road複製(Duplicate):Road1
Position(x,y,z) = 0,0,2
(2)把Road複製(Duplicate):Road2
Position(x,y,z) = 0,0,4
(3)把Road複製(Duplicate):Road3
Position(x,y,z) = 0,0,6

(4)調整camera視角
Position(x,y,z) = 0,9,3
Rotation(x,y,z) = -270,0,0
成果圖片

9.設定Turn轉角物件
(1)匯入3D模型:Turn拉到場景scene內
先打開Ballance的階層◄
把Turn模型拖曵到Scene(白色那個Turn,不是黑色的)
(2)調整位置,大小
Position(x,y,z) = 0,0,-3
Rotation(x,y,z) = -90,0,0
Scale(x,y,z) = 1,1,1
(3)修改名稱 = Turn
(4)先把texture1, texture2拖曵到Add Component
(5)inspector→Materials→Size:3
Element 0:指定材質為:Texture1
Element 1:指定材質為:Texture2
Element 2:指定材質為:Texture1
成果圖片

(6)設定Road有碰撞效果
選取Road物件→component→Physics→Mesh Collider(網格碰撞)
成果圖片

9.修改main Camera的位置
Position(x,y,z) = 0,3,-5
Rotation(x,y,z) = 40,0,0
Scale(x,y,z) = 1,1,1
成果圖片

10.儲存場景
File→Save As Scene:part1

12.建立一個球
(1)GameObject→3D Object→Sphere
(2)修改名稱 = Ball
(3)調整位置,大小 Position(x,y,z) = 0,1,0
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 1,1,1
成果圖片

(4)設定Ball有碰撞效果
選取Road物件→component→Physics→Sphere Collider(球體碰撞)

(5)設定Ball有自由落體效果(剛體)
選取Ball物件→component→Physics→Rigidbody(物理剛體)
成果圖片

13.把材質與程式碼加入Ball物件
(1)拖曵glass-texture.jpg材質圖片,拖曵到球(add component)
成果圖片

(2)在Assets視窗裡面,滑鼠右鍵→Create→c# script
名稱:ball
(3)hierarchy視窗點選Ball物件
(4)把Assets視窗裡面的script1,拖曵到Ball物件的add component
成果圖片

14.然後用上下左右鍵(或滑桿)移動ball
(1)雙擊ball程式
(2)打開vs code
//關鍵重點1:如何找到場景裡面的ball物體(若要移動,必須要說rigidbody物件)
Rigidbody rb;
rb = GetComponent<Rigidbody> ();

//關鍵重點2:如何移動物件(左右鍵移動左右(x axis),上下鍵移動前後(z axis)
float x1 = Input.GetAxis("Horizontal");
float z1 = Input.GetAxis("Vertical");
rb.AddForce (x1,0,z1,ForceMode.Force);

//關鍵重點3:然後偵測鍵盤的上下左右鍵
float x1 = Input.GetAxis("Horizontal");
float z1 = Input.GetAxis("Vertical");

//關鍵重點4:對於一個rigidBody物件然後施力移動
方法(1):施力後,放開力道
rb.AddForce (x1,y1,z1,ForceMode.Force);
x1:螢幕左右
y1:螢幕上下
z1:螢幕前後

方法(2):施力後,控制成,等速運動
Vector3 direction = new Vector3(x1,0,z1);
rb.velocity = direction * movementSpeed;

(3)完整程式碼:rb.AddForce()
程式碼內容

(3)完整程式碼:rb.velocity = direction * movementSpeed
程式碼內容

15.補充:unity中讓Rigidbody移動的方式
(1)Rigidbody.velocity
給定剛體一個速度speed:
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
direction = new Vector3(horizontal,0f,vertical);
rb.velocity = speed * direction;

(2).Rigidbody.MovePosition() 移動到新的position:
Vector3 movement;
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
movement.Set(h, 0f, v);
movement = movement.normalized * speed * Time.deltaTime;
playerRigidbody.MovePosition(transform.position + movement);

(3)Rigidbody.AddForce:rb.AddForce(transform.forward * thrust);

public float thrust;
rb.AddForce(0, 0, thrust, ForceMode.Impulse);

16.補充:給剛體物體施力,Rigidbody.AddForce(),有四個方法:
(1)void Rigidbody.AddForce(vector3 Force);

(2)void Rigidbody.AddForce(Vector3 Force,ForceMode mode);
其中
Vector3 Force:第一個引數與第一個一樣都是需要傳入一個向量,
ForceMode mode:第二個引數傳入一個力的作用模式

(3)void Rigidbody.AddForce(float x,float y,float z);

(4)void Rigidbody.AddForce(float x,float y,float z,ForceMode mode)

(與前兩個基本一樣);

其中ForceMode有四種形式:
ForceMode.Acceleration
ForceMode.Force
ForceMode.Impulse
ForceMode.VelocityChange

17.補充:unity施力的四種ForceMode
ForceMode.Acceleration
ForceMode.Force
ForceMode.Impulse
ForceMode.VelocityChange
(1)ForceMode.Force:給物體新增一個持續的力並使用其質量(測試採用質量為2)
(2)ForceMode.Acceleration::給物體新增一個持續的加速度(但是忽略其質量。即無論設定的質量為多少,都採用預設質量1)
(3)ForceMode.Impulse;:給物體新增一個瞬間的力(使用它的預設質量)
(4)ForceMode.VelocityChange;:給物體新增一個瞬間的加速度(但是忽略其質量)

功能注解:在以下舉例中均設剛體品質為m=2.0f,力向量為f=(10.0f,0.0f,0.0f)。

(1)ForceMode.Force:
預設方式,使用剛體的品質計算,以每幀間隔時間為單位計算動量。
設FixedUpdate()的執行頻率採用系統預設值(即0.02s),則由動量定理
f•t=m•v
可得:10*0.02=2*v1,從而可得v1=0.1,即每幀剛體在X軸上值增加0.1米,從而可計算得剛體的每秒移動速度為v2=(1/0.02)*v1=5m/s。

(2)ForceMode.Acceleration:
在此種作用方式下會忽略剛體的實際品質而採用預設值1.0f,時間間隔以系統幀頻間隔計算(預設值為0.02s),即
f•t=1.0•v
即可得v1= f•t=10*0.02=0.2,即剛體每幀增加0.2米,從而可得剛體的每秒移動速度為v2=(1/0.02)*v1=10m/s。

(3)ForceMode.Impulse:
此種方式採用瞬間力作用方式,即把t的值默認為1,不再採用系統的幀頻間隔,即
f•1.0=m•v
即可得v1=f/m=10.0/2.0=5.0,即剛體每幀增加5.0米,從而可得剛體每秒的速度為v2=(1/0.02)*5.0=250m/s。

(4)ForceMode.VelocityChange:
此種作用方式下將忽略剛體的實際品質,採用默認品質1.0,同時也忽略系統的實際幀頻間隔,採用默認間隔1.0,即
f•1.0=1.0•v
即可得v1=f=10.0,即剛體每幀沿X軸移動距離為10米,從而可得剛體每秒的速度為v2=(1/0.02)*v1=500m/s。

18.設定攝影機跟著Ball移動
(1)在Assets視窗裡面,滑鼠右鍵→Create→c# script
名稱:camera
(3)hierarchy視窗點選Main Camera物件
(4)把Assets視窗裡面的camera script,拖曵到Main Camera物件的add component
成果圖片
(5)雙擊ball程式
程式碼內容

測試結果:果然攝影機可以跟著ball移動
成果圖片

19.到Asset Store線上商店下載Gem Shader寶石模型
(1)Window→Asset Store
(2)Search:Sets - Gems (Free)
(3)download→Import→Import
成果圖片

20.拖曵Gems_Red/gem_08到hierarchy視窗裡面
(1)修改名稱:寶石1
Position(x,y,z) = 0,0.5,3.5
Rotation(x,y,z) = 0,-0,0
Scale(x,y,z) = 1,1,1

(2)設定Tag
功用1:此遊戲有兩個碰撞事件(撿取寶石,球掉下就會觸發Game Over遊戲結束)
選取寶石1→Add Tag→ + →
Tag0:Picker
成果圖片

(3)設定寶石的碰撞事件(打勾Convex,IsTrigger)
選取寶石1→component→ Physics → Mesh Collider
打勾Convex,IsTrigger
成果圖片

(4)建立pretab預鑄物件
選取寶石1→拖曵到Assets/image裡面(建立pretab預鑄物件)
把pretab預鑄物件→拖曵到場景畫面中
修改名稱:寶石2
Position(x,y,z) = 0,0.5,1.5
Rotation(x,y,z) = 0,-0,0
Scale(x,y,z) = 1,1,1

把pretab預鑄物件→拖曵到場景畫面中
修改名稱:寶石3
Position(x,y,z) = -0.6,0.5,-2.4
Rotation(x,y,z) = 0,-0,0
Scale(x,y,z) = 1,1,1
觀看目前效果,按:▶play
成果圖片

21.(寫程式碼)Ball碰撞到寶石,寶石會消失
(1)打開ball(script)
(2)寫程式碼:當遇到Pickup就會把該石頭消失
固定套路寫法:3D碰撞(可以直接複製)
程式碼內容

(3)比較:2D碰撞寫法:當遇到Pickup就會把該石頭消失
程式碼內容
(4)完整程式碼:
程式碼內容
觀看目前效果,按:▶play

22.(寫程式碼)在OnGUI()顯示目前得到寶石幾個
(1)重點1:如何在螢幕顯示目前寶石幾顆
程式碼內容
(2)若是被碰撞,修改螢幕寶石數量
程式碼內容
(3)完整程式碼:
程式碼內容
觀看目前效果,按:▶play
成果圖片

23.(寫程式碼)在OnGUI()顯示你贏了後,出現按鈕(是否要再玩一次?),若要,則重新開始
(1)重新玩遊戲:
過去的指令:Application.LoadLevel();來進行場景的切换。
但在5.3版本之後不再使用,
最新指令:UnityEngine.SceneManagement.SceneManager.LoadScene(0);

方法1:切換到場景0(LoadScene(0))
UnityEngine.SceneManagement.SceneManager.LoadScene(0);

方法2:切換到場景"SampleScene"(LoadScene("SampleScene"))
UnityEngine.SceneManagement.SceneManager.LoadScene("SampleScene");

(2)注意:出現的GUI.button()要出現在void OnGUI()裡面
(3)完整程式碼:
程式碼內容
觀看目前效果,按:▶play
成果圖片

24.若是Ball掉落,就結束遊戲Game Over
(1)建立一個3D Object Cube
方法:加入一個看不見(透明)的cube物件,若是cube被碰撞了,就表示有得分
新增GameObject→3D Object→cube
調整位置,大小
Position(x,y,z) = 0,-2,0
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 50,1,50
成果圖片

(2)設定碰撞事件
is Trigger打勾

(3)設定不顯示
Mesh Renderer取消打勾

成果圖片

(4)設定tag
添加Tag
功用1:此遊戲有兩個碰撞事件(撿取寶石,球掉下,就會觸發Game Over遊戲結束)
選取Ball→Add Tag→ + →
Tag0:GameOver
成果圖片

(5)(寫程式碼)碰撞GameOver Cube則顯示遊戲結束,並詢問是否重新玩遊戲?
A.碰撞事件的寫法
程式碼內容
B.顯示button詢問是否重新玩遊戲
程式碼內容
C.完整程式碼:
程式碼內容

觀看目前效果,按:▶play
成果圖片

25.設定天空背景圖片
(1)到Asset Store線上商店下載classic skybox模型
Window→Asset Store
Search:classic skybox(Free)
download→Import→Import
成果圖片

(2)使用classic skybox
Windows → Rendering → Lighting Settings
→ Scene →Skybox → 選 :sky05

成果圖片

 
 
chp11.狗狗過馬路3D遊戲

觀看

本範例的成果圖片1圖片2

下載

下載本章project成果檔案
目錄 1.建立馬路,公園,狗狗,樹木 9.建立公園園區物件群組 12.讓汽車能夠持續平滑行動的方法Vector3.Lerpl 15.自動產生物件的方法(Instantiate)
16.不斷執行的方法InvokeRepeating 18.建立不斷自動產生出現的汽車物件 23.把不斷累積的物件刪除的方法Destroy 24.用滑鼠按一下操控物件向前移動
25.用鍵盤ws前後ad左右操控物件移動 26.用上下左右鍵操控物件移動 27.用滑鼠操控物件上下左右移動 方法1:把3D物件座標,轉換成Screen畫面螢幕座標
方法2:把滑鼠畫面座標,轉換成world世界座標 設定攝影機跟著dog移動 (觀念)比較:Collision碰撞 vs Trigger觸發 28.狗狗碰撞到汽車,則顯示game Over,遊戲結束
29.game Over後,狗狗無法再移動 30.使用GUISkin(圖形使用者介面面板)顯示分數

2014年app遊戲排行榜第一名是狗狗過馬路的遊戲(Crossy Road)
1.new project
類型:選3D
name:exp11-3d-crossyroad

2.下載圖片檔案
下載圖片檔案

3.在Assets新增models目錄
拖曵圖片,3D模型進入

4.建立新場景
File→New Scene
File→Save As:主畫面

5.加上馬路背景
(1)GameObject→3D Object→Plane
(2)修改名稱 = Road
(3)調整位置,大小
Position(x,y,z) = 0,0,0
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 25,1,25
(4)拖曵圖片road1.jpg拉到這個平面內
成果圖片

(5)修改材質的titling數值:
x:100
y:100
成果圖片

6.加上公園
(1)GameObject→3D Object→Cube
(2)修改名稱 = Park
(3)調整位置,大小
Position(x,y,z) = 0,0,0
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 100,0.2,2
(4)拖曵圖片road2.jpg拉到這個Box內
成果圖片

7.把狗狗3D物件加上場景
(1)先打開dog.fbx模型檔的階層◄
(2)選取Pasted_bitmap模型,並拖曵到場景Scene
成果圖片

(3)修改名稱 = Road
(4)調整位置,大小
Position(x,y,z) = 0,0,0
Rotation(x,y,z) = 0,270,0
Scale(x,y,z) = 0.05,0.05,0.05
(5)拖曵圖片dog.jpg拉到這個物件內
成果圖片

8.把樹木3D模型加到場景內
(1)先打開tree.fbx模型檔的階層◄
(2)選取tree_bitmap模型,並拖曵到場景Scene
(3)修改名稱 = Tree
(4)調整位置,大小
Position(x,y,z) = 2,0,6.83
Rotation(x,y,z) = 0,270,0
Scale(x,y,z) = 0.1,0.1,0.1
(5)拖曵圖片tree2.jpg拉到這個物件內
成果圖片

(6)設定Tree的碰撞tag
選取Tree→Add Tag→ + →
Tag0:tree
選取:tree
成果圖片

9.建立第2個公園園區物件群組(Parks)
(1)GameObject→Crete Empty
(2)修改名稱 = Parks
(3)調整位置,大小
Position(x,y,z) = 0,0,0
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 1,1,1
(4)把剛剛建立的兩個物件加入群組
複製Park1
把Park,Tree物件,拖曵到Parks群組內
成果圖片

(5)再複製多個樹木tree
成果圖片
結果Parks群組內有:
Park1
Tree
Tree1
Tree2
Tree3
Tree4
成果圖片

(6)移動物件群組(Parks)成為第二個公園區
成果圖片
成果圖片

(7)移動樹木位置
成果圖片

10.複製第3個公園園區物件群組(Parks)
(1)選取Parks群組
(2)右鍵 → copy
(3)右鍵 → paste
(4)移動Parks位置
成果圖片
成果圖片

11.把car1車子3D模型加到場景內
(1)先打開car1.fbx模型檔的階層◄
(2)選取Pasted_bitmap模型,並拖曵到場景Scene
(3)修改名稱 = car1
(4)調整位置,大小
Position(x,y,z) = -4,0,4
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 0.05,0.05,0.05
成果圖片
(5)拖曵圖片car1.jpg拉到這個物件內
成果圖片

(6)設定Tree的碰撞tag
選取car1→Add Tag→ + →
Tag0:car
選取:car
成果圖片
成果圖片

11.把car2車子3D模型加到場景內
(1)先打開car2.fbx模型檔的階層◄
(2)選取Pasted_bitmap模型,並拖曵到場景Scene
(3)修改名稱 = car2
(4)調整位置,大小
Position(x,y,z) = 0,0,3.54
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 0.05,0.05,0.05
(5)拖曵圖片car2.jpg拉到這個物件內
(6)設定Tree的碰撞tag
選取car2→Tag0:car
選取:car
成果圖片
成果圖片

12.(寫程式碼)讓car1,car2能夠向右行動
(1)在Assets/models視窗裡面,滑鼠右鍵→Create→c# script
名稱:move
(2)點選car1/car2/prefab_car1/prefab_car2/prefab_car3/prefab_car4物件
(3)把walk.cs拖曵到物件的component

(1)關鍵指令1:車子的位置 = transform.position
(2)關鍵指令2:使用Vector3.Lerp 線性插值製作滑順效果
公式:transform.position = Vector3.Lerp(起始位置, 目的位置, t);
t:代表的是from 與 to之間的差值,是一個介於0~1之間的浮點數
例如:t = 0.1,表示把起始位置~目的位置之間分成10等分,然後逐格顯示
範例:
public Vector3 p1= new Vector3(25,0,0);
ransform.position = Vector3.Lerp(transform.position, p1, 0.1);
(3)Lerp 線性插值:
在Unity中,Lerp一種是用來計算線性插值的函式。
Lerp可以使用在很多個地方,像是:Color.Lerp 、Mathf.Lerp 、Vector3.Lerp 、Material.Lerp 。
Lerp可以用來製作許多滑順的效果。譬如說可以利用Color.Lerp來計算兩個顏色之間的插值,
就可以讓兩種不同的顏色平滑的轉換。

(4)Lerp函式:.Lerp(from, to, t: float):
其中t代表的是from 與 to之間的差值,是一個介於0~1之間的浮點數。
若t=0則傳回from,,t=1則傳回to,t=0.5則傳回from與to的平均值。
以Vector3.Lerp來說,那from 與 to都會是Vector3型態,傳回值也會是Vector3型態。

(5)注意:要達成滑順的轉化效果其實是要不斷地呼叫Lerp,所以要放在void Update()裡面
因為,Lerp其實僅僅只是計算單一次插值得結果。並不會自動幫你完成連續的動作。
舉例:
有個遊戲物件要從目前的位置移動到位置p1,
那就要在Update中一直呼叫Vector3.Lerp來逼近位置p1。
function Update ()
{
transform.position = Vector3.Lerp(transform.position, p1, 0.1);
}
Lerp函式在transform.position與p1之間計算出十分之一的距離,
然後給傳回ransform.position 以改變現在的位置。
下一次Update時在用新的位置計算與p1十分之一的距離,一直逼近到p1。

(6)注意:滑順效果不是線性的。
Lerp是線性插值,但做出的效果不是線性的。
實際上一開始的變化會最快,而越接近目標時變化會越來越慢。
以上面的例子來說,雖然每次都是移動十分之一的距離,但是其實一開始兩個的位置差距最大,算出來的十分之一當然也最大。當兩個位置差逐漸縮小時,這十分之一的距離當然也越來越小。
這也意謂這每次Update時,移動的距離越來越小,最後小到你都看不見。

(7)完整程式碼:
程式碼內容
(8)說明:
☎Vector3.Lerp(transform.position, MoveTo, 0.001f)
☎transform.position = 目前最新位置
☎MoveTo = Vector3(25,0,0),到 x =40的位置
☎0.0002f = 2/10000,分成10000格,然後逐格移動
成果圖片

13.建立prefab預鑄的car1物件
(1)選取car1物件
(2)拖曵到Assets/models裡面,形成prefab預鑄物件car1
(3)把move.cs拉到 add component
(4)car1的Move To = Position(x,y,z) = 14,0,5
成果圖片

13.建立prefab預鑄的car2物件
(1)選取car2物件
(2)拖曵到Assets/models裡面,形成prefab預鑄物件car2
(3)把move.cs拉到 add component
(4)car2的Move To = Position(x,y,z) = 14,0,2.5

13.建立prefab預鑄的car3物件
(1)選取car1物件
(2)拖曵到Assets/models裡面,形成prefab預鑄物件car3(改名為car3)
(3)把move.cs拉到 add component
(4)car3的Move To = Position(x,y,z) = 14,0,12

13.建立prefab預鑄的car4物件
(1)選取car2物件
(2)拖曵到Assets/models裡面,形成prefab預鑄物件car4(改名為car4)
(3)把move.cs拉到 add component
(4)car4的Move To = Position(x,y,z) = 14,0,14
成果圖片

15.(寫程式碼)產生物件的指令:Instantiate
(1)指令:Instantiate實例化:生成物件在某物件的位置 語法:Instantiate實例化(要生成的物件, 物件位置, 物件旋轉值);
語法:Instantiate(gameObject, transform.position, transform.rotation);
其中:transform.position = new Vector3(3,0,0)
其中:transform.rotation = new Quaternion(0,90,0,0)

範例:Instantiate (gameObject, new Vector3(3,0,0), new Quaternion(0,90,0,0));
注意:若物件有調整過旋轉值Rotation,記得要用一個GameObject來當做父物件,此父物件旋轉值都為0度。
若沒有這樣做,那麼生成出來的物件方向會不同。

16.(寫程式碼)不斷執行的的指令:Invoke,InvokeRepeating
(1)方法1:Invoke是延時調用函數,在用Invoke函數之前需要引入命名空間using UnityEngine.Events;
範例:Invoke("MethodName",2)
兩秒之後調用一次,MethodName方法

(2)方法2:InvokeRepeating("MethodName",1,2)
多次調用Invoke,一秒後,每隔兩秒,調用MethodName方法。

(3)取消:CancelInvoke("MethodName")
取消MethodName方法的調用

17.(寫程式碼)建立不斷執行+自動產生出現的汽車物件
(1)在Assets/models視窗裡面,滑鼠右鍵→Create→c# script
名稱:repeatCreate
(2)點選repeatCreateCar1/repeatCreateCar2/repeatCreateCar3/repeatCreateCar4物件
(3)把repeatCreate.cs拖曵到物件的component
(4)完整程式碼:
程式碼內容
(3)說明:
☎InvokeRepeating("Create",3,4):從3秒後,每隔4秒,重複執行Create()函數事件
☎Instantiate(gameObject, transform.position, new Quaternion(0,0,0,0))
語法:Instantiate實例化(要生成的物件, 物件位置, 物件旋轉值);
把gameObject物件,在transform.position位置產生,物件旋轉值=Quaternion(0,0,0,0)

18.建立不斷自動產生出現的汽車物件car1(讓prefab_car1不斷出現)
(1)GameObject→Crete Empty
(2)修改名稱 = repeatCreateCar1
(3)調整位置,大小
Position(x,y,z) = -14,0,5
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 1,1,1
(4)把程式碼repeatCreate.cs加入這個物件內(add component)
(5)設定參數
time1 = 4
Game Object(指定出現的物件) = car1(把prefab_car1拖曵入內)
成果圖片
成果圖片

(6)讓car1(prefab_car1)向前移動
點選Assets/models/裡面的car1(prefab_car1)
設定程式碼(把move.cs拖曵到car1(prefab_car1)的add component)
設定程式參數:
car1的Move To = Position(x,y,z) = 14,0,5
成果圖片
成果圖片

19.同樣的方法,建立不斷自動產生出現的汽車物件car2(讓prefab_car2不斷出現)
(1)GameObject→Crete Empty
(2)修改名稱 = repeatCreateCar2
(3)調整位置,大小
Position(x,y,z) = -18,0,2.5
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 1,1,1
(4)把程式碼repeatCreate.cs加入這個物件內(add component)
(5)設定參數
time1 = 5
Game Object(指定出現的物件) = car2(把prefab_car2拖曵入內)
(6)讓car1(prefab_car1)向前移動
點選Assets/models/裡面的car2(prefab_car2)
設定程式碼(把move.cs拖曵到car2(prefab_car2)的add component)
car2的Move To = Position(x,y,z) = 14,0,2.5
成果圖片

20.同樣的方法,在另外一條馬路,建立不斷自動產生出現的汽車物件car3(讓prefab_car3不斷出現)
car3的Move To = Position(x,y,z) = 14,0,12
21.同樣的方法,在另外一條馬路,建立不斷自動產生出現的汽車物件car4(讓prefab_car4不斷出現)
car4的Move To = Position(x,y,z) = 14,0,14
成果圖片

22.若是出現錯誤:
遠方道路的車子,會斜斜開向鏡頭前方
原因:因為指向位置,是在z=0的點(public Vector3 MoveTo= new Vector3(40,0,0);)
(1)建立:製作預鑄物件,car3,car4
(2)修改他們的Move To
car1的Move To = Position(x,y,z) = 14,0,5
car2的Move To = Position(x,y,z) = 14,0,2.5
car3的Move To = Position(x,y,z) = 14,0,12
car4的Move To = Position(x,y,z) = 14,0,14
成果圖片
成果圖片

23.出現錯誤:產生的汽車物件,會不斷累積,越來越多
(1)改善方法:在move.cs把超過出現4秒的汽車刪除
(2)偵錯指令
Debug.Log(timea);
(3)經過了多少秒之Ticks?
分享: facebook PLURK twitter
方法1:用Timer
方法2:long StartDate = DateTime.Now.Ticks;
(4)如何用ticks回推幾秒?
秒數 = (Ticks1 - Ticks2)/10000000,相減後除以10000000就是幾秒
因為,1 Ticks = 100奈秒
範例:if(((DateTime.Now.Ticks - StartDate) / 10000000)>15)

(5)完整程式碼:move.cs
程式碼內容
成果圖片

24.(寫程式碼)讓狗狗走路(用滑鼠按下操控)
(1)在Assets/models視窗裡面,滑鼠右鍵→Create→c# script
名稱:walk
(2)點選dog物件
(3)把walk.cs拖曵到dog物件的component

(4)完整程式碼(1):只是向前移動
程式碼內容

(5)重點說明
A.按了滑鼠的事件:Input.GetMouseButtonUp(0)
if(Input.GetMouseButtonUp(0))
{....}

B.如何把目前位置(向量),再加上一個向量:
方法:new Vector3(1, 2, 3) + new Vector3(4, 5, 6)
方法:transform.position + new Vector3(0, 0, 2)
(z=2,為向前)

C.平滑移動
transform.position = Vector3.Lerp(transform.position, endpoint, 0.3f);
transform.position = Vector3.Lerp(transform.position, transform.position+new Vector3(0, 0, 2), 0.3f);
成果圖片

25.(寫程式碼)讓狗狗走路(用鍵盤ws前後,ad左右操控)
(1)判別是否按了w鍵:
if (Input.GetKeyDown(KeyCode.W))
if (Input.GetKeyDown(KeyCode.S))
if (Input.GetKeyDown(KeyCode.A))
if (Input.GetKeyDown(KeyCode.D))

(2)完整程式碼(2):鍵盤ws前後,ad左右操控
程式碼內容


26.(寫程式碼)讓狗狗走路(用鍵盤↑↓←→上下左右鍵操控)
(1)判別是否按了↑↓←→上下左右鍵鍵:
if(Input.GetKeyDown("up"))
if(Input.GetKeyDown("down"))
if(Input.GetKeyDown("left"))
if(Input.GetKeyDown("right"))
或是
if (Input.GetKeyDown(KeyCode.UpArrow))
if (Input.GetKeyDown(KeyCode.DownArrow))
if (Input.GetKeyDown(KeyCode.LeftArrow))
if (Input.GetKeyDown(KeyCode.RightArrow))

(2)完整程式碼(2):用鍵盤↑↓←→上下左右鍵操控
程式碼內容
成果圖片

27.(注意若是出現錯誤)用鍵盤↑↓←→上下左右鍵操控,但是前進很遠
成果圖片
(1)原因:若是偵錯鍵盤的指令是Input.GetKey("up"),而不是用Input.GetKeyDown("up")
if(Input.GetKey("up"))
if(Input.GetKey("down"))
if(Input.GetKey("left"))
if(Input.GetKey("right"))

(2)偵錯錯誤的指令:
Debug.Log("Up Arrow key was pressed.");
例如:
if(Input.GetKey("up"))
{
transform.position = Vector3.Lerp(transform.position, transform.position+new Vector3(0, 0, 2), 0.3f);
Debug.Log("Up Arrow key was pressed.");
}
結果:才按了一下的up鍵,就執行了10多次的Debug.Log("Up Arrow key was pressed.");
代表執行多次,所以才會向前移動很遠。
成果圖片

28.(寫程式碼)讓狗狗走路(用滑鼠的上下左右點按,操控狗狗移動)
(1)觀念:滑鼠操控3D物件,這兩個的座標不同:
滑鼠座標:畫面screen的2D畫面座標(x,y)(z=0)
3D物件座標:3D世界座標(x,y,z)(一般在地板的物件,y=0)(x,z)
(2)若是要用滑鼠操控3D物體移動,就要先比對兩者的座標差異
(3)就要先轉換成同一種座標系統,才能比較(World世界座標,或Screen畫面螢幕座標)
(4)兩種轉換座標的方法
方法1:把3D物件座標,轉換成Screen畫面螢幕座標
方法2:把滑鼠畫面座標,轉換成world世界座標
(5)方法1:把3D物件座標,轉換成Screen畫面螢幕座標
程式碼內容

//注意:3D物件座標:3D物件.position = transform.position
Vector3 objectToscreenPos = cam.WorldToScreenPoint(transform.position);
//注意:滑鼠的座標:mouseToscreenPos = Input.mousePosition
Vector3 mouseToscreenPos = Input.mousePosition;
mouseToscreenPos.z = 0;
//注意:方法1的滑鼠座標雖然是(x,y,z),但是畫面只有(x,y),所以要設定z=0(mouseToscreenPos.z = 0)

(6)方法2:把滑鼠畫面座標,轉換成world世界座標
程式碼內容

(7)完整程式碼(3):用滑鼠控制物體移動
(採用:方法1:把3D物件座標,轉換成Screen畫面螢幕座標)
程式碼內容
說明:
//注意:3D物件座標:3D物件.position = transform.position
Vector3 objectToscreenPos = cam.WorldToScreenPoint(transform.position);
//注意:滑鼠的座標:mouseToscreenPos = Input.mousePosition
Vector3 mouseToscreenPos = Input.mousePosition;
mouseToscreenPos.z = 0;
//注意:方法1的滑鼠座標雖然是(x,y,z),但是畫面只有(x,y),所以要設定z=0(mouseToscreenPos.z = 0)


26.設定攝影機跟著dog移動
(1)在Assets視窗裡面,滑鼠右鍵→Create→c# script
名稱:camera
(3)hierarchy視窗點選Main Camera物件
(4)把Assets視窗裡面的camera script,拖曵到Main Camera物件的add component
(5)雙擊camera程式,完整程式碼:
程式碼內容
測試結果:果然攝影機可以跟著dog移動
成果圖片


27.(觀念)比較:Collision碰撞 vs Trigger觸發
(1)主要觀念:
1) 想要讓程式判斷兩個物件有接觸,則雙方都必需要有Collider(碰撞器),
並且正在動的一方一定要有Rigidbody(剛體)才有效,另一方有沒有剛體無所謂。
※也就是說,如果動的一方沒有剛體,它去撞的靜止一方即使有剛體,也是當作沒撞到。

2) 接下來有兩種方式判斷接觸,
一、Collision碰撞,造成物理碰撞,可以在碰撞時執行OnCollision函式。
二、Trigger觸發,取消所有物理碰撞,可以在觸發時執行OnTrigger函式。
所以兩個物件A跟B接觸時,不可能同時產生碰撞+觸發,最多產生其中一種,
但是可以辦到讓A跟B產生碰撞,A跟C產生觸發。

3) 產生接觸的設定方式如下:
一、Collision碰撞:雙方都有碰撞器,並且至少動的一方有剛體,
就會造成碰撞,可以執行OnCollision函式。
※但若雙方都勾了Kinematic運動學,或任一方勾了Trigger觸發器,則碰撞無效。

二、Trigger觸發:雙方都有碰撞器,並且至少動的一方有剛體,
並且至少其中一方的碰撞器有勾觸發器,就會造成觸發,可以執行OnTrigger函式。

4) 接觸後的函式又細分為Enter、Stay、Exit三種,
以Trigger為例,就是OnTriggerEnter、OnTriggerStay、OnTriggerExit
(Collision依此類推)。
Enter函式是當兩個物件接觸的瞬間,會執行一次這個函式;
Stay函式是當兩個物件持續接觸時,會不斷執行這個函式;
Exit函式是當兩個物件分開的瞬間,會執行一次這個函式。

(2)進一步解釋:
【Collider碰撞器】:
最重要的核心!只要有碰撞器就會對其他物件產生碰撞;
若自身要受到碰撞的話,則需要碰撞器+剛體,缺一不可。
若自身要受到程式Translate位移或Rotate旋轉,也至少需要碰撞器。

【IsTrigger觸發器】:
勾了就不允許自身受到/造成碰撞,也不會受到重力等物理作用力影響,
而是改為Trigger觸發,雙方碰到時會直接穿越並執行Trigger函式。
但自身還是可以受到程式位移或旋轉。

【Rigidbody剛體】:
允許自身受到碰撞,且動的一方要有剛體才允許產生Trigger觸發。
加了剛體的物件才會受到物理作用力,如受到重力而落下、被物理作用力推動/旋轉,
也無法主動穿越其他碰撞器,這都是受到剛體的影響。
而對方若是沒加剛體,對方就不會受到碰撞的作用力推擠,但仍然可以判斷雙方有碰撞。

【IsKinematic運動學】:
不允許自身受到碰撞,但還是會對其他物件造成碰撞。
也不會受到重力等物理作用力影響。
※雙方都勾運動學的話,雙方都不會受到碰撞,會直接穿越,
 因此會被視為沒有碰撞到,無法執行OnCollision函式。
※對自身而言,剛體+運動學的效果,就等同於不加剛體,
 唯一差異是「剛體+運動學」去撞「靜止的碰撞體」時,
 仍可以執行碰撞、觸發函式;
 但雙方都不加剛體的話,則無法執行碰撞、觸發函式。

【Constraints限制】:
自身受到碰撞時,勾選的位置(Position)、角度(Rotarion)不受力。
很類似把運動學拆成六個細項來設定,但唯一差別在於仍然算有碰撞,
可以照常執行OnCollision函式。

【Drag空氣阻力】:提高數值可減少落下速度、被撞飛距離。

【Angular Drag角阻力】:提高數值可減少旋轉速度。


28.狗狗碰撞到汽車,則顯示game Over,遊戲結束
(1)檢查狗狗dog是否有設定成剛體Rigdibody
選取dog物件→component→Physics→Rigidbody(物理剛體)
設定gravity = 0(否則會落下)
選取dog物件→component→ Physics → box Collider
成果圖片
(2)檢查汽車
選取car物件→component→ Physics → box Collider
打勾IsTrigger
設定Tag
功用:碰到汽車,樹木,終點區,就會觸發Game Over遊戲結束)
選取car→Add Tag→ + →
Tag0:car

注意:要設定的汽車物件有
1.場景中的car1,car2
2.在assets/models/裡面的預鑄物件,car1_prefab,car2_prefab,car3_prefab,car4_prefab

(3)檢查樹木
選取car物件→component→ Physics → Box Collider
打勾IsTrigger
設定Tag
功用:碰到汽車,樹木,終點區,就會觸發Game Over遊戲結束)
選取car→Add Tag→ + →
Tag0:tree

注意:要設定的樹木物件有
1.場景中的Park,Park2群組裡面的tree,tree1,tree2,tree3

(4)建立終點區域
方法:加入一個看不見(透明)的cube物件,若是cube被碰撞了,就表示有得分
1).新增GameObject→3D Object→cube
設定名稱:cube
調整位置,大小
Position(x,y,z) = 0,0,23.5
Rotation(x,y,z) = 0,0,0
Scale(x,y,z) = 100,1,10
2).設定碰撞事件:is Trigger打勾
3).設定不顯示:box Renderer取消打勾
4).選取car→Add Tag→ + → Tag0:final
成果圖片

(5)(寫程式)當is Trigger被觸發,則
打開walk(script)
寫程式碼:當遇到car就會顯示GameOver
固定套路寫法:3D碰撞(可以直接複製)
void OnTriggerEnter (Collider other)
{
if (other.tag == "car")
{
//Debug.Log("car-Game Over");
output = "Game Over";
}
}
void OnGUI()
{
GUILayout.BeginHorizontal("box1");
GUILayout.Label(output);
GUILayout.EndHorizontal();
}

(6)walk完整程式碼:
程式碼內容


29.當狗狗碰撞到汽車,顯示game Over後,狗狗無法再移動,遊戲停止
(1)方法:宣告一個isMoving變數,當true可以移動,當false不可以移動
bool isMoving = true;
public void Update()
{
if(isMoving == true)
{
if (Input.GetMouseButtonUp(0))
{
//狗狗移動..............
}
}
}
void OnTriggerEnter (Collider other)
{
if (other.tag == "final")
{
output = "恭喜,你已經成功過關。";
isMoving = false;
}
if (other.tag == "car" || other.tag == "tree")
{
//Debug.Log("car");
output = "Game Over,遊戲結束";
isMoving = false;
}
}
(2)walk完整程式碼:
程式碼內容


30.使用GUISkin(圖形使用者介面面板)顯示分數
(1)在Assets→Create→GUISkin
成果圖片
修改名稱:MyGUISkin
(2)設定GuiSkin的顏色顏色:
Label→Normal→Text Color = yellow
Label→Font Size = 36
成果圖片
(3)在walk c#程式碼裡面,設定
public GUISkin customSkin;
public Texture TextureScore;
int mScore = 0;
(4)選取dog物件,看walk.c#
設定custom skin = myGUISkin(把myGUISkin拖曵進去)
成果圖片
設定Texture Score= Coin圖片
成果圖片
(5)(寫程式碼)向前一步加1分,後退一步減去1分
打開walk.c#
//用鍵盤↑↓上下鍵操控
if (Input.GetKeyDown("up"))
{
transform.position = Vector3.Lerp(transform.position, transform.position + new Vector3(0, 0, 2), 0.3f);
mScore ++;
}
if (Input.GetKeyDown("down"))
{
transform.position = Vector3.Lerp(transform.position, transform.position + new Vector3(0, 0, -2), 0.3f);
mScore --;
}
(5)(寫程式碼)畫面顯示score: 2,並且顯示coin圖片,紅色36大小字體
打開walk.c#
void OnGUI()
{
GUI.skin = customSkin;
GUI.Label(new Rect( 80, 25, 100, 60 ), "score : ");
GUI.Label(new Rect( Screen.width-35, 25, 100, 60 ), mScore.ToString() );
GUI.DrawTexture(new Rect(10, 10, 60, 60), TextureScore , ScaleMode.ScaleToFit, true, 1.0F);
}

(6)walk完整程式碼:
程式碼內容

程式結果:
成果圖片
成果圖片

 
 
chp2.第一個3D專案

觀看

本範例的成果圖片

下載

下載本章project成果檔案