簡單的點擊交互

unity爲我們提供了許多人機交互的方式,包括鼠標、鍵盤、手柄等等,這些具體的設置我們可以通過Edit->ProjectSettings->Input中查看
這裏寫圖片描述

這裏我講一下鼠標左鍵的點擊,我們點開Fire1
這裏寫圖片描述
這裏Alt Positive Button顯示的是mouse 0,表示鼠標左鍵點擊就會有該響應,而且是積極相應,這些可以自己修改

下面我做一個小遊戲:

  • 用 Plane 或其他物體做地面, tag 爲“Finish”
  • 點擊地面後,出現一個圓形攻擊標記,兩秒後自動消失。注意:該攻擊標記不能擋住點擊。

首先我們做一個Terrain,上次我們說過美化的方法,所以我做出了這樣子的
這裏寫圖片描述
進入Inspector,將Tag改爲Finish
這裏寫圖片描述
然後我們製作一個圓形攻擊標誌,在Assert中創建文件夾Resources->Prefabs,然後創建一個圓柱,將其高度設爲0.001(設爲0會變成一個黑色圓),拖入Prefabs,然後在當前目錄創建Material,給它添加喜歡的顏色,然後再拖入我們的預設,圓形標誌就做好了
這裏寫圖片描述

現在我們考慮如何編寫腳本,這裏我採用了工廠單例模式。意思很簡單,就是有一個腳本在鼠標點擊後告訴一個工廠“我需要一個圓形標誌,放在哪裏”,工廠接到小心以後就先看看自己庫存還有沒有,有就直接拿給它,否則就創建一個拿給它。因爲unity創建一個遊戲對象、銷燬一個遊戲對象會佔很大的資源,所以有什麼辦法可以少生產,少銷燬甚至不銷燬呢?很簡單,把用完的拿回來。那這些庫存放哪呢,也在遊戲場景中,只是並不在攝像機的視角範圍內。

這樣我們思路就很清晰了,一個人機交互,並給工廠下達指令的腳本、一個生產、回收的工廠

Factory

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Factory : MonoBehaviour {
    private static Factory instance;
    public static List<GameObject> free = new List<GameObject>();
    public static List<GameObject> used = new List<GameObject>();

    public static Factory GetInstance()
    {
        if (instance == null)
        {
            instance = new Factory();
        }
        return instance;
    }


    public void placeAttackMark(Vector3 position)
    {
        GameObject t;
        if (free.Count == 0) // 空餘組中沒有多餘的,此時需要創建
        {
            t = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Cylinder"), Vector3.zero, Quaternion.identity);
        } else
        {
            t = free[0];
            free.Remove(t);
        }
        used.Add(t);
        t.transform.position = position;
        t.AddComponent<disappear>();
    }
}

爲什麼要用static呢,原因很簡單,單例模式,整個遊戲只需要一個工廠。用了兩個List,一個用於表示庫存,一個用於記錄用過的,以便可以回收。placeAttackMark是作爲交互腳本調用的,首先判斷是否有庫存,有的話把這個調到指定位置,並移到已用記錄中,否則直接創造一個。由於要求兩秒以後自動消失,我們爲每個拿出去的產品添加一個計時器(組件)disappear。

disappear

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class action : Factory { }

    public class disappear : action {
    private float time = 2;

    void Update()
    {
        time -= Time.deltaTime;
        if (time <= 0)
        {
            transform.position = Vector3.zero;
            used.Remove(gameObject);
            free.Add(gameObject);
            Destroy(this);
        }
    }
}

當時間到了以後,把這個標記移到我們看不見的地方,再從已用list中刪除,同時把它重新加入庫存中,完成回收,值得一提的是,要刪掉這個組件,不然它會每一幀都運行。

Shot

首先我說一下是如何判斷鼠標是否點擊到了物體,簡單來說,就是以攝像機爲原點,朝鼠標點擊的位置發出一條射線,如果撞擊到了物體就是點擊到了這個物體的意思。所以Shot中我們要添加一個攝像機成員,還要一個工廠

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Shot : MonoBehaviour {
    private Factory MyFactory;
    public GameObject Cam;
    // Use this for initialization
    void Start ()
    {
        MyFactory = Factory.GetInstance(); 
    }

    // Update is called once per frame
    void Update () {
        if (Input.GetButtonDown("Fire1"))
        {
            Vector3 mp = Input.mousePosition;

            Camera ca = Cam.GetComponent<Camera>();
            Ray ray = ca.ScreenPointToRay(mp);

            RaycastHit hit;

            if (Physics.Raycast(ray, out hit))
            {
                if (hit.collider.gameObject.tag.Contains("Finish"))
                {
                    print(mp);

                    MyFactory.placeAttackMark(hit.point);
                }
            }
        }
    }
}

Raycasr(ray, out hit){}的意思就是如果這條射線發生了碰撞就執行以下事件:告訴工廠我要在點擊的位置生成一個圓形標誌

這樣我們就完成了這樣一個有(無)趣(聊)的小遊戲這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章