Unity中基于粒子碰撞的智能腐蚀系统开发指南——从水枪控制到动态物体管理

完整代码:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class WaterGunController1 : MonoBehaviour
{
    [Header("粒子系统")]
    public ParticleSystem waterParticles;

    [Header("UI控制")]
    public Button startButton;
    public Button shutButton;
    public GameObject waterGunUI;

    [Header("腐蚀设置")]
    public string corrosionTag = "Corrosive";

    [Header("水枪本体")]
    public GameObject waterGunObject;

    // 新增:预加载腐蚀物体列表
    private GameObject[] corrosiveObjects;

    void Start()
    {
        startButton.onClick.AddListener(StartWaterGun);
        shutButton.onClick.AddListener(StopWaterGun);

        // 初始化时获取所有腐蚀物体
        corrosiveObjects = GameObject.FindGameObjectsWithTag(corrosionTag);
        Debug.Log($"找到{corrosiveObjects.Length}个腐蚀物体");

        ConfigureParticleCollision();
    }

    void ConfigureParticleCollision()
    {
        var collision = waterParticles.collision;
        collision.enabled = true;
        collision.mode = ParticleSystemCollisionMode.Collision3D;
        collision.quality = ParticleSystemCollisionQuality.High;
        collision.sendCollisionMessages = true;
        collision.collidesWith = LayerMask.GetMask("Default");
    }

    void StartWaterGun()
    {
        waterParticles.Play();
        Debug.Log("水枪启动");
    }

    void StopWaterGun()
    {
        waterParticles.Stop();
        Debug.Log("水枪停止");
    }

    void OnParticleCollision(GameObject other)
    {
        Debug.Log($"粒子碰撞到:{other.name}");
        if (other.CompareTag(corrosionTag))
        {
            DestroyCorrodedObject(other);
            CheckAllObjectsDestroyed();
        }
    }

    void DestroyCorrodedObject(GameObject obj)
    {
        Debug.Log($"正在销毁:{obj.name}");
        Destroy(obj);

        // 从数组中移除已销毁物体
        var list = new List(corrosiveObjects);
        list.Remove(obj);
        corrosiveObjects = list.ToArray();
    }

    void CheckAllObjectsDestroyed()
    {
        Debug.Log($"剩余腐蚀物体数量:{corrosiveObjects.Length}");

        // 使用预加载数组检测
        bool allDestroyed = true;
        foreach (var obj in corrosiveObjects)
        {
            if (obj != null)
            {
                allDestroyed = false;
                break;
            }
        }

        if (allDestroyed)
        {
            Debug.Log("开始关闭流程");

            // 停止粒子系统
            waterParticles.Stop();

            // 关闭UI
            if (waterGunUI != null)
            {
                waterGunUI.SetActive(false);
                Debug.Log("UI已关闭");
            }

            // 关闭水枪本体
            if (waterGunObject != null)
            {
                waterGunObject.SetActive(false);
                Debug.Log("水枪本体已关闭");
            }
            else
            {
                gameObject.SetActive(false);
                Debug.Log("默认物体已关闭");
            }
        }
    }
}

 

一、代码核心功能

这段代码实现了一个完整的水枪腐蚀系统,主要包含以下功能:

  1. 水枪粒子控制:通过UI按钮控制水枪的启动/停止

  2. 腐蚀物体交互:当水粒子碰撞到标记为腐蚀的物体时,触发物体销毁

  3. 自动关闭机制:当场景中所有腐蚀物体消失后,自动关闭水枪系统和UI界面

  4. 调试监控:通过控制台实时显示系统状态

二、代码结构解析

1. 变量声明部分
[Header("粒子系统")]
public ParticleSystem waterParticles;

[Header("UI控制")]
public Button startButton;
public Button shutButton;
public GameObject waterGunUI;

[Header("腐蚀设置")]
public string corrosionTag = "Corrosive";

[Header("水枪本体")]
public GameObject waterGunObject;

private GameObject[] corrosiveObjects;
  • 功能说明

    • 使用[Header]属性在Unity Inspector中创建分组标签

    • 公开可配置的粒子系统、UI元素、水枪本体等引用

    • corrosiveObjects数组用于存储场景中所有腐蚀物体

2. 初始化部分
void Start()
{
    // 按钮事件绑定
    startButton.onClick.AddListener(StartWaterGun);
    shutButton.onClick.AddListener(StopWaterGun);
    
    // 预加载腐蚀物体
    corrosiveObjects = GameObject.FindGameObjectsWithTag(corrosionTag);
    Debug.Log($"找到{corrosiveObjects.Length}个腐蚀物体");

    ConfigureParticleCollision();
}

 

  • 关键点

    • 使用FindGameObjectsWithTag预加载所有腐蚀物体

    • 初始化时打印腐蚀物体数量用于调试

    • 调用粒子系统配置方法

3. 粒子系统配置
void ConfigureParticleCollision()
{
    var collision = waterParticles.collision;
    collision.enabled = true;
    collision.mode = ParticleSystemCollisionMode.Collision3D;
    collision.quality = ParticleSystemCollisionQuality.High;
    collision.sendCollisionMessages = true;
    collision.collidesWith = LayerMask.GetMask("Default");
}
  • 配置细节

    • 启用3D碰撞检测

    • 设置碰撞质量为High(精确检测)

    • 开启碰撞消息发送

    • 只与Default层的物体发生碰撞

4. 水枪控制逻辑
void StartWaterGun() => waterParticles.Play();
void StopWaterGun() => waterParticles.Stop();
  • 特点

    • 简洁的按钮响应方法

    • 直接控制粒子系统的播放/停止

 5. 碰撞处理核心

void OnParticleCollision(GameObject other)
{
    Debug.Log($"粒子碰撞到:{other.name}");
    if (other.CompareTag(corrosionTag))
    {
        DestroyCorrodedObject(other);
        CheckAllObjectsDestroyed();
    }
}
  • 执行流程

    1. 打印碰撞物体名称

    2. 校验标签是否匹配

    3. 触发销毁逻辑

    4. 检查剩余物体

6. 物体销毁逻辑

 

void DestroyCorrodedObject(GameObject obj)
{
    Debug.Log($"正在销毁:{obj.name}");
    Destroy(obj);
    
    // 从数组中移除已销毁物体
    var list = new List(corrosiveObjects);
    list.Remove(obj);
    corrosiveObjects = list.ToArray();
}
  • 创新点

    • 使用动态列表更新腐蚀物体数组

    • 确保数组只包含未被销毁的物体

7. 全物体检测逻辑
void CheckAllObjectsDestroyed()
{
    Debug.Log($"剩余腐蚀物体数量:{corrosiveObjects.Length}");

    bool allDestroyed = true;
    foreach (var obj in corrosiveObjects)
    {
        if(obj != null)
        {
            allDestroyed = false;
            break;
        }
    }

    if(allDestroyed)
    {
        // 关闭系统逻辑...
    }
}

双重校验机制

  1. 通过数组长度初步判断

  2. 遍历检查每个物体是否为null

三、工作流程图解

graph TD
    A[游戏启动] --> B[初始化腐蚀物体列表]
    B --> C[配置粒子碰撞]
    C --> D[等待玩家操作]
    D -->|点击启动按钮| E[播放粒子效果]
    E --> F[实时碰撞检测]
    F -->|碰撞腐蚀物体| G[销毁物体并更新列表]
    G --> H{所有物体销毁?}
    H -->|是| I[关闭水枪系统]
    H -->|否| F

四、技术难点解析

  1. 粒子碰撞检测
    • 需要确保粒子系统的Send Collision Messages已启用

    • 碰撞层(Layer)设置必须正确匹配

    • 3D碰撞模式需要物体具有合适的碰撞体

  2. 空引用处理
    • 使用Destroy()后对象不会立即变为null

    • 采用预加载数组+动态移除策略保证数据准确性

  3. 多物体同步
    • 处理多个腐蚀物体同时被击中的情况

    • 使用线程安全的List操作避免数据竞争

 

 

 

 

 

 

 

你可能感兴趣的:(unity,粒子系统,碰撞检测,动态对象管理,Unity初学者,游戏开发者)