5.生成道具
5.1创建 Prefab
单个道具的行为已经完成,接下来需要创建自动生成道具的工厂。该工厂的功能:按照一定的时间间隔在随机位置生成苹果或*弹炸**。
工厂的创建方法:
- 使用已经存在的对象创建 Prefab
- 创建生成器脚本
- 给空对象挂载生成器脚本
- 将 Prefab 传递给生成器脚本
首先,将苹果和*弹炸**从层级窗口拖拽到工程窗口中,命名为:applePrefab 和 bombPrefab。然后从层级窗口中删除苹果和*弹炸**。
5.2创建生成器脚本
在工程窗口右击选择 Create -> C# Script,命名为 ItemGenerator。编写脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemGenerator : MonoBehaviour
{
public GameObject applePrefab;
float span = 1.0f;
float delta = 0.0f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
delta += Time.deltaTime;
if (delta > span)
{
delta = 0.0f;
Instantiate(applePrefab);
}
}
}
上面的代码中,只生成苹果实例。
5.3挂载生成器脚本
在层级窗口中创建一个空对象,命名为 ItemGenerator。将生成器脚本挂载到 ItemGenerator 对象上,然后将 applePrefab 拖拽到检视器窗口中脚本的 Apple Prefab 上。启动游戏,看看效果。
这时,我们看到每隔 1 秒会落下 1 个苹果,但都是在同一位置落下。
5.4随机落下
让道具随机落下包含如下功能:
- 道具落下的位置随机
- 生成道具的种类随机
1.道具落下的位置随机
道具落下的位置由 x 坐标和 z 坐标决定,舞台的中心位于原点,左右区域的中心是加 1 或减 1 算出来的,所以,x 坐标和 z 坐标的取值可能是:-1、0、1。
修改代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemGenerator : MonoBehaviour
{
public GameObject applePrefab;
float span = 1.0f;
float delta = 0.0f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
delta += Time.deltaTime;
if (delta > span)
{
delta = 0.0f;
GameObject obj = Instantiate(applePrefab) as GameObject;
float x = Random.Range(-1, 2);
float z = Random.Range(-1, 2);
obj.transform.position = new Vector3(x, 4, z);
}
}
}
上面的代码中,通过 as 将实例化的 Prefab 转换为 GameObject,通过 Random 类的 Range 方法生成随机数(该方法返回大于等于第一个参数并小于第二个参数的整数)。运行游戏后可以发现苹果能够在随机位置落下。
2.生成道具的种类随机
对于随机生成道具,我们设计一个简单的算法:假设我们希望生成*弹炸**的概率为 20%,那么,我们可以随机生成1 ~ 10的整数,如果为1 或 2,则生成*弹炸**,否则生成苹果。
修改代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemGenerator : MonoBehaviour
{
public GameObject applePrefab;
public GameObject bombPrefab;
float span = 1.0f;
float delta = 0.0f;
int probability = 2;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
delta += Time.deltaTime;
if (delta > span)
{
delta = 0.0f;
int n = Random.Range(1, 11);
GameObject obj;
if (n <= probability)
{
obj = Instantiate(bombPrefab) as GameObject;
}
else
{
obj = Instantiate(applePrefab) as GameObject;
}
float x = Random.Range(-1, 2);
float z = Random.Range(-1, 2);
obj.transform.position = new Vector3(x, 4, z);
}
}
}
在上面的代码中,增加了:
public GameObject bombPrefab; 用于表示*弹炸**的 Prefab,将 bombPrefab 拖拽到检视器窗口中脚本的 BombPrefab 上。
运行游戏,检查效果。
3.让参数能够在外部调整
为什么要让参数能够在外部调整呢?因为我们本章开头就说明要做的是一个关卡游戏,其中的关卡设计就是通过调整参数来让:
- 道具产生的时间间隔越来越短
- *弹炸**出现的概率越来越大
- 道具的下落速度越来越块
下面我们通过修改代码来实现参数化和道具下落速度控制。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemGenerator : MonoBehaviour
{
public GameObject applePrefab;
public GameObject bombPrefab;
float span = 1.0f;
float delta = 0.0f;
int probability = 2;
float speed = -0.03f;
public void SetParameters(float span, int probability, float speed)
{
this.span = span;
this.probability = probability;
this.speed = speed;
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
delta += Time.deltaTime;
if (delta > span)
{
delta = 0.0f;
int n = Random.Range(1, 11);
GameObject obj;
if (n <= probability)
{
obj = Instantiate(bombPrefab) as GameObject;
}
else
{
obj = Instantiate(applePrefab) as GameObject;
}
float x = Random.Range(-1, 2);
float z = Random.Range(-1, 2);
obj.transform.position = new Vector3(x, 4, z);
obj.GetComponent<ItemController>().dropSpeed = speed;
}
}
}
首先,在代码中增加
float speed = -0.03f; 在 ItemController 中我们已经控制了下落速度,所以在代码获取对应的组件来修改速度就可以了,代码如下:
obj.GetComponent<ItemController>().dropSpeed = speed;
对于参数化,我们增加一个方法 SetParameters,需要调整参数时直接调用即可。