首页 > 解决方案 > 如何在 Unity 中为特定的克隆游戏对象播放粒子?

问题描述

我现在正在 Unity 中制作一个简单的游戏。有锥体从天而降,玩家需要控制一个立方体来躲避它们。当一个锥形击中立方体时,它会降低立方体的 HP 并发射一些粒子。这是我的脚本:

public class move : MonoBehaviour{

ParticleSystem particle;

static move instance;

void Start()
{
    particle = FindObjectOfType<ParticleSystem>();
    instance = this;
}

public static void PlayParticles()
{
    instance.particle.Play();
}
}

第二:

private void OnCollisionEnter(Collision collision)
{
    if (collision.gameObject.CompareTag("cone"))
    {
        move.PlayParticles();
        GameDirector.DecreaseHp(0.25f);

    }

}

第一个脚本附加到锥形预制件,第二个脚本附加到立方体。但问题是,当一个锥体撞击立方体时,其他锥体会发射粒子,而不是撞击立方体的锥体。我该如何解决这个问题?任何帮助是极大的赞赏!

标签: c#unity3dparticlesparticle-system

解决方案


正如我所看到的,您(ab!)对所有事情都使用单例模式,并调用了很多static应该是实例化方法/属性的东西。


因此,假设每个预制件都有你的move脚本以及ParticleSystem它自己的层次结构中的某个地方,你宁愿这样做

public class move : MonoBehaviour
{
    // Already reference this via the Inspector by dragging the 
    // GameObject with the ParticleSystem into this slot
    [SerializeField] private ParticleSystem particle;

    private void Awake()
    {
        // As fallback get it on runtime
        if(!particle) particle = GetComponentInChildren<ParticleSystem>(true);
    }

    // Use a normal instanced method
    public void PlayParticles()
    {
        particle.Play();
    }
}

然后从碰撞中获取实例:

private void OnCollisionEnter(Collision collision)
{
    if (collision.gameObject.CompareTag("cone"))
    {
        // Get the instance of the component
        var moveInstance = collision.gameObject.GetComponent<move>();
        if(!moveInstance)
        {
             Debug.LogError($"There is no {nameof(move)} component attached to the colliding object {collision.gameObject.name}!", this);   
        }
        else
        {
            // call the method of this instance
            moveInstance.PlayParticles();
        }
        GameDirector.DecreaseHp(0.25f);
    }
}

但似乎你也可以让你的 Player 直接自己处理整个事情。而是将粒子系统附加到它上,然后像这样放在move播放器(立方体)上

public class move : MonoBehaviour
{
    // Already reference this via the Inspector by dragging the 
    // GameObject with the ParticleSystem into this slot
    [SerializeField] private ParticleSystem particle;

    void Start()
    {
        if(!particle) particle = GetComponentInChildren<ParticleSystem>(true);
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.CompareTag("cone"))
        {
            particle.Play();
            GameDirector.DecreaseHp(0.25f);
        }
    }
}

注意:它可能是相同的GameDirector,你应该有一个字段

[SerilaizeField] private GameDirector gameDirector;

并通过 Inspector 引用它,或者(仅作为后备)在运行时通过

private void Awake()
{
    if(!gameDirector) gameDirector = FindObjectOfType<GameDirector>();
}

FindObjectOfType似乎是“好的”,因为GameDirector听起来像是场景中只存在一次的东西。


推荐阅读