【unity实战】基于权重的随机事件(附项目源码)

简介: 【unity实战】基于权重的随机事件(附项目源码)

前言

随机功能和UnityEvent前面其实我们都已经做过了,但是随机+UnityEvent事件要怎么使用呢?这里就来举一个例子说明。

当然对之前随机功能和UnityEvent事件感兴趣的小伙伴也可以去看看,这里我贴出地址

ps:本篇为自己的学习记录,希望对你有帮助

开始

一、简单的使用

新增ChestInteractableEvents,定义宝箱交互事件

[System.Serializable]
public class ChestInteractableEvents
{
    [Header("宝箱事件名称")]
  public string EventName;
  [Range(0f, 1f), Header("掉落几率")]
  public float DropChance = 0.5f;
    [Header("宝箱交互事件")]
  public UnityEvent ChestInteractionEvent;
}

新增Box

public class Box : MonoBehaviour
{
  [Header("宝箱交互事件数组")]
  [SerializeField] private ChestInteractableEvents[] _chestInteractionEvents;
  
  //测试执行
  private void Update()
  {
      if (Input.GetKeyDown(KeyCode.Space))
      {
          DetermineAndFireChestEvent();
      }
  }
  
  private void DetermineAndFireChestEvent()
  {
    // 计算总的掉落几率
    float totalChance = 0f;
    foreach (ChestInteractableEvents interactableEvents in _chestInteractionEvents)
    totalChance += interactableEvents.DropChance;
    
    float rand = Random.Range(0f, totalChance); // 生成一个随机数,范围是0到总掉落几率
    float cumulativeChance = 0f;
    foreach (ChestInteractableEvents interactableEvents in _chestInteractionEvents)
    {
        cumulativeChance += interactableEvents.DropChance;
        if (rand < cumulativeChance)
        {
            interactableEvents.ChestInteractionEvent.Invoke(); // 触发宝箱交互事件
            return;
        }
    }
  }
  
  // 生成金币
  public void SpawnCoins()
  {
    Debug.Log("生成了一个金币");
  }
  
  // 生成敌人
  public void SpawnEnemies()
  {
    Debug.Log("生成了敌人");
  }
  
  // 生成生命药水
  public void SpawnHealthPotion()
  {
    Debug.Log("生成了一个生命药水");
  }
}

箱子挂载脚本,配置事件

运行效果

二、完善各种事件

1. 完善生成金币事件

[Header("生成金币")]
[SerializeField] private Rigidbody2D _coinToSpawn; // 要生成的金币刚体
[SerializeField] private int _numberofCoinsTospawn = 100; // 要生成的金币数量
[SerializeField] private float _explosionForce = 10f; // 金币爆炸力度
[SerializeField, Range(0f, 0.5f)] private float _explosionArc = 0.5f; // 金币爆炸角度范围
[SerializeField] private bool _delayBetweenspawns = false; // 是否延迟生成金币
[SerializeField] private Transform _spawnTransform; // 生成金币的位置

/// <summary>
/// 生成金币
/// </summary>
public void SpawnCoins()
{
  if (!_delayBetweenspawns)
  {
    // 直接生成金币
    for (int i = 0; i < _numberofCoinsTospawn; i++)
    {
      Rigidbody2D coinRB = Instantiate(_coinToSpawn, _spawnTransform.position, Quaternion.identity);
      Explosion(coinRB);
    }
  }
  else
  {
    // 延迟生成金币
    StartCoroutine(SpawnCoinsWithDelay());
  }
}

/// <summary>
/// 延迟生成金币
/// </summary>
/// <returns></returns>
private IEnumerator SpawnCoinsWithDelay()
{
  for (int i = 0; i < _numberofCoinsTospawn; i++)
  {
    Rigidbody2D coinRB = Instantiate(_coinToSpawn, _spawnTransform.position, Quaternion.identity);
    Explosion(coinRB);
    yield return null;
  }
}

/// <summary>
/// 金币爆炸效果
/// </summary>
/// <param name="rb"></param>
private void Explosion(Rigidbody2D rb)
{
  Vector2 randDir = new Vector2(Random.Range(-_explosionArc, _explosionArc), 1f);
  Vector2 force = randDir.normalized * _explosionForce;
  rb.AddForce(force, ForceMode2D.Impulse);
}

效果,金币飞出

2. 完善生成敌人事件敌人

[Header("生成敌人")]
[SerializeField] private GameObject[] _enemiesToSpawn; // 要生成的敌人数组
[SerializeField] private GameObject _enemySpawnParticles; // 敌人生成时的粒子效果
[SerializeField] private int _numofEnemiesToSpawn = 3; // 要生成的敌人数量
[SerializeField, Range(0f, 15f)] private float _enemySpawnoffset = 2f; // 敌人生成的偏移距离

/// <summary>
/// 生成敌人
/// </summary>
public void SpawnEnemies()
{
    for (int i = 0; i < _numofEnemiesToSpawn; i++)
    {
        int randIndex = Random.Range(0, _enemiesToSpawn.Length);
        float randX = Random.Range(-_enemySpawnoffset, _enemySpawnoffset);
        float randY = Random.Range(-_enemySpawnoffset, _enemySpawnoffset);
        Vector2 spawnPos = ((Vector2)_spawnTransform.position + new Vector2(randX, randY)).normalized;
        GameObject enemy = Instantiate(_enemiesToSpawn[randIndex], spawnPos, Quaternion.identity);
        //生成粒子效果
        GameObject enemySpawnParticles = Instantiate(_enemySpawnParticles, spawnPos, Quaternion.identity);
        //粒子效果和敌人大小一致
        enemySpawnParticles.transform.localScale = enemy.transform.localScale;
    }
}

效果

3. 完善生成药水事件

[Header("生成生命药水")]
[SerializeField] private Rigidbody2D _healthPotionToSpawn; // 要生成的生命药水刚体
[SerializeField] private float _upwardForce = 5f; // 生命药水向上的力度

/// <summary>
/// 生成生命药水
/// </summary>
public void SpawnHealthPotion()
{
    Rigidbody2D rb = Instantiate(_healthPotionToSpawn, _spawnTransform.position, Quaternion.identity);
    Vector2 force = Vector2.up * _upwardForce;
    rb.AddForce(force, ForceMode2D.Impulse);
}

效果

最终效果

参考

【视频】https://www.youtube.com/watch?v=UeTlJyBz7h8

源码

https://gitcode.net/unity1/unity-randomevent

目录
相关文章
|
2天前
|
存储 JSON 关系型数据库
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
11 2
|
2天前
|
图形学
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)(上)
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)
10 2
|
2天前
|
人工智能 定位技术 图形学
【unity实战】制作敌人的AI,使用有限状态机、继承和抽象类多态 定义不同状态的敌人行为
【unity实战】制作敌人的AI,使用有限状态机、继承和抽象类多态 定义不同状态的敌人行为
45 1
|
2天前
|
图形学
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(下)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
7 0
|
2天前
|
图形学 容器
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(上)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
5 0
|
2天前
|
存储 JSON 图形学
【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解
6 0
|
2天前
|
存储 图形学
【unity小技巧】unity事件系统创建通用的对象交互的功能
【unity小技巧】unity事件系统创建通用的对象交互的功能
6 0
|
2天前
|
图形学
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)(下)
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)(下)
8 0
|
2天前
|
图形学
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版3(附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版3(附带项目源码)
13 2
|
2天前
|
图形学
【制作100个unity游戏之28】花半天时间用unity复刻童年4399经典小游戏《黄金矿工》(附带项目源码)
【制作100个unity游戏之28】花半天时间用unity复刻童年4399经典小游戏《黄金矿工》(附带项目源码)
10 0