實現一個很簡單的點擊小游戲,學習交互相關的內容,在不實時創建銷毀的情況下,使用簡單工廠創建、管理、回收、復用標記。
游戲概述:點擊出現標記,兩秒內自動消失
游戲展示:
1.1實現點擊效果。
1.1.1用 Plane 或其他物體做地面, tag 為“Finish”
先創建Plane,並選擇tag為Finish。
1.1.2點擊地面后,出現一個圓形攻擊標記,兩秒后自動消失。注意:該攻擊標記不能擋住點擊。(Primitive Objects / Cylinder)
1.點擊對象出現事件,之前設置地板的tag為Finish,可以利用tag找到對象,對應編寫事件。
if (hit.collider.gameObject.tag.Contains ("Finish"))
2.圓形攻擊標記,按提示創建Cylinder作為攻擊標記。
GameObject cylinder_1 = GameObject.CreatePrimitive (PrimitiveType.Cylinder);
3.剛開始不知道不能擋住點擊該如何完成,這一點是在整體實現之后才查到相關資料解決的,加上下面一句代碼,把圓柱形標記設為不啟用,這樣就不會妨礙在同一地方繼續點擊生成或出現圓柱形標記。
cylinder_1.GetComponent<Collider> ().enabled = false; // 不影響再次點擊
4.整理代碼,如下。
void Update() { Vector3 mp = Input.mousePosition; cm = Camera.main; Ray ray = cm.ScreenPointToRay (mp); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { // 如果點擊到標簽為Tag的對象 if (hit.collider.gameObject.tag.Contains ("Finish")) { Vector3 finishposition = hit.point + new Vector3(0f,0.8f,0f); GameObject cylinder_1 = GameObject.CreatePrimitive (PrimitiveType.Cylinder); cylinder_1.GetComponent<Collider> ().enabled = false; cylinder_1.transform.position = hit.point+ new Vector3(0f,0.8f,0f); } } }
現在可以點擊創建圓柱形標記,但是還不會消失。要求需要在兩秒內自動消失,考慮增加一個類專門管理消失。(消失不是destroy,如下面所提示的,對象創建之后,放在列表內,不必釋放,因為釋放再重建耗費太多資源。)做到這一步,需要先使用簡單工廠,先放上代碼,后續在下一點再講述。
專門管理延時的類:
1.1.3請使用一個簡單工廠創建、管理這些的標記,並自動收回這些標記(注意,這些對象創建后,放在列表內,不必釋放)。
為適應下面紅色字體要求,修改類名和相關函數名。
用戶僅需申請使用即可 GameObject myFactory.placeAttackMark(Vector3 position)
myFactory為工廠類,其中的placeAttackMark(Vector3 position)函數為具體實現。
建立myFactory.cs,建立placeAttackMark函數和對象列表(public List<GameObject> free = new List<GameObject>();),將之前Update里面的內容放到placeAttackMark中。考慮到需要回收對象(修改位置或者隱藏,讓用戶無法看到),在創建新的標記時需要判斷對象列表里還有沒有可用的,有則復用不創建。
修改之前Update里面的內容,如下所示:重要代碼后寫有注釋。
public void placeAttackMark(Vector3 target) { cm = Camera.main; Ray ray = cm.ScreenPointToRay (target); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { // 如果點擊到標簽為Tag的對象 GameObject cylinder_1; if (hit.collider.gameObject.tag.Contains ("Finish")) { Vector3 finishposition = hit.point + new Vector3(0f,0.8f,0f); if (free.Count == 0) { // 如果未使用的圓柱形標記為空,則創建 cylinder_1 = GameObject.CreatePrimitive (PrimitiveType.Cylinder); cylinder_1.GetComponent<Collider> ().enabled = false; // 不影響再次點擊 cylinder_1.transform.position = hit.point+ new Vector3(0f,0.8f,0f); } else { // 還有標記空閑,復用標記 cylinder_1 = free[0]; free.RemoveAt(0); // 用了之后移除 cylinder_1.transform.position = hit.point + new Vector3(0f,0.8f,0f); } // 兩秒后自動消失 waitToRecovery wt = cylinder_1.AddComponent<waitToRecovery>(); wt.delay2min (cylinder_1, free); } } }
最后,在用戶端直接訪問 myFactory.placeAttackMark(Vector3 position)即可。
在這里,如之前一樣,在myFactory里面實現了GetInstance方法。
using System.Collections; using System.Collections.Generic; using UnityEngine; using Com.mygame; public class BaseCode : MonoBehaviour { private Camera cm; private GameObject temp; // Use this for initialization void Start () { cm = Camera.main; } // Update is called once per frame void Update () { if (Input.GetMouseButtonDown (0)) { Vector3 mp = Input.mousePosition; myFactory.GetInstance ().placeAttackMark (mp); } } }