設為首頁收藏本站

HKCDC討論區

 找回密碼
 註冊

QQ登錄

只需一步,快速開始

搜索

參謀

路過的神祕人一個

積分
1300
JLChnToZ 發表於 2014-2-16 16:58:48 |顯示全部樓層
本帖最後由 JLChnToZ 於 2014-2-16 17:29 編輯

大家好~ 這是我的第一次發教學帖
這次我會教大家如何使用 Unity 編寫一個簡單的遊戲
嘛... 既然說是基礎, 那麼就... 仿製一個簡單點的遊戲吧 (笑)
這一隻怎樣?

(按圖片進去看看吧, 這是論壇的 Flash 遊戲而已)

在開始之前, 我已假定大家會用 3D 軟件 (如 Maya) 建模,還有就是怎樣也會寫一點類 C++ (C#, Java 之類的) 的程式語言
[[如果不會用 3D 軟件的話請先去惡補一下, 這論壇是有這方面的教學的!]]
好了啦~ 事不宜遲, 先把咱們的 Unity 打開吧~

首先, 開一個新的 Project... 至於名字呢... 既然是 Missle... 就叫 Missle Game 吧~!

然後呢, 放一盞燈 (spot light) 進去吧~

接著把燈放到主鏡頭 (Main Camera) 裡, 再把座標旋轉全部歸零

至於鏡頭呢... 把它的起始座標設成這樣吧,
背景顏色方面, 變成深灰色吧:


調好後應該會在場景編輯畫面看到這個樣子:

都弄好之後先儲存一下唄~ ((叫 Main Scene 好了, 已經懶得想名字了啦~



好了~ 基本的燈光和鏡頭已經設好了, 再來就要開始搭場景了~
大家先去看一下上面的遊戲, 不難發現整個遊戲場景像是在一個管道裡, 所以...
咱們先弄管子吧!
現在來打開你熟悉的 3D 軟件 (咱最熟悉 Maya, 所以就拿 Maya 來用了)
用你的方法拉一條直管出來
直徑最好是 100, 長度最少 1000+, 管子的厚度不重要的說~

直接把這管子匯出成 fbx 款式 (或者其他 Unity 支援的格式也可)

直接命名為 "Pipe" 好了
先不要急著關掉 3D 軟件~ 咱們還有東西沒做好的~
再來就是做障礙物, 先把管子的厚度弄大, 還有就是不要太長, 短短的就好:

把這個環也匯出吧, 命名為 "Part1" 就好
然後就發揮你的創意, 把這個環裡面做點變化, 例如這樣:

再次匯出成 "Part2" 吧
重複幾次, 做幾個版本, 這部分就完成了~


到這裡, 你應該會先後儲存了這些檔案:

不用說了, 這些通通拉到 Unity 裡吧!

如果你是喜歡整潔的人, 不妨在 Assets 開一個資料夾, 才把這些模組拉到裡面
然後, 先把那直直的管子拉到場景裡, 同樣的, 所有座標歸零:

接著就是最精采的部分----遊戲編程!
先開一個 Dummy 的遊戲物件, 用來處理遊戲程式的
接著, 把它命名為 "MainController" 以及把它的 Tag 選成 "GameController"
然後打開最下面的 "Add Component" -> "New Script", 開一個新的腳本叫 "LevelController" 吧 (別忘了把 Language 記成 C#, 否則下面你會出錯滴)

點兩下這個 "LevelController", 等一下之後應該會出現 MonoDevelop 的畫面了~

先來一個簡單的~ 用滑鼠移動鏡頭吧~
把程式碼改成這樣再 save:
  1. using UnityEngine;
  2. using System.Collections;

  3. public class LevelController : MonoBehaviour {
  4.         Vector3 lastMousePos;

  5.         // Use this for initialization
  6.         void Start () {
  7.                 lastMousePos = Input.mousePosition; // 儲存起始滑鼠位置
  8.         }
  9.         
  10.         // Update is called once per frame
  11.         void Update () {
  12.                 Vector3 pos = Input.mousePosition; // 現在的滑鼠位置
  13.                 Vector3 diff = (pos - lastMousePos) / 100; // 與上一個位置的差
  14.                 Camera.main.transform.position += new Vector3(diff.x, 0, diff.y); // 移動鏡頭
  15.                 lastMousePos = pos; // 儲存新的滑鼠位置
  16.         }
  17. }
複製代碼

這個時候你可以回去 Unity 測試一下了~ (建議不要把 MonoDevelop 關閉, 否則等下再修改程式的時候又要非常有耐性的等它啟動)
應該不難發現移動滑鼠雖然可以移動鏡頭, 但完全沒有限制其範圍, 要移動到管子外完全不是難事吧?
這不是咱們想要的, 所以有必要追加點限制...
再回去 MonoDevelop 的畫面, 追加以下程式到原本的程式中:
  1. ...
  2.         Vector3 lastMousePos;
  3.         const float maxDistance = 0.7F; // 限定最大距離
  4. ...
  5.         void Start () {
  6.                 lastMousePos = Input.mousePosition; // 儲存起始滑鼠位置
  7.                 cameraPos = Camera.main.transform.position; // 儲存起始鏡頭位置
  8.         }
  9. ...
  10.         void Update () {
  11.                 Vector3 pos = Input.mousePosition; // 現在的滑鼠位置
  12.                 Vector3 diff = (pos - lastMousePos) / 100; // 與上一個位置的差
  13.                Vector3 pos2 = Camera.main.transform.position; // 取得現在的鏡頭位置
  14. ...
複製代碼

再儲存測試吧, 現在應該限制了可移動的範圍吧 (?)
接著咱們就要把障礙物也放進去了, 把 Asset 裡的 "Part1" 拉到場景中吧~ (重複的話不想再說了, 座標要清零~)
然後就再次的... 創建一個新的 Script... 這次叫 "PartBehavior" 吧

點兩下剛創建的程式, 再次進入 MonoDevelop
輸入以下的程式:
  1. using UnityEngine;
  2. using System.Collections;

  3. public class PartsBehavior : MonoBehaviour {
  4.         public float speed = 0.1F; // 速度
  5.         public float startpos = 0F; // 開始位置
  6.         public float endpos = 10F; // 結束位置

  7.         // Use this for initialization
  8.         void Start () {

  9.         }
  10.         
  11.         // Update is called once per frame
  12.         void Update () {
  13.                 if(gameObject.transform.position.y >= endpos) { // 如果 Y 座標大於最大值
  14.                         gameObject.transform.position -= new Vector3(0, endpos - startpos, 0); // 回去開始位置
  15.                 } else { // 否則
  16.                         gameObject.transform.position += Vector3.up * speed; // 以速度的值移動
  17.                 }
  18.         }
  19. }
複製代碼

現在測試一下應該會發現整個場景會好像不斷向前走, 但感覺那個環與環之間的距離好像太疏了吧?
好~ 那就複製多點吧!
回去 "LevelController", 追加以下的程式:
  1. ...
  2.         public int DodgeObjectCount = 5; // 環的數量
  3.         public float DodgeObjectDistance = 2; // 環之間的距離
  4.         public PartsBehavior[] behaviors; // 環的行為定義

  5.         // Use this for initialization
  6.         void Start () {
  7. ...
  8.                 GameObject go = GameObject.Find ("part1"); // 取得 "Part1" 的程式
  9.                 behaviors = new PartsBehavior[DodgeObjectCount+1]; // 初始化環的定義數量
  10.                 behaviors[DodgeObjectCount] = go.GetComponent<PartsBehavior>(); // 取得第一個環的行為定義
  11.                 for(int i = 0; i < DodgeObjectCount; i++) {
  12.                         GameObject g = (GameObject)Instantiate(go); // 複製一個環
  13.                         g.transform.position += Vector3.up * DodgeObjectDistance * (i + 1); // 設定這個環的位置
  14.                         behaviors[i] = g.GetComponent<PartsBehavior>(); // 取得這個環的定義
  15.                 }
  16.         }
  17. ...
複製代碼

測試一下~ 現在應該多點.... 也太密了吧

那現在需要做的就是... 把數量減少
順帶一提, 除了在 MonoDevelop 裡面直接改預設數值之外, 還可以在 Unity 裡面直接修改的
基本上全部在 MonoDevelop 裡面定義的公用變數都可以在 Unity 裡面作個別修改, 換句話說, 同一段程式可以重複使用的同時也可以有不同的參數
所以這次可以這樣改:

現在應該會看到舒服多了吧? (笑
雖然如此, 但不也覺得太單調了吧? 每個環都是一模一樣的, 一點考驗性也沒有
現在就來難點的東西了囉~ 讓那些環都隨機起來好了
現在回去 "PartsBehavior" 修改修改吧:
  1. ...
  2.         private MeshFilter meshFilt; // 形狀的處理器
  3.         private Mesh initMesh; // 起始的形狀
  4.         public Mesh mesh1; // 第一個形狀
  5.         public Mesh mesh2; // 第二個形狀
  6.         public Mesh mesh3; // 第三個形狀
  7.         
  8.         float rotatespeed;

  9.         // Use this for initialization
  10.         void Start () {
  11.                 meshFilt = gameObject.GetComponent<MeshFilter>(); // 取得形狀處理器
  12.                 initMesh = meshFilt.mesh; // 定義起始形狀
  13.         }
  14.         
  15.         // Update is called once per frame
  16.         void Update () {
  17.                 if(gameObject.transform.position.y >= endpos) { // 當 Y 座標大於結束位置時
  18. ...
  19.                         switch(Random.Range (0, 3)) { // 隨機改變形狀
  20.                                 case 0: meshFilt.mesh = initMesh; break;
  21.                                 case 1: meshFilt.mesh = mesh1; break;
  22.                                 case 2: meshFilt.mesh = mesh2; break;
  23.                                 case 3: meshFilt.mesh = mesh3; break;
  24.                         }
  25. ...
複製代碼

再回去 Unity, 把其餘的障礙物也定義到程式裡吧:
點 Mesh 1, Mesh 2,... 右邊的圓圈選擇吧

現在應該沒有那麼單調了

再來, 讓那些障礙物旋轉吧~
在 "PartsBehavior" 加入這些程式:
  1. ...
  2.         float rotatespeed;

  3.         // Use this for initialization
  4.         void Start () {
  5. ...
  6.                 rotatespeed = (Random.value - 0.5F) * 2;
  7.         }
  8.         // Update is called once per frame
  9.         void Update () {
  10.                 if(gameObject.transform.position.y >= endpos) {
  11. ...
  12.                         rotatespeed = (Random.value - 0.5F) * 2;
  13.                 }
  14. ...
複製代碼

現在再測試應該會轉了

下次我會再發佈障礙物判定的教學等等~
這次教學的參考專案:

以上的教學我不介意轉載, 但轉載前請先通知一下, 謝謝


如要查看全部, 請登錄註冊 QQ登錄
附件: 你需要登錄才可以下載或查看附件。沒有帳號?註冊

使用道具 舉報

積分
2921
destroylim 發表於 2014-2-16 17:08:59 |顯示全部樓層
很專業的樣子耶...

使用道具 舉報

上尉

積分
25730

最高榮譽勳章

哈KING哈 發表於 2014-2-16 18:52:10 |顯示全部樓層
可以叫係高水平教學啦

Counter Strike: Global Offensive名稱 :~Ha*KING*Ha~
Counter Strike 1.6名稱 :~Ha*KING*Ha~

CS1.6冇玩了,CSGO吧

使用道具 舉報

參謀

路過的神祕人一個

積分
1300
JLChnToZ 發表於 2014-2-16 19:42:51 |顯示全部樓層
哈KING哈 發表於 2014-2-16 18:52
可以叫係高水平教學啦

過獎了~ 謝謝

使用道具 舉報

積分
20669

最高榮譽勳章

lzi19 發表於 2014-2-17 18:33:57 |顯示全部樓層
內容詳細 教學簡單 值得稱讚
路遙知馬力

使用道具 舉報

積分
608
davidchan098 發表於 2014-2-21 21:02:14 |顯示全部樓層
好PRO WOR~UNITY3D 易學難精

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 註冊

Archiver|手機版|HKCDC   

GMT+8, 2017-10-22 05:35 , Processed in 0.132113 second(s), 18 queries .

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回頂部