2016年8月2日 星期二

【Unity】轉珠系統製作Part.1 - 產生盤面

             Part.2

這次要來做轉珠遊戲中的關鍵要素─轉珠系統,全部完成可能需要六到七篇左右,第一篇就從產生盤面開始吧,下圖為這次的目標。
按下執行時,依照盤面的行列數產生相同數量的珠子,並且隨機賦予珠子屬性(不考慮消除)。

準備需要的圖檔資源。
在專案(Project)中新增Resources資料夾,並在Resources資料夾下新增Image資料夾。
在Image資料夾中新增背景圖、各屬性的珠子圖、珠子消除後的Null圖。
將全部圖檔的類型(Texture Type)修改成Sprite格式。

新增Canvas。
在階層中新增Canvas,並調整比例模式(UI Scale Mode)為Scale With Screen Size。
參照的解析度(Reference Resolution)為720X1280,數值可以依開發環境為基準。

新增背景圖物件(Background)。
Canvas下新增Image物件,並選擇背景圖檔。
修改背景圖的座標原點至左下角(bottom left)。
修改圖檔的寬(Width)與高(Height)為720X600,可以依個人情況調整。
將支點(Pivot)設為(0, 0),也就是左下角。

新增珠子物件(Orb)。
新增Image物件作為珠子物件。
和背景圖相同,修改座標原點、寬高和支點。

將珠子物件設為Prefabs並新增腳本。
Resources資料夾下新增Prefabs資料夾,並將珠子物件從階層拖曳至資料夾中。
在珠子物件上新增腳本Orb,Orb腳本會做珠子被新增時的初始化

新增轉珠系統控制物件(PuzzleSystem)。
新增空物件PuzzleSystem並在上面新增腳本PuzzleSystem。
腳本PuzzleSystem會做整個系統的流程控制。

回到Orb腳本,新增珠子需要的變數。
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
public class Orb : MonoBehaviour
{
    public enum OrbsType { Fire, Ice, Shine, Null };////(1)
    public OrbsType type;////(2)
    private Image image;
    void ChangeImage()
    {
        image.sprite = Resources.Load<Sprite>("Image/" + type);////(4)
    }
    void Start()
    {
        image = GetComponent<Image>();
        ChangeImage();////(3)
    }
}
(1)宣告列舉OrbsType,包含所有珠子的屬性以及Null。
(2)宣告珠子的類型。
(3)宣告換圖用的函式,並在珠子初始化的時候執行一次。
(4)透過珠子的type更換圖片。

回到PuzzleSystem腳本,產生盤面中的珠子。
using UnityEngine;
using System.Collections.Generic;
public class PuzzleSystem : MonoBehaviour
{
    public RectTransform BGRect;////(1)
    public int rowCount = 5;
    public int columnCount = 6;
    private Vector2 addPos = new Vector2(120, 120);
    void Start()
    {
        InitGrid();
    }
    void InitGrid()////(2)
    {
        for (int r = 0; r < rowCount; r++)
        {
            for (int c = 0; c < columnCount; c++)
            {
                GameObject orbObj = Instantiate(Resources.Load("Prefabs/Orb")) as GameObject;////(3)
                RectTransform orbRect = orbObj.GetComponent<RectTransform>();
                orbRect.SetParent(BGRect);////(4)
                orbRect.localScale = Vector2.one;////(5)
                orbRect.anchoredPosition = new Vector2(c * addPos.x, r * addPos.y);////(6)
            }
        }
    }
}
(1)新增變數,背景圖的RectTransform、盤面中行與列的珠子數、位移的距離。
(2)新增初始化盤面的函式InitGrid,函式當中使用兩層的迴圈,在盤面中每個位置新增珠子。
(3)產生珠子物件。
(4)設定珠子物件的父物件。
(5)設定比例。
(6)設定位置。

將背景圖物件帶入BGRect,執行結果如下。
可以看到依盤面珠子數量生成的結果,接著要隨機珠子的類型、以及有系統的修改珠子名稱。

回到Orb腳本,修改珠子名稱。
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
public class Orb : MonoBehaviour
{
    .
    .
    .
    public int row;
    public int column;
    .
    .
    .
    void Start()
    {
        .
        .
        .
        transform.name = "orb" + row + column;
        .
        .
        .
    }
}
新增行變數column與列變數row,並在Start中使用行列變數修改transform.name。

回到PuzzleSystem腳本,初始化每個珠子。
using UnityEngine;
using System.Collections.Generic;
public class PuzzleSystem : MonoBehaviour
{
    .
    .
    .
    void Start()
    {
        InitGrid();
    }
    void InitGrid()
    {
        for (int r = 0; r < rowCount; r++)
        {
            for (int c = 0; c < columnCount; c++)
            {
                .
                .
                .
                Orb orb = orbObj.GetComponent<Orb>();////(1)
                orb.row = r;
                orb.column = c;
                OrbCreate(orb);
            }
        }
    }
    void OrbCreate(Orb orb)////(2)
    {
        int typeNum = Random.Range(0, (int)Orb.OrbsType.Null);
        orb.type = (Orb.OrbsType)typeNum;
    }
}

(1)抓取珠子物件下的Orb腳本,修改Orb腳本下的row和column,接著呼叫OrbCreate函式
(2)在OrbCreate函式中,使用Random隨機一個珠子類型編號,並且將該編號帶入珠子的類型中。

到這個階段執行會看到以下結果。
5X6盤面的初始化到這裡這一步就算完成了,接下來要新增調整盤面行列數量的功能。

回到Orb腳本,初始化珠子的大小。
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
public class Orb : MonoBehaviour
{
    .
    .
    .
    public float width = 120;
    public float height = 120;
    .
    .
    .
    void Start()
    {
        .
        .
        .
        GetComponent<RectTransform>().sizeDelta = new Vector2(width, height);
        .
        .
        .
    }
}
新增珠子的寬width與高height,並在Start中修改sizeDelta。

回到PuzzleSystem腳本,做行列數值的調整。
using UnityEngine;
using System.Collections.Generic;
public class PuzzleSystem : MonoBehaviour
{
    public RectTransform BGRect;
    public int rowCount = 5;
    public int columnCount = 6;
    private Vector2 addPos = new Vector2(120, 120);
    void Start()
    {
        InitGrid();
    }
    void InitGrid()
    {

        addPos.y = BGRect.sizeDelta.y / rowCount;
        addPos.x = BGRect.sizeDelta.x / columnCount;

        for (int r = 0; r < rowCount; r++)
        {
            for (int c = 0; c < columnCount; c++)
            {
                .
                .
                .
                orb.height = BGRect.sizeDelta.y / rowCount;
                orb.width = BGRect.sizeDelta.x / columnCount;
            }
        }
    }
}
在進入迴圈前修改位移的xy,進入迴圈之後修改珠子的寬與高,數值如下。
珠子寬 = (背景圖寬/行數)、珠子高 = (背景圖高/列數)

接著只要修改PuzzleSystem的rowCount和columnCount就可以調整盤面,以下是4X5和6X7的盤面。

以上是產生盤面的說明,不過盤面的初始化還沒完成,接著還要做珠子連結判斷、Combo判斷、消除珠子、產生珠子,回到連結判斷步驟直到沒有Combo,才算完成盤面的初始化。
這次就到這裡。

2016/08/06修正:
PuzzleSystem腳本中,有關OrbCreate函式的部分。
using UnityEngine;
using System.Collections.Generic;
public class PuzzleSystem : MonoBehaviour
{
    .
    .
    .
    void Start()
    {
        InitGrid();
        OrbCreate();
    }
    void InitGrid()
    {
        for (int r = 0; r < rowCount; r++)
        {
            for (int c = 0; c < columnCount; c++)
            {
                .
                .
                .
                Orb orb = orbObj.GetComponent<Orb>();////(1)
                orb.row = r;
                orb.column = c;
            }
        }
    }
    void OrbCreate()////(2)
    {
        foreach (Orb orb in orbs)
        {
            if (orb.type == Orb.OrbsType.Null)
            {
                int typeNum = Random.Range(0, (int)Orb.OrbsType.Null);
                orb.type = (Orb.OrbsType)typeNum;
            }
            
        }
}
產生珠子屬性的OrbCreate函式,由於後續還會在其他地方呼叫,所以做了以上修正。

6 則留言:

  1. 請問我的步驟做到要隨機珠子之前那裡
    就整片要出來那裡
    我的珠子會全部移位
    珠子整片的左下角會剛好對到背景的質心
    請問怎麼處理
    謝謝

    回覆刪除
    回覆
    1. 聽起來像是anchoredPosition給數值時有問題。
      方便結個圖嗎?

      刪除
  2. 還有我是新手...
    請問一下
    成是你打下來的每串該怎麼銜接阿?

    回覆刪除
    回覆
    1. 找到相同的函式或迴圈,新增追加的程式碼。
      其實我自己也覺得有點難懂,之後會想個容易看的方式。

      刪除
  3. 你好,我想請問一下,
    就是要怎麼讓遊戲畫面是直的,
    我不管開幾次檔案他都是顯示橫的QQ感謝

    回覆刪除
    回覆
    1. 是輸出apk後是橫的?還是在專案裡就是橫的?
      是專案裡可以看這篇
      https://jerrard-liu.blogspot.tw/2016/07/GameView.html

      輸出的話調整Player setting下的default orientation

      刪除

【自製小遊戲】水平思考猜謎(海龜湯)

遊戲連結 海龜湯的玩法是由出題者提出一個難以理解的事件,參與猜題者可以提出任何問題以試圖縮小範圍並找出事件背後真正的原因。但出題者僅能以「是」、「不是」或「沒有關係」來回答問題。 本遊戲蒐集各種論壇、平台的42個題目,提供給想玩海龜湯卻愁找不到題目的你們。 ...