Unity3D学习1——鼠标点击效果显示

来源:互联网 发布:bim用什么软件 编辑:程序博客网 时间:2024/05/22 12:05

在很多游戏当中,像梦幻西游等等游戏都会采用鼠标控制人物行走的方式。今天我们就来实现鼠标点击产生行走的标记的这么一个效果。

首先我们上设计的梗概。

实现点击效果。

1.首先点击需要地面, 并把地面的tag 设为“Finish”

2.点击地面后,出现一个圆形攻击标记,两秒后自动消失。注意:该攻击标记不能挡住点击。

3.使用一个简单工厂创建、管理这些的标记,并自动收回这些标记(注意,这些对象创建后,放在列表内,不必释放)。

先来一个程序的架构图

一般小游戏可以不需要GameMaster和Storage这两个部分,只需要用简单工厂模式就很容易完成这个功能了。不过对于Destory和instantiate来说比较耗费资源去计算,如果频繁的去生成某个物件如子弹之类的,并且销毁的话,会耗费很多不必要的资源,所以我们采用一个Master来管理这些物体,并且在不用的时候可以回收而不是销毁他们。

具体的可以看下面这个连接。

点击打开链接


制作地面这些我就不多说了。我们需要一个GameController去处理我们的点击事件。

using UnityEngine;using System.Collections;using Com.Mygame;public class GameController : MonoBehaviour {    private GameObject cam;    private ActionManager myFactory;    void Start()    {        cam = GameObject.FindWithTag("MainCamera");        myFactory = ActionManager.getInstance();    }    void Update()    {        if (Input.GetMouseButtonDown(0))        {            Vector3 mp = Input.mousePosition;            Ray ray = cam.GetComponent<Camera>().ScreenPointToRay(mp);            RaycastHit hit;            if (Physics.Raycast(ray, out hit))            {                if (hit.transform.gameObject.tag == "Finish")                {                    myFactory.placeAttackMark(hit.point);                }            }        }    }}

其实这里的cam获取的游戏对象我们最好不要用find去寻找,这样也会相对损耗资源,比较好的做法是把他声明称pubic的然后在外面拖动你想要的camera对象进去。

这里主要就是利用射线然后判断射线撞击的物体的collider后得到这个物体是不是我们想要的那个物体。

可以看到。在这个GameController里面,我们需要用到工厂类里面的placeAttackMark这个方法。

工厂类如下:

using UnityEngine;using System.Collections;using Com.Action;using Com.Storage;namespace Com.Mygame{    public class ActionManager : System.Object    {        private static ActionManager _instance;        public static ActionManager getInstance()        {            if (_instance == null)            {                _instance = new ActionManager();            }            return _instance;        }        public void placeAttackMark(Vector3 point)        {            GameObject master = GameObject.Find("GameMaster");            GameObject mark = master.GetComponent<GameMaster>().AskForMark();            showSymbol ac = mark.AddComponent<showSymbol>();            ac.setting(point);        }    }}
这里我们采用了简单工厂模式,就可以方便的管理我们的放置标记这个动作了。

看到我们的placeAttackMark这个方法。在这个方法里面,我们首先要向GameMaster申请拿到我们放置的物体,然后呢,我们要对拿到的这个物体进行处理——给它增加动作,通过给它增加Actions里面的类来增加他的动作。

GameMaster的代码:

using UnityEngine;using System.Collections;using Com.Storage;public class GameMaster : MonoBehaviour{    public GameObject Mark;    private Vector3 UnusedPlace = new Vector3(1000f, 1000f, 1000f);    private Storge storage = Storge.getInstance();    void Start()    {        for (int i = 0; i < 3; i++)        {            GameObject newMark = GameObject.Instantiate(Mark, UnusedPlace, Quaternion.identity) as GameObject;            storage.insertUnuseSymbol(newMark);        }    }    public GameObject AskForMark()    {        if (storage.unuseSymbolEmpty())        {            GameObject newMark = GameObject.Instantiate(Mark, UnusedPlace, Quaternion.identity) as GameObject;            storage.insertUnuseSymbol(newMark);        }        GameObject returnOne = storage.getUnuseSymbol()[0];        storage.insertUsingSymbol(returnOne);        storage.getUnuseSymbol().RemoveAt(0);        //Debug.Log(storage.getUsingSymbol().Count);        return returnOne;    }    public void MarkComplete(GameObject obj)    {        storage.getUsingSymbol().Remove(obj);        storage.insertUnuseSymbol(obj);        obj.transform.position = UnusedPlace;    }}
在GameMaster里,我们需要对我们的仓库类Storage进行操作,Storage类里面,会设定一个正在使用的List,我们这里叫List1好了和一个没有被使用的List,叫List2好了。他们里面装的都是GameObject类,用来存储我们将要用到的标记。这里的理念是:如果List2是空的的话。我们就要实例化一个新的物体然后把他放进List2里面,如果不是空的的话,就把其中的一个拿出来,放进List1里面,并且把这个物体放在我们要放置的地方。

我们在开头就创建好了三个要用的物体,不过其实不创建也没什么关系了。

这里面最后还有一个MarkComplete的方法,我们先放在这里。

然后看我们的Storage仓库类:

using UnityEngine;using System.Collections;using System.Collections.Generic;namespace Com.Storage{    public class Storge : System.Object    {        private List<GameObject> using_Symbol = new List<GameObject>();        private List<GameObject> unuse_Symbol = new List<GameObject>();        private static Storge _instance;        public static Storge getInstance()        {            if (_instance == null)            {                _instance = new Storge();            }            return _instance;        }        public List<GameObject> getUsingSymbol()        {            return using_Symbol;        }        public bool usingSymbolEmpty()        {            return using_Symbol.Count == 0;        }        public List<GameObject> getUnuseSymbol()        {            return unuse_Symbol;        }        public bool unuseSymbolEmpty()        {            return unuse_Symbol.Count == 0;        }        public void insertUsingSymbol(GameObject obj)        {            using_Symbol.Add(obj);        }        public void insertUnuseSymbol(GameObject obj)        {            unuse_Symbol.Add(obj);        }    }}
提供了一系列的方法,给我们的GameMaster去调用,方便我们改变里面的数据。

其实到了这里我们已经完善的差不多了。差不多已经可以把东西都放出来了。不过问题是这些物体放出来了之后就放出来了,不会消失。为此,我们就要为我们放出来的物体增加动作了,让他们在放出来之后的一段时间之后就自动消失。

Actions类如下:

using UnityEngine;using System.Collections;using Com.Storage;namespace Com.Action{    public class U3dAction : MonoBehaviour    {        public void Free()        {            Destroy(this);        }    }    public class U3dActionAuto : U3dAction{}    public class showSymbol : U3dActionAuto    {        private Vector3 pos;        private float time;        public void setting(Vector3 p)        {            pos = p;            time = Time.time;            transform.position = pos;        }        void Update()        {            if (Time.time - time > 2.0f)            {                GameObject master = GameObject.Find("GameMaster");                master.GetComponent<GameMaster>().MarkComplete(this.gameObject);                Free();            }        }    }}
我们设置了放置出来的物体在2秒钟之后就自动删除。这里就要提到我们之前的MarkComplete方法了,在这里,我们在两秒钟之后就会调用到我们的MarkCompete方法,就像析构一样,把物体放回List2里面,把LIst1里面的东西删掉,并且把放置的物体放在我们看不到的地方。

这样一来。我们就大功告成了!可以点击一下然后生成一个东西了!


最后,值得一说的是,我们放置的那个物体不能存在collider组件,不然的话我们放置的物体就不能重叠起来了,因为物体的collider会挡住我们的射线,就拿不到我们地面这个物体了。


最后的最后,应该说的是,要实现这个效果还是很容易的,主要就是要好好的把我们每个部件的角色分工好,这样一来,在开发更大的项目的时候才会更加容易并且顺利而且明确还有不容易出现问题,即使出现问题也容易解决的这么一些好处。





1 0
原创粉丝点击