zoukankan      html  css  js  c++  java
  • 【Unity3D】点击交互——简单工厂

    实现一个很简单的点击小游戏,学习交互相关的内容,在不实时创建销毁的情况下,使用简单工厂创建、管理、回收、复用标记。

    游戏概述:点击出现标记,两秒内自动消失

    游戏展示:


    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);
            }
        }
    }
  • 相关阅读:
    C++之容器
    C++之复制控制
    TCP的3次握手/4次握手
    linux编程之多线程编程
    linux编程之信号
    linux编程之共享内存
    MySQL数据库优化
    MySQL存储引擎InnoDB与Myisam
    Redis--持久化
    Redis 请求应答模式和往返延时 Pipelining
  • 原文地址:https://www.cnblogs.com/xieyuanzhen-Feather/p/6599881.html
Copyright © 2011-2022 走看看