从10月20号到现在,Unity3D也学了10天了,对于Unity3D也有了一个大致的了解,有必要做一个小游戏来检测一下自己的学习成果了。经过两天的努力,终于总算是做出来了一个可以玩的坦克大战了。首先讲讲我的设计目标:
1.地图编辑器
2.道具系统
3.简单AI系统
4.计分器
------------------------------------------------------------------------------------------------------------------------------------------
地图编辑器
我的想法是在编辑器中编辑好地图后,直接打开游戏就可以玩。这样的话,就需要一个文件来存储这些地图元素。鉴于xml在C#上支持非常好,简单易用,就选它了。
然后我们规定一下地图的格式,首先地图是由一个一个item组成的,原版的item有普通的墙,坚固的墙,水和草丛(德玛西亚)。为了方便读取,就用一个名字来规定他们,其次,由于我们是2D的场景,所以存入的坐标是x与y。最后得到的数据存储格式如下:
-
gras
-1.2
-3
-
gras
-1.2
-3
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坦克大战之各种各样的墙<<附上项目源码>>