前言
又是一次跟着教程做的练习,非常简单的一个小游戏。这里来记录一下一些新学到的东西和笔记。
教程地址: https://ke.qq.com/course/274001#term_id=100324034
工程代码:https://github.com/Aelinuial/Unity-Stick-Pin
一.场景
场景的含义在上一篇文章里已经介绍过了。这个游戏因为我们只做了第一关的本体,连开始画面和结束画面都没有,所以一共也就用到了一个场景。
二.直接来分析脚本吧
(一)Rotater.cs(其实旋转体的英文是rotator……这里我拼错了,代码里就将错就错了,囧。)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotater : MonoBehaviour {
public float speed = 90f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
transform.Rotate(0f, 0f, speed * Time.deltaTime);
}
}
这里的rotator是一个2D的sprite对象:
(2D object - sprite和UI - Image有什么区别? https://www.cnblogs.com/AaronBlogs/p/6863298.html)
可以看到,我们赋予它的行为只有旋转。
public void Rotate(float xAngle, float yAngle, float zAngle, Space relativeTo = Space.Self);
可以看到,我们实际上是让它绕着Z坐标轴旋转。由于这是一个2D的场景,因此我推测Z坐标轴是垂直于屏幕平面的。尝试改变Rotate函数的参数以后发现确实如此。
transform.Rotate(0f, 0f, speed * Time.deltaTime);
其中,Time.deltaTime的官方解释是 “以秒计算,完成最后一帧的时间(只读)”。我个人的理解即程序运行到这里所用的时间。与之相对的是,Update( )的刷新的单位是帧。
(二)Pin.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Pin : MonoBehaviour {
public float speed = 20f;
private Rigidbody2D rb;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody2D>();
rb.velocity = Vector2.up * speed;
}
// Update is called once per frame
void Update () {
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "Rotater")
{
rb.velocity = Vector2.zero;
if (Random.Range(0f, 1f) > 0.5f)
{
collision.GetComponent<Rotater>().speed *= -1;
}
collision.GetComponent<Rotater>().speed += 10;
Score.scoreValue++;
transform.SetParent(collision.transform);
}else if (collision.tag == "Pin")
{
GameObject.FindObjectOfType<Manager>().GameOver();
}
}
}
这里的Pin是指游戏中发射出去的针:
以下为官方文档的描述:
Rigidbody2D类本质上提供了与3D刚体同样功能。添加Rigidbody2D组件到一个精灵上置于物理引擎的控制下。就其本身而言,这意味着精灵会受到重力的影响并可以从脚本使用力控制。通过添加合适的碰撞器组件,该精灵也会响应与其他精灵碰撞。这种行为完全来自Unity的物理系统;非常少的代码得到令人印象深刻和真实的物理行为,并允许游戏中未明确编码的“突发”的运动。
GetComponent从当前游戏对象中获取组件T。在该脚本中,我们获取了组件Rigidbody2D,并赋予它一个向上的速度。(velocity)
↑ 然而我不是很懂为什么这部分要放在start( )函数中,这里有一张关于Unity的执行顺序的图也许可以解释一些东西:
void OnTriggerEnter2D(Collider2D collision)
这是一个2D触发器,由于我们在Pin上设置了trigger:
所以当Pin碰撞到ratator时,我们让score增加。为了(稍微)增加难度,我们让ratator的旋转方向随机变化并且随着Pin的数量增加速度。
如果Pin碰到的不是ratatoer而是其它Pin,则游戏结束。
GameObject.FindObjectOfType<Manager>().GameOver();
查找Manger类中的对象。
(三)Spawner.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawner : MonoBehaviour {
public GameObject pinFrefab;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetButtonDown("Fire1"))
{
SpawnPin();
}
}
void SpawnPin()
{
Instantiate(pinFrefab, transform.position, transform.rotation);
}
}
Input.GetButtonDown("Fire1")
这个显然是获取鼠标事件。然而我不是很懂后面的Fire1算是什么。查了一下Fire1是可以响应Ctrl按下的,然而实际上鼠标左键点击也是可以的……
这个脚本里主要就是定位了Pin的发射点。Instantiate函数用来克隆原始物体并返回克隆物体。其用法为:
Instantiate(要生成的物体,生成位置,旋转角度)
我们这里的transform.position和transform.rotation似乎是指主摄像机的位置和角度。
(四)Score.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Score : MonoBehaviour {
public static int scoreValue;
public Text scoreText;
// Use this for initialization
void Start () {
scoreValue = 0;
}
// Update is called once per frame
void Update () {
scoreText.text = scoreValue.ToString();
}
}
这里没什么内容,即初始时分数设置为0。
在UI - Text中显示当前分数。
(五)Manager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Manager : MonoBehaviour {
private bool isGameOver = false;
public Spawner spawner;
public Rotater rotater;
// Use this for initialization
void Start () {
Screen.SetResolution(450, 750, false);
}
public void GameOver()
{
if (!isGameOver)
{
isGameOver = true;
spawner.enabled = false;
rotater.enabled = false;
GetComponent<Animator>().SetTrigger("Gameover");
Debug.Log("Game Over");
}
}
public void RestartGame()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
// Update is called once per frame
void Update () {
}
}
这个脚本里主要就是控制界面大小,设定动画和结束界面的切换。这里要注意的是
GetComponent<Animator>().SetTrigger("Gameover");
这样的动画加载方式。具体似乎可以通过学习Unity动画系统了解。
结尾
这么看看其实一个游戏只用到了五个很短的脚本,素材只有一张圆的图片。但是如果让我从头再写一遍并且讲清楚各个部分的用法和意义其实我还是不太懂的,还是要继续加油学习呀……