实现一个很简单的点击小游戏,学习交互相关的内容,在不实时创建销毁的情况下,使用简单工厂创建、管理、回收、复用标记。
游戏概述:点击出现标记,两秒内自动消失
游戏展示:
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); } } }