【跟我一起学Unity3D】做一个2D的90坦克大战之地图编辑器

从10月20号到现在,Unity3D也学了10天了,对于Unity3D也有了一个大致的了解,有必要做一个小游戏来检测一下自己的学习成果了。经过两天的努力,终于总算是做出来了一个可以玩的坦克大战了。首先讲讲我的设计目标:

1.地图编辑器
2.道具系统
3.简单AI系统
4.计分器

其中,最重要的就是地图编辑器了,其次到AI系统,其他几个都挺简单的。

------------------------------------------------------------------------------------------------------------------------------------------

地图编辑器

我的想法是在编辑器中编辑好地图后,直接打开游戏就可以玩。这样的话,就需要一个文件来存储这些地图元素。鉴于xml在C#上支持非常好,简单易用,就选它了。

然后我们规定一下地图的格式,首先地图是由一个一个item组成的,原版的item有普通的墙,坚固的墙,水和草丛(德玛西亚)。为了方便读取,就用一个名字来规定他们,其次,由于我们是2D的场景,所以存入的坐标是x与y。最后得到的数据存储格式如下:

 <item>
      <name>gras</name>
      <position_x>-1.2</position_x>
      <position_y>-3</position_y>
    </item>

整个文件大概是下面这样的结构:

<data>
  <items>
    <item>
      <name>gras</name>
      <position_x>-1.2</position_x>
      <position_y>-3</position_y>
    </item>
  </items>
</data>

对应的文件存入的函数为:

    bool SaveInXml()
    {
        if (File.Exists(m_sXmlPath))
        {
            File.Delete(m_sXmlPath);
        }
        XmlDocument xmlDoc = new XmlDocument();
        XmlElement data = xmlDoc.CreateElement("data");
        xmlDoc.AppendChild(data);
        //地图数据
        XmlElement xml_items = xmlDoc.CreateElement("items");
        data.AppendChild(xml_items);
        foreach (GameObject item in m_Items)
        {
            Debug.Log("要保存的数据:" + item.name + "位置:" + item.transform.position.x + "," + item.transform.position.y);

            //save in xml file
            XmlElement xml_item = xmlDoc.CreateElement("item");
            xml_items.AppendChild(xml_item);
            XmlElement name = xmlDoc.CreateElement("name");
            name.InnerText = item.name;
            xml_item.AppendChild(name);

            XmlElement position_x = xmlDoc.CreateElement("position_x");
            position_x.InnerText = item.transform.position.x.ToString();
            xml_item.AppendChild(position_x);

            XmlElement position_y = xmlDoc.CreateElement("position_y");
            position_y.InnerText = item.transform.position.y.ToString();
            xml_item.AppendChild(position_y);
        }
        xmlDoc.Save(m_sXmlPath);
        Debug.Log("创建XML完毕");
        m_Items.Clear();
        return true;
    }

然后就是对应的读取函数了(读取完直接实例化显示的):

    void ReadMap(XmlNode xml_items)
    {
        XmlNodeList items = xml_items.SelectNodes("item");
        foreach (XmlNode current_node in items)
        {
            XmlNode current_name = current_node.SelectSingleNode("name");
            XmlNode position_x = current_node.SelectSingleNode("position_x");
            XmlNode position_y = current_node.SelectSingleNode("position_y");

            Vector3 psition = new Vector3(float.Parse(position_x.InnerText), float.Parse(position_y.InnerText), -1);

            if (current_name.InnerText == "wall")
            {
                m_readItem = Instantiate(m_ItemWall, psition, Quaternion.identity) as GameObject;
            }

            else if (current_name.InnerText == "gras")
            {
                m_readItem = Instantiate(m_ItemGras, psition, Quaternion.identity) as GameObject;
            }

            else if (current_name.InnerText == "steel")
            {
                m_readItem = Instantiate(m_ItemSteel, psition, Quaternion.identity) as GameObject;
            }

            else if (current_name.InnerText == "water")
            {
                m_readItem = Instantiate(m_ItemWater, psition, Quaternion.identity) as GameObject;
            }

            else continue;

            m_readItem.name = current_name.InnerText;

            Debug.Log("要读取的数据:" + m_readItem.name + "位置:" + m_readItem.transform.position.x + "," + m_readItem.transform.position.y);

            m_Items.Add(m_readItem);
        }
    }

这样,就完成了一个基本的地图编辑器的核心部分了,剩下的就是拖拽控件了。

关于拖拽控件,设计的想法是,地图的item在右边,然后点击item会复制一个点击到的item,然后可以拖拽这个复制出来的item到地图上,下面是实现代码:

    void Update()
    {
        //检测鼠标左键的拾取  
        if (Input.GetMouseButtonDown(0))
        {
            //鼠标的屏幕坐标空间位置转射线  
            m_ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            m_rayhit = Physics2D.GetRayIntersection(m_ray);
            //射线检测,相关检测信息保存到RaycastHit 结构中  
            if (m_rayhit)
            {
                //打印射线碰撞到的对象的名称  
                Debug.Log(m_rayhit.collider.gameObject.name);
                if (m_rayhit.collider.gameObject.name == "walls" ||
                    m_rayhit.collider.gameObject.name == "grass" ||
                    m_rayhit.collider.gameObject.name == "steels" ||
                    m_rayhit.collider.gameObject.name == "waters")
                {
                    m_clickItem = Instantiate(m_rayhit.collider.gameObject, m_rayhit.collider.transform.position, Quaternion.identity) as GameObject;
                    m_clickItem.name = m_rayhit.collider.gameObject.name.Substring(0, m_rayhit.collider.gameObject.name.Length - 1);
                    //m_clickItem.tag = m_clickItem.name; //ERROR: not define tag in editor
					m_Items.Add(m_clickItem);
                }
                else if (m_rayhit.collider.gameObject.name == "wall" ||
                    m_rayhit.collider.gameObject.name == "gras" ||
                    m_rayhit.collider.gameObject.name == "steel" ||
                    m_rayhit.collider.gameObject.name == "water")
                {
                    m_clickItem = m_rayhit.collider.gameObject;
                }
                else
                {
                    m_clickItem = null;
                }
            }
            else
            {
                m_clickItem = null;
            }
        }
        if (Input.GetMouseButton(0))
        {
            if (m_clickItem != null)
            {
                m_clickItem.transform.position = SetPointInMap(new Vector3(camera.ScreenToWorldPoint(Input.mousePosition).x, camera.ScreenToWorldPoint(Input.mousePosition).y, -1));
            }
        }
        if (Input.GetMouseButtonUp(0))
        {
            if (m_clickItem != null)
            {
                Vector3 cur_point = SetPointInMap(new Vector3(camera.ScreenToWorldPoint(Input.mousePosition).x, camera.ScreenToWorldPoint(Input.mousePosition).y, -1));
                if (m_Map.collider2D.OverlapPoint(cur_point))
                {
                    m_clickItem.transform.position = cur_point;
                }
                else	//在地图外就销毁掉
                {
                    Destroy(m_clickItem);
                }
            }
        }
    }


 

这样,就完成了一个简单的地图编辑器的基本功能了。


项目源码:【跟我一起学Unity3D】做一个2D的90坦克大战之各种各样的墙<<附上项目源码>>

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值