简单的点击交互

unity为我们提供了许多人机交互的方式,包括鼠标、键盘、手柄等等,这些具体的设置我们可以通过Edit->ProjectSettings->Input中查看
简单的点击交互_第1张图片

这里我讲一下鼠标左键的点击,我们点开Fire1
简单的点击交互_第2张图片
这里Alt Positive Button显示的是mouse 0,表示鼠标左键点击就会有该响应,而且是积极相应,这些可以自己修改

下面我做一个小游戏:

  • 用 Plane 或其他物体做地面, tag 为“Finish”
  • 点击地面后,出现一个圆形攻击标记,两秒后自动消失。注意:该攻击标记不能挡住点击。

首先我们做一个Terrain,上次我们说过美化的方法,所以我做出了这样子的
简单的点击交互_第3张图片
进入Inspector,将Tag改为Finish
简单的点击交互_第4张图片
然后我们制作一个圆形攻击标志,在Assert中创建文件夹Resources->Prefabs,然后创建一个圆柱,将其高度设为0.001(设为0会变成一个黑色圆),拖入Prefabs,然后在当前目录创建Material,给它添加喜欢的颜色,然后再拖入我们的预设,圆形标志就做好了
简单的点击交互_第5张图片

现在我们考虑如何编写脚本,这里我采用了工厂单例模式。意思很简单,就是有一个脚本在鼠标点击后告诉一个工厂“我需要一个圆形标志,放在哪里”,工厂接到小心以后就先看看自己库存还有没有,有就直接拿给它,否则就创建一个拿给它。因为unity创建一个游戏对象、销毁一个游戏对象会占很大的资源,所以有什么办法可以少生产,少销毁甚至不销毁呢?很简单,把用完的拿回来。那这些库存放哪呢,也在游戏场景中,只是并不在摄像机的视角范围内。

这样我们思路就很清晰了,一个人机交互,并给工厂下达指令的脚本、一个生产、回收的工厂

Factory

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

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

    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(Resources.Load("Prefabs/Cylinder"), Vector3.zero, Quaternion.identity);
        } else
        {
            t = free[0];
            free.Remove(t);
        }
        used.Add(t);
        t.transform.position = position;
        t.AddComponent();
    }
}

为什么要用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();
            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){}的意思就是如果这条射线发生了碰撞就执行以下事件:告诉工厂我要在点击的位置生成一个圆形标志

这样我们就完成了这样一个有(无)趣(聊)的小游戏简单的点击交互_第6张图片

你可能感兴趣的:(3D游戏开发设计)