(譯)【Unity教程】使用Unity開發Windows Phone上的橫版跑酷遊戲

譯者注:html

目前移動設備的跨平臺遊戲開發引擎基本都是採用Cocos2d-x或者Unity。通常而言2d用cocos2d-x 3d用unity,可是對於Windows Phone開發者,程序員

cocos2d-x for wp8是微軟維護的,版本升級十分緩慢,到如今仍是 V2.0 preview,咱們不可能拿一個不太穩定的版本去開發遊戲。與之相反,Unity4.2發佈以後,架構

支持WP8和Windows8,固然也包括其餘平臺,開發調試都是十分便捷,所以使用Unity來開發目標用戶在WP上的遊戲,是個很好的選擇。app

 

這是一篇譯文,原文很長,因而我把它分紅了兩部分,並且加入了本身的一些修改和理解,點擊一下連接觀看第一部分效果。(須要安裝最新的unity插件)dom

http://jeekun.sinaapp.com/share/flash/flash.htmlide

原文:http://catlikecoding.com/unity/tutorials/runner/函數

介紹                                                                                                                                       

在這篇教程裏,咱們將學習如何去製做一款簡單的無盡跑酷遊戲,在這裏你將學到:學習

  • 生成一個分層的背景
  • 重用對象
  • 使用物理引擎
  • 經過檢測輸入來控制玩家跳躍
  • 實現能量增長
  • 一個簡單的事件管理器
  • 按需控制物體的開關
  • 製做一個簡單的GUI

遊戲設計                                                                                                                                  ui

在開始以前,咱們應該先考慮一下在遊戲裏面加入什麼。咱們要作的是一個2D側卷軸遊戲,可是仍是太寬泛了,讓咱們來縮小一下範圍。this

遊戲的玩法咱們將控制一我的物不斷的向屏幕右側奔跑,從一個平臺跳到另一個平臺,要跑的儘量的遠。這些平臺有不一樣的特性,有的會讓你加速,

有的會讓你減速。咱們還包含單一的能量球,可讓你在空中跳躍。

遊戲圖形咱們將使用純Cube和標準的粒子系統來製做(程序員的悲哀。。。) 玩家,平臺,包括背景,通通都是Cube,而粒子系統將被用於製做運動軌跡,

不少漂浮物將會給人更好的速度和深度的感受。

另外,遊戲不包括特效音和背景音。

創建場景                                                                                                                                   

打開Unity,建立一個新的工程,不要導入任何的包。

咱們是要作的2D視角的遊戲,可是還想有一點3D的效果,Orthographic攝像機是不能用於3D遊戲的,所以咱們得采用默認的Perspective類型。這樣的話,將物體放到離鏡頭不一樣

的距離,咱們就能獲得一個分層的滾動背景。

就讓咱們假定,前景是在距離0,第一個背景在距離50,第二個背景在距離100。讓咱們分別放三個Cube在這三個深度,而且將他們做爲建立場景的引導者。我本身已經試過了一些角度和顏色組合,

以爲還能夠,固然你也能夠本身去實驗一些新的數值。

 

下面正式開始:

首先添加一個平行光(GameObject->Create Other->Directional Light),設置旋轉爲(20,330,0)

而後設置攝像機的參數,顏色爲(115,140,220)

其餘數值見圖:

建立3個Cube, Position 分別是(0,0,0) (0,0,50) (0,0,100),名字對應的是 Runner, Skyline Close, Skyline Far Away,後兩個Skyline Cube 不須要

碰撞器(Box Collider),直接在屬性面板裏,右鍵移除組件便可。 Runner是此次遊戲的豬覺,在這裏我稱之爲 「奔跑者」,後面同之。

給3個Cube分別建立材質(Project 視圖,Create-> Material),命名爲Runner Mat, Skyline Close Mat, Skyline Far Away Mat. 而後分別拖放到對應的Cube上。

我使用了默認的 diffuse Shader , 顏色分別設爲, White, (100, 120, 220), (110, 140, 220), 設置完成後的值以下:

           

爲了使項目的組織架構更好,咱們在Project視圖裏增長2個文件夾,Runner, Skyline, 而後把材質放到對應的文件夾裏。

運行一下,能夠看到3個Cube都出如今了視野裏面。

開始跑步吧                                                                                                                                           

到目前爲止,咱們作的還沒什麼奇特的,場景裏面什麼也沒有發生,可是接下來就是見證奇蹟的時刻了。

讓咱們來讓 「奔跑者」 向右邊移動來模擬一下這個遊戲吧。

在Runner文件夾裏建立一個C#腳本,Runner.cs

using UnityEngine;
using System.Collections;

public class Runner : MonoBehaviour {

    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
        transform.Translate(5f * Time.deltaTime, 0f, 0f);
    }
}

把腳本拖到層次視圖的Runner 上面,運行,怎麼樣,看到主角開始跑了吧。可是有個問題,攝像頭沒有跟隨它在運動,沒一會就跑出咱們的視野了,

這樣的遊戲根本無法玩啊,也不是咱們想要的。解決的方法很簡單,把攝像機對象拖到Runner裏,讓他成爲Runner的Child.

   如今再運行的話就沒有問題了,並且咱們能夠發現,遠處的Cube要比進出的Cube移動的好像快一些,固然這就是視差的問題了。

生整天際線                                                                                                                                        

如今咱們已經有了基本的運動了,接下來讓咱們生成一行的Cube來實現無止境的天際線。首先有件事情咱們必須意識到,名爲無盡的,其實只須要一部分存在地圖中就能夠了,

由於隨着鏡頭不斷的右移,左側的天際線不斷消失在視野中,他們是能夠被銷燬的,沒有必要再繼續佔用資源了。或者,咱們能夠將它移動位置,在右側重建場景,省去了重複的

建立開支。

經過這個特性,咱們只須要不多的資源就能夠建立無止盡的天際線了。

在Skyline 文件夾中建立一個SkylineManager的腳本,由於要經過一個腳本建立兩個天際線,因此須要傳一個值進來,知道是要建立具體哪一種。

public Transform prefab;

一樣的,爲了場景層次視圖中的組織結構友好,咱們須要設置一下層次。 首先新建一個空對象,起名Managers, 做爲父容器。

而後給它建立一個子對象 Skyline Close Manager,而後把腳本拖到這個對象上來。

接下來把Skyline Close和Skyline Far Away 這兩個Cube拖拽到Project中的Skyline文件夾下,使之成爲Prefab,而後將層次視圖中的兩個對象刪除,

設置好以後,層次視圖和Project視圖以下所示:

      

如今咱們須要一個起點指示咱們從哪裏開始構建天際線,咱們能夠經過Manger對象自己的位置,並且咱們須要一個數量值來決定多少個Cube組合起來才能填充完屏幕,

新建一個變量叫作 numberOfObjects ,另外聲明一個變量 nextPosition ,指示左邊的對象無效以後,應該在哪裏重建。

public Transform prefab;
public int numberOfObjects;

private Vector3 nextPosition;

void Start()
{
    nextPosition = transform.localPosition;
}

下一步是建立初始行的Cube,經過一個for循環來實現,實例化咱們以前建立爲prefab的Cube,每個cube的位置都是nextPosition,並且隨着沒添加一個動態修改這個變量的值

void Start()
{
    nextPosition = transform.localPosition;

    for (int i = 0; i < numberOfObjects; i++)
    {
       Transform o = (Transform)Instantiate(prefab);
        o.localPosition = nextPosition;
        nextPosition.x += o.localScale.x;
    }
}

如今設置Skyline Close Manager 的Position 爲(0, -1, 0) 而且設置 numberOfObjects 變量的值爲10 ,運行

 

能夠看到出現了一連串的Cube了,有點「地平線」的影子了,可是有個問題就是「天際線」自己不會隨着鏡頭運動,去往左側就消失不見了。

咱們回收重用Cube的策略是隻回收那些離玩家超過必定距離的,所以必定要知道玩家跑了有多遠,爲了達到這個目的,咱們在 Runner.cs 裏

添加一個靜態變量,並且時時更新它。

public static float distanceTraveled;

// Use this for initialization
void Start () {
    
}
    
// Update is called once per frame
void Update () {
  transform.Translate(5f * Time.deltaTime, 0f, 0f);

    //由於起始位置是 0
  distanceTraveled = transform.position.x;
}

如今咱們將要把咱們的組成地平線的物體放到一個隊列裏,而且不斷的檢查是否要回收,由於是隊列,只須要檢查第一個便可,若是是須要回收,

從隊列中移除,修改位置,而後放到隊列最後邊就能夠了。

咱們用一個recycleOffset變量來配置具體物體落後玩家多遠的話 能夠回收,這裏設置爲 60 .

public class SkylineManager : MonoBehaviour {

    public Transform prefab;
    public int numberOfObjects;
    public float recycleOffset;

    private Vector3 nextPosition;
    private Queue<Transform> objectQueue;

    void Start()
    {
        objectQueue = new Queue<Transform>(numberOfObjects);
        nextPosition = transform.localPosition;

        for (int i = 0; i < numberOfObjects; i++)
        {
            Transform o = (Transform)Instantiate(prefab);
            o.localPosition = nextPosition;
            nextPosition.x += o.localScale.x;

            objectQueue.Enqueue(o);
        }
    }

    // Update is called once per frame
    void Update () {
        if (objectQueue.Peek().localPosition.x + recycleOffset < Runner.distanceTraveled)
        {
            Transform o = objectQueue.Dequeue();
            o.localPosition = nextPosition;
            nextPosition.x += o.localScale.x;
            objectQueue.Enqueue(o);
        }
    }
}

如今運行,在Scene視圖裏,能夠看到Cube行 是隨着 「奔跑者」 不斷的從新修正本身的位置的。可是他如今看起來還不像天際線,爲了生成更像實際的

沒有規則的天際線,讓咱們在它生成或者充值的時候隨機放大它。

首先考慮到會有重複的代碼產生,首先寫個函數Recycle ,在start或者update的時候都調用它。

public class SkylineManager : MonoBehaviour
{

    public Transform prefab;
    public int numberOfObjects;
    public float recycleOffset;

    private Vector3 nextPosition;
    private Queue<Transform> objectQueue;

    void Start()
    {
        objectQueue = new Queue<Transform>(numberOfObjects);
        for (int i = 0; i < numberOfObjects; i++)
        {
            objectQueue.Enqueue((Transform)Instantiate(prefab));
        }
        nextPosition = transform.localPosition;
        for (int i = 0; i < numberOfObjects; i++)
        {
            Recycle();
        }
    }

    void Update()
    {
        if (objectQueue.Peek().localPosition.x + recycleOffset < Runner.distanceTraveled)
        {
            Recycle();
        }
    }

    private void Recycle()
    {
        Transform o = objectQueue.Dequeue();
        o.localPosition = nextPosition;
        nextPosition.x += o.localScale.x;
        objectQueue.Enqueue(o);
    }
}

下一步,讓咱們加入兩個變量分別表示容許的放大最大和最小值,當放大一個物體以後,咱們要肯定能夠保證後面的物體和前面的

都是底部對齊的,

public class SkylineManager : MonoBehaviour
{
    public Transform prefab;
    public int numberOfObjects;
    public float recycleOffset;

    public Vector3 minSize, maxSize;

    private Vector3 nextPosition;
    private Queue<Transform> objectQueue;

    void Start()
    {
        objectQueue = new Queue<Transform>(numberOfObjects);
        for (int i = 0; i < numberOfObjects; i++)
        {
            objectQueue.Enqueue((Transform)Instantiate(prefab));
        }
        nextPosition = transform.localPosition;
        for (int i = 0; i < numberOfObjects; i++)
        {
            Recycle();
        }
    }

    void Update()
    {
        if (objectQueue.Peek().localPosition.x + recycleOffset < Runner.distanceTraveled)
        {
            Recycle();
        }
    }

    private void Recycle()
    {
        Vector3 scale = new Vector3(
            Random.Range(minSize.x, maxSize.x),
            Random.Range(minSize.y, maxSize.y),
            Random.Range(minSize.z, maxSize.z));

        Vector3 position = nextPosition;
        position.x += scale.x * 0.5f;
        position.y += scale.y * 0.5f;

        Transform o = objectQueue.Dequeue();
        o.localScale = scale;
        o.localPosition = position;
        nextPosition.x += scale.x;
        objectQueue.Enqueue(o);
    }
}

爲了獲得一個漂亮的天際線效果,把這個Manager放到(-60,-60, 50),而且將MinSize 設置爲(10,20,10) MaxSize設置爲(30,60,10)Recycle Offset 設置爲60

讓咱們繼續添加第二個天際線層,選中Skyline Close Manager "CTRL+D " 複製一份,而且更名爲 Skyline Far Away Manager, 將它的prefab屬性改成 Skyline Far Away 這個預設。

它的位置設置爲(-100,-100, 100) 它的Recycle Offset 爲 75,MinSize爲(10,50,10) MaxSize爲(30,100,10) 固然你也能夠照你本身的喜愛來設置新的值

   

產平生臺                                                                                                                   

生成平臺跟生整天際線很像,稍微有點不一樣的是平臺的高度須要隨機設定,並且他們之間須要有溝壑。而且咱們須要約束平臺的高度,好讓它不會影響天際線的顯示,

若是平臺超出這個範圍了,咱們須要給它糾正過來。

在Project視圖裏新建一個文件夾,取名字叫作Platform, 而後在裏面建立一個C#腳本,叫作 PlatformManager, 而後把SkylineManager的腳本拷貝到這裏來,

修改一部分源碼以下:

public class PlatformManager : MonoBehaviour {

    public Transform prefab;
    public int numberOfObjects;
    public float recycleOffset;

    public Vector3 minSize, maxSize, minGap, maxGap;
    public float minY, maxY;

    private Vector3 nextPosition;
    private Queue<Transform> objectQueue;

    void Start()
    {
        objectQueue = new Queue<Transform>(numberOfObjects);
        for (int i = 0; i < numberOfObjects; i++)
        {
            objectQueue.Enqueue((Transform)Instantiate(prefab));
        }
        nextPosition = transform.localPosition;
        for (int i = 0; i < numberOfObjects; i++)
        {
            Recycle();
        }
    }

    void Update()
    {
        if (objectQueue.Peek().localPosition.x + recycleOffset < Runner.distanceTraveled)
        {
            Recycle();
        }
    }

    private void Recycle()
    {
        Vector3 scale = new Vector3(
            Random.Range(minSize.x, maxSize.x),
            Random.Range(minSize.y, maxSize.y),
            Random.Range(minSize.z, maxSize.z));

        Vector3 position = nextPosition;
        position.x += scale.x * 0.5f;
        position.y += scale.y * 0.5f;

        Transform o = objectQueue.Dequeue();
        o.localScale = scale;
        o.localPosition = position;
        nextPosition.x += scale.x;
        objectQueue.Enqueue(o);

        nextPosition += new Vector3(
            Random.Range(minGap.x, maxGap.x) + scale.x,
            Random.Range(minGap.y, maxGap.y),
            Random.Range(minGap.z, maxGap.z));

        if (nextPosition.y < minY)
        {
            nextPosition.y = minY + maxGap.y;
        }
        else if (nextPosition.y > maxY)
        {
            nextPosition.y = maxY - maxGap.y;
        }
    }
}

而後就要建立一個用於顯示平臺的形狀了,在Skyline文件夾裏,選中Skyline Close Mat ,Ctrl+D複製一份,顏色改成(255,60,255)而後拖放到Platform裏,

更名爲Platform Regular Mat, 而後建立一個Cube,把這個Meterial 拖放到Cube上,而後把Cube拖回到Platform文件夾裏,使之成爲預設,更名爲Platform 

在層次視圖裏建立一個 Empty GameObject,命名爲Platform Manager, 一樣也放到Managers 下面,成爲它的子對象。把Platform Manager這個腳本拖放到對象上,成爲它的

組件。參考下圖設置一下腳本的各個變量的值。

跳躍和墜落                                                                                                                        

如今有平臺了,是時候升級一下咱們的「奔跑者」了,咱們使用物理引擎來實現跑,跳,墜落等效果。選中在層次視圖裏選中「奔跑者」,而後Compnent->physics->rigid body,

給它添加物理引擎支持,由於咱們不想讓它旋轉也不想跳出咱們的視野,所以要給他添加 Z軸約束而且鎖定全部的旋轉方向。

由於運動將會在平臺上平滑的移動來完成,讓咱們來建立一個沒有摩擦的材質(Project 視圖上 Platform文件夾上 Create->Physics Material)。 具體設置以下圖所示。

將這個物理材質設置爲層次試圖裏的 Runner的 Box Collider 組件的 Material 屬性

把Runner的Position 設置爲(0,2,0)這樣的話 一開始 「跑步者」 就會降落在平臺上,而後開始運動。

運行一下,能夠看到「跑步者」落到平臺,而後向右側運動,跟設想的如出一轍,可是假如它蹭到平臺的邊緣,就會發現運動有些奇怪。這是由於即便在這個狀況下,Update也不會不斷修改奔跑者」位置的,

讓咱們換一種方式,使用物理引擎,採用添加「力」來使物體位置改變。

把Runner.cs代碼修改以下:

public class Runner : MonoBehaviour {

    public static float distanceTraveled;

    public float acceleration;

    private bool touchingPlatform;

    void Update()
    {
        distanceTraveled = transform.localPosition.x;
    }

    void FixedUpdate()
    {
     //碰撞的時候不會繼續做用力
if (touchingPlatform) { rigidbody.AddForce(acceleration, 0f, 0f, ForceMode.Acceleration); } } void OnCollisionEnter() { touchingPlatform = true; } void OnCollisionExit() { touchingPlatform = false; } }

設置acceleration的值爲5

在Platform文件夾裏,像剛纔那樣給Platform也建立物理材質,命名爲 Platform Regular PMat, 設置以下,而後把它複製給Platform的預設(prefab)

如今平臺有了一些摩擦力,可是由於有持續做用力,因此咱們的「跑步者」可以克服這些阻力。下面再給Runner.cs 添加一個變量來控制「跑步者」的跳躍速度。

添加變量 jumpVeclocity 設置爲 (1,7,0)

將 Runner.cs 代碼改成以下:

public class Runner : MonoBehaviour {

    public static float distanceTraveled;
    public Vector3 jumpVelocity;

    public float acceleration;

    private bool touchingPlatform;

    void Update()
    {
        if (touchingPlatform && Input.GetKeyDown(KeyCode.A))
        {
            Debug.Log(1);
            rigidbody.AddForce(jumpVelocity, ForceMode.VelocityChange);
        }
        distanceTraveled = transform.localPosition.x;
    }

    void FixedUpdate()
    {
        if (touchingPlatform)
        {
            rigidbody.AddForce(acceleration, 0f, 0f, ForceMode.Acceleration);
        }
    }

    void OnCollisionEnter()
    {
        touchingPlatform = true;
    }

    void OnCollisionExit()
    {
        touchingPlatform = false;
    }
}

如今運行,而後按下鼠標左鍵,就可讓咱們的「跑步者」跳躍了。

可是玩一會就發現,假如「奔跑者」碰到平臺的邊緣,咱們能夠經過不斷的按鼠標左鍵來防止墜落。

這是一個bug,須要修復一下。

解決方案很簡單,一旦玩家按下鼠標左鍵,就將touchingPlatform變量的值設爲false,就不能夠連續的跳躍了。

    void Update()
    {
        if (touchingPlatform && Input.GetKeyDown(KeyCode.A))
        {
            touchingPlatform = false;
            rigidbody.AddForce(jumpVelocity, ForceMode.VelocityChange);
        }
        distanceTraveled = transform.localPosition.x;
    }

部署到Windows Phone                                                                                                        

由於Unity的跨平臺作的實在是太好了,咱們只須要簡單兩步就能夠生成Windows Phone的工程,在菜單欄 File-> Build Setting彈出對話框

而後選擇 Player Setting

修改一下 Orientation ,連上你的WP8手機,而後點擊 Build & Run ,會彈出一個選擇文件夾的對話框,由於Unity會幫咱們生成工程,因此這也就是工程的所在地,

新建文件夾 Projects->WP8 而後選擇,等待一會編譯完成,會發現遊戲開始了,很興奮吧!這麼簡單就能夠作一款遊戲,so easy, 老闆不再擔憂項目進度了。

可是!!!

還有問題,由於沒有處理回退事件,因此如今的遊戲是沒法經過後退按鈕退出的,找到編譯出來的項目工程,打開,而後註釋後退事件的代碼:

private void PhoneApplicationPage_BackKeyPress(object sender, CancelEventArgs e)
{
      //e.Cancel = UnityApp.BackButtonPressed();
}

OK,至此,第一部分項目完成了,請等待 後續 的到來。

附項目下載地址:點擊下載

相關文章
相關標籤/搜索