编辑器功能的初步实现就是要达到一个基本的使用循环,编辑——运行——编辑——运行…
编辑功能就是拖拽加上一些摆放的功能,能够保存在一个文本文件里。
运行功能就是将文本文件里的内容进行解析,然后运行。

鼠标高亮

编辑功能拆分实现如下

  • 摆放关卡对象
    • 绘制地形或关卡对象
    • 重复检测
    • 橡皮擦
    • 拖拽绘制
  • 保存生成关卡文件
    • 关卡信息搜集、序列化

我们在v0.0.5版本中只做一件事情,就是绘制地形实现。

首先新建一个场景命名为LevelEditor,然后打开这个场景,在其中新建一个空对象命名为LevelEditor,将其Transform重置一下。

然后新建一个2D Object——Sprite——Square,将其命名为EmptyHighlight,代表着高亮块,用来提示鼠标位置,将sprite的透明度设为128

然后在Scripts——ViewController——LevelEditor内部新建LevelEditor脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using UnityEngine;

namespace ShootingEditor2D
{
public class LevelEditor : MonoBehaviour
{
public SpriteRenderer EmptyHighlight;


void Update()
{
var mousePosition = Input.mousePosition;
var mouseWorldPos = Camera.main.ScreenToWorldPoint(mousePosition);
mouseWorldPos.z = 0;
mouseWorldPos.x = Mathf.Floor(mouseWorldPos.x + 0.5f);//+0.5f表示四舍五入
mouseWorldPos.y = Mathf.Floor(mouseWorldPos.y + 0.5f);
EmptyHighlight.transform.position = mouseWorldPos;
}
}
}

将此脚本挂载在LevelEditor上,并将EmptyHighlight拖拽进来。这样一个跟随鼠标的高亮块就做好了

Mathf.Floor的功能是返回小于或等于f的最大浮点数。也就是说Mathf.Floor(10.7)返回的是10f,直接加0.5f就能实现四舍五入了

与Floor相对,也有Mathf.Ceil函数,并且也提供Mathf.FloorToIntMathf.CeilToInt函数,顾名思义返回的是整数

单击绘制地块

继续修改LevelEditor脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using UnityEngine;

namespace ShootingEditor2D
{
public class LevelEditor : MonoBehaviour
{
public SpriteRenderer EmptyHighlight;


void Update()
{
var mousePosition = Input.mousePosition;
var mouseWorldPos = Camera.main.ScreenToWorldPoint(mousePosition);
mouseWorldPos.z = 0;
mouseWorldPos.x = Mathf.Floor(mouseWorldPos.x + 0.5f);
mouseWorldPos.y = Mathf.Floor(mouseWorldPos.y + 0.5f);
EmptyHighlight.transform.position = mouseWorldPos;

//+++
if (Input.GetMouseButtonDown(0))
{
var groundPrefab = Resources.Load<GameObject>("Ground");
var groundGameObj = Instantiate(groundPrefab,transform);//作为LevelEditor的子对象
groundGameObj.transform.position = mouseWorldPos;
groundGameObj.name = "Ground";
}
//+++
}
}
}

避免重复绘制

继续修改LevelEditor脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using UnityEngine;

namespace ShootingEditor2D
{
public class LevelEditor : MonoBehaviour
{
public SpriteRenderer EmptyHighlight;

private bool mCanDraw;

void Update()
{
var mousePosition = Input.mousePosition;
var mouseWorldPos = Camera.main.ScreenToWorldPoint(mousePosition);
mouseWorldPos.z = 0;
mouseWorldPos.x = Mathf.Floor(mouseWorldPos.x + 0.5f);
mouseWorldPos.y = Mathf.Floor(mouseWorldPos.y + 0.5f);

if (Mathf.Abs(EmptyHighlight.transform.position.x - mouseWorldPos.x) < 0.1f &&
Mathf.Abs(EmptyHighlight.transform.position.y - mouseWorldPos.y) < 0.1f)
{
//这句判断的意思是如果当前鼠标没有移动,高亮块先不用变色
//用Mathf.Abs比较int和Float的差值,来确定它们是否相等
}
else
{
EmptyHighlight.transform.position = mouseWorldPos - new Vector3(0,0,1);//保证高亮块在物品前面
Ray ray = Camera.main.ScreenPointToRay(mousePosition);

RaycastHit2D hit = Physics2D.Raycast(ray.origin, Vector2.zero,20);//用Raycast来确定能否绘制

if (hit.collider)
{
EmptyHighlight.color = new Color(1, 0, 0,0.5f);
mCanDraw = false;
}
else
{
EmptyHighlight.color = new Color(1, 1, 1, 0.5f);
mCanDraw = true;
}
}
if (Input.GetMouseButtonDown(0) && mCanDraw)//使用mCanDraw变量避免重复绘制
{
var groundPrefab = Resources.Load<GameObject>("Ground");
var groundGameObj = Instantiate(groundPrefab,transform);
groundGameObj.transform.position = mouseWorldPos;
groundGameObj.name = "Ground";
mCanDraw = false;
}
}
}
}