【8.关卡游戏】5.生成道具

5.生成道具

5.1创建 Prefab

单个道具的行为已经完成,接下来需要创建自动生成道具的工厂。该工厂的功能:按照一定的时间间隔在随机位置生成苹果或*弹炸**。

工厂的创建方法:

  1. 使用已经存在的对象创建 Prefab
  2. 创建生成器脚本
  3. 给空对象挂载生成器脚本
  4. 将 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,需要调整参数时直接调用即可。