在一个2D平面上,玩家操控一个圆球进行上下左右移动,从而触碰到平面上一个小球,触碰到小球后游戏胜利,不过在触碰小球的过程中路上可能会有一些墙阻碍我们的移动,我们需要绕过它们然后触碰到小球。
大家可以根据前面的篇章思考一下应该怎么去做?
我们要完成的任务有以下几点:
- 小方块的上下左右移动
- 场景的设计
- 与墙壁的碰撞
- 触碰到目标提示通关
方块移动
我们首先需要创建一个圆球,在Hierarchy界面右键 2DObject -> Sprites -> Circle,我们给他命名为Player,同时在Inspector界面中color设置为蓝色。
接下来就要进行角色的移动了,还记得吗?在角色的移动得时候我们可以使用Transform组件中的Position,但是我们需要加入物理系统,此时就需要我们再去添加刚体Rigidbody 2D组件和碰撞体的Box Collider 2D组件。
准备好后就要添加Script脚本进行编写代码,在前几篇文章出现了人物触碰到墙壁抖动的问题和帧对移动速度影响的问题,在这里我们就直接利用刚体来设计代码。添加Script命名为Control。
public class Control: MonoBehaviour
{
public float speed = 5f;
Rigidbody2D rb;
float horizontal;
float vertical;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
}
private void FixedUpdate()
{
Vector2 position = rb.position;
position.x = position.x + speed * horizontal * Time.deltaTime;
position.y = position.y + speed * vertical * Time.deltaTime;
rb.MovePosition(position);
}
}
编写好代码之后我们的小蓝球就可以移动啦!
场景设计
在设计场景的时候,你可以使用瓦片地图设计地图,不过我为了方便就直接把背景全部涂成灰色的了。
随后就是设计墙壁,在这里我们还是在Hierarchy空白区域右键 2D Object ->Sprites -> Square 将方块进行拉伸形成一个墙壁并重命名为Wall,最后将Wall拖拽到Project中形成预制件。
最终场景设计的地图如下:
注意:这里的黄色是目标,我们可以在Hierarchy中同样添加一个Circle并把它变成黄色放置在场景当中。
墙壁碰撞
这里还记得刚才的预制件吗,我们进入到预制件模式,为Wall添加Box Collider 2D组件,然后我们再返回,这个时候我们运行游戏就可以发现小球会与墙壁发生碰撞啦!
触碰目标
在这里,我们需要让蓝色小球触碰到黄色小球后显示YOU WIN的文本。
右键Hierarchy空白区域, UI -> Text - TextMeshPro,这个时候可以看到Hierarchy中出现了Canvas和Text。
双击 Text,这个时候我们会到一个UI界面,这个界面将会是我们的游戏界面,此时可以点击Game来直观的看到这个文本。
YOU WIN!!!的文本信息。
在Main Setting内的Vertex Color中还可以修改字体颜色,这里我修改成了绿色。
最后我们需要在开始的使用禁用这个标签,当小蓝球触碰到黄球的时候启用。
双击Control脚本,我们开始编写代码,在这里我们对文本使用SetActive的函数来让文本禁用,在这里只做简单演示,以后遇到了会具体说明。
我们通过SetActive(false) 来禁用,SetActive(true)来启用,这个时候就需要思考达到什么条件的时候才需要启用这个文本。
由于我们没有说道触发器,所以这里我采用判断Position的方式来启用文本。
当小蓝球的位置等于小黄球的位置的时候就启用文本。
所以在Control代码中我们需要得到小黄球的位置。所以我们需要声明一个公有类,类型为GameObject,同样的,文本应该声明一个公有的GameObject。
public GameObject text;
public GameObject exit;
声明完之后返回到Unity界面,在Player的Inspector的脚本下会出现Text 和 Exit 的两个框,我们可以将Hierarchy中的Text拖入到Text后面的框中,将我们的小黄球(Exit)拖入到Exit后面的框中。
此时我们的Exit就获得了小黄球的组件信息,我们可以在Control中直接使用exit对象来获取小黄球内的组件,同理也可以控制Text文本信息。
还记得我们之前的想法么,当小黄球的位置等于小篮球的位置就显示文本信息。
void Start()
{
rb = GetComponent<Rigidbody2D>();
text.SetActive(false);
}
void Update()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
if(transform.position == exit.transform.position){
text.SetActive(true)
}
}
此时我们可以运行游戏看一下。
可以发现,文本信息确实消失了,但是当我们移动到小黄球的位置的时候并没有出现文本信息,究竟是怎么回事呢?这个时候在Update函数下添加两行代码。
Debug.Log("Player"+transform.position);
Debug.Log("EXIT"+exit.transform.position);
Debug函数可以通过Unity 中Console控制台来查看参数的变化。
我们运行后来回尝试终于发现了问题:Position的位置太精确了,我们移动的时候很难完全让两个位置一样,就跟两个很小的点要重叠一样,所以我们需要修改我们的代码,要让小蓝球在小黄球位置的范围内才可以。
public class Control : MonoBehaviour
{
public float speed = 5f;
public GameObject text;
public GameObject exit;
Rigidbody2D rb;
float horizontal;
float vertical;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
text.SetActive(false);
}
// Update is called once per frame
void Update()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
if (transform.position.x < exit.transform.position.x + 0.5f && exit.transform.position.x - 0.5f < transform.position.x && transform.position.y < exit.transform.position.y + 0.5f && exit.transform.position.y - 0.5f < transform.position.y)
{
text.SetActive(true);
}
}
private void FixedUpdate()
{
Vector2 position = rb.position;
position.x = position.x + speed * horizontal * Time.deltaTime;
position.y = position.y + speed * vertical * Time.deltaTime;
rb.MovePosition(position);
}
}
此时我们再运行游戏,发现成功了!
现在我们算是从头到尾做出来一个简单的小游戏,学习更多之后,比如我们还未接触到的触发器,就会方便我们不用写那么长的If条件语句。所以我们需要了解的知识还有很多啊。