【Unity3D遊戲開發】基礎知識之Tags和Layers (三二)

Tags和Layers分別表示是Unity引擎裏面的標籤和層,他們都是用來對GameObject進行標識的屬性,Tags常用於單個GameObject,Layers常用於一組的GameObject。添加Tags和Layers的操作如下:

"Edit" -> "Project Settings" -> "Tags and Layers"來打開設置面板。




    tag可以理解爲一類元素的標記,如hero、enemy、apple-tree等。通過設置tag,可以方便地通過GameObject.FindWithTag()來尋找對象。GameObject.FindWithTag()只返回一個對象,要想獲取多個tag爲某值的對象,GameObject.FindGameObjectsWithTag()。

    每個GameObject的Inspector面板最上方都也有個Layer選項,就在Tag旁邊,unity已經有了幾個層,我們新建個層,也叫UI,點擊Add Layer,可以看到從Layer0到Layer7都灰掉了,那是不能用的,從第八個起可以用,Layer和tag還有一個很大的區別就是layer最多只能有32個層。

    在使用過程中,使用Culling Mask、Layer Mask的地方實際指的就是layer。下面我們來看一段使用layer來檢測碰撞的代碼:

Ray ray1 = nguiCamera.camera.ScreenPointToRay(Input.mousePosition);  
RaycastHit hit1; 
LayerMask mask = 1 << LayerMask.NameToLayer("UI"); 
 if (Physics.Raycast(ray1, out hit1, 600, mask.value)) 
{ 
      return;
} 

LayerMask的NameToLayer是通過層的名稱返回該層的索引,如果是8,然後1<<8換算成LayerMask值,再用LayerMask的value就可以了。注意也必須設置collider才能接收碰撞,這裏才能判斷到。LayerMask實際上是一個位碼操作,在Unity中Layers一共有32層,這個是不能增加或者減少的:     1 << LayerMask.NameToLayer("UI") 這一句實際上表示射線查詢只在UI所在這個層級查找是返回的該名字所定義的層的層索引,注意是從0開始。

下面我們來看一個玩家控制的腳本,利用 Physics2D.Linecast檢測物體是否碰撞到地面。

using UnityEngine;
using System.Collections;

public class PlayerControl : MonoBehaviour
{
    [HideInInspector]
    public bool facingRight = true;            // For determining which way the player is currently facing.
    [HideInInspector]
    public bool jump = false;                // Condition for whether the player should jump.


    public float moveForce = 365f;            // Amount of force added to move the player left and right.
    public float maxSpeed = 5f;                // The fastest the player can travel in the x axis.
    public AudioClip[] jumpClips;            // Array of clips for when the player jumps.
    public float jumpForce = 1000f;            // Amount of force added when the player jumps.
    public AudioClip[] taunts;                // Array of clips for when the player taunts.
    public float tauntProbability = 50f;    // Chance of a taunt happening.
    public float tauntDelay = 1f;            // Delay for when the taunt should happen.


    private int tauntIndex;                    // The index of the taunts array indicating the most recent taunt.
    private Transform groundCheck;            // A position marking where to check if the player is grounded.
    private bool grounded = false;            // Whether or not the player is grounded.
    private Animator anim;                    // Reference to the player's animator component.


    void Awake()
    {
        // Setting up references.
        // 在子對象裏面找到groundCheck
        groundCheck = transform.Find("groundCheck");
        // 獲取當前的動畫控制器
        anim = GetComponent<Animator>();
    }

    void Update()
    {
        // 是爲能隨時檢測到groundCheck這個物體,添加一個名叫Ground的Layer,然後把場景中的所有代表地面的物體的Layer設爲Ground
        // 這裏用到了2D射線檢測Physics2D.Linecast()
        // LayerMask實際上是一個位碼操作,在Unity3d中Layers一共有32層,這個是不能增加或者減少的:
        // 1 << LayerMask.NameToLayer("Ground") 這一句實際上表示射線查詢只在Ground所在這個層級查找 是返回的該名字所定義的層的層索引,注意是從0開始
        // 每個GameObject的Inspector面板最上方都也有個Layer選項,就在Tag旁邊,unity3d已經有了幾個層,我們新建個層,也叫UI,點擊Add Layer,可以看到從Layer0到Layer7都灰掉了,那是不能用的,從第八個起可以用,所以在第八個建個UI的層。
        // 一般情況下我們只用前兩個參數,distance表示射線距離,默認是無限遠,重點是最後一個參數layerMask,專門處理layer過濾的,是個整型,怎麼用呢,是靠layer的二進制位來操作的
        // LayerMask的NameToLayer是通過層的名稱返回該層的索引,這裏是8,然後1<<8換算成LayerMask值,再用LayerMask的value就可以了。
        // 注意也必須設置collider才能接收碰撞,這裏才能判斷到。
        grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));  

        // If the jump button is pressed and the player is grounded then the player should jump.
        // 如果點擊了跳的按鍵,並且已經着陸,那麼就可以跳起來
        if(Input.GetButtonDown("Jump") && grounded)
            jump = true;
    }

    // 因爲主角遊戲對象要使用到剛體力,所以一定要寫在FixedUpdate裏面,不能放在Update上
    void FixedUpdate ()
    {
        // Cache the horizontal input.
        // 換取水平方向的移動距離
        float h = Input.GetAxis("Horizontal");

        // The Speed animator parameter is set to the absolute value of the horizontal input.
        // 設置動畫的速度變量
        anim.SetFloat("Speed", Mathf.Abs(h));

        // 給物體添加一個水平的力,讓它移動的時候會產生慣性的效果
        // If the player is changing direction (h has a different sign to velocity.x) or hasn't reached maxSpeed yet...
        // 如果速度小於最大的速度 
        if(h * rigidbody2D.velocity.x < maxSpeed)
            // ... add a force to the player.
            rigidbody2D.AddForce(Vector2.right * h * moveForce);

        // If the player's horizontal velocity is greater than the maxSpeed...
        if(Mathf.Abs(rigidbody2D.velocity.x) > maxSpeed)
            // ... set the player's velocity to the maxSpeed in the x axis.
            rigidbody2D.velocity = new Vector2(Mathf.Sign(rigidbody2D.velocity.x) * maxSpeed, rigidbody2D.velocity.y);

        // 轉身
        // If the input is moving the player right and the player is facing left...
        if(h > 0 && !facingRight)
            // ... flip the player.
            Flip();
        // Otherwise if the input is moving the player left and the player is facing right...
        else if(h < 0 && facingRight)
            // ... flip the player.
            Flip();

        // If the player should jump...
        if(jump)
        {
            // Set the Jump animator trigger parameter.
            // 觸發跳的動畫
            anim.SetTrigger("Jump");

            // Play a random jump audio clip.
            int i = Random.Range(0, jumpClips.Length);
            AudioSource.PlayClipAtPoint(jumpClips[i], transform.position);

            // Add a vertical force to the player.
            // 添加一個垂直的力
            rigidbody2D.AddForce(new Vector2(0f, jumpForce));

            // Make sure the player can't jump again until the jump conditions from Update are satisfied.
            jump = false;
        }
    }
    
    // 轉身
    void Flip ()
    {
        // Switch the way the player is labelled as facing.
        facingRight = !facingRight;

        // Multiply the player's x local scale by -1.
        Vector3 theScale = transform.localScale;
        theScale.x *= -1;
        transform.localScale = theScale;
    }


    public IEnumerator Taunt()
    {
        // Check the random chance of taunting.
        float tauntChance = Random.Range(0f, 100f);
        if(tauntChance > tauntProbability)
        {
            // Wait for tauntDelay number of seconds.
            yield return new WaitForSeconds(tauntDelay);

            // If there is no clip currently playing.
            if(!audio.isPlaying)
            {
                // Choose a random, but different taunt.
                tauntIndex = TauntRandom();

                // Play the new taunt.
                audio.clip = taunts[tauntIndex];
                audio.Play();
            }
        }
    }


    int TauntRandom()
    {
        // Choose a random index of the taunts array.
        int i = Random.Range(0, taunts.Length);

        // If it's the same as the previous taunt...
        if(i == tauntIndex)
            // ... try another random taunt.
            return TauntRandom();
        else
            // Otherwise return this index.
            return i;
    }
}


原文鏈接:http://www.cnblogs.com/linzheng/p/3991375.html

發佈了106 篇原創文章 · 獲贊 24 · 訪問量 132萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章