【问题标题】:Accessing Unity particle emitter via script通过脚本访问 Unity 粒子发射器
【发布时间】:2020-02-04 14:34:56
【问题描述】:

我创建了一个粒子系统,并且在我的游戏中的某个时间点我想增加最大粒子数。

因此,我创建了一个游戏对象,并在其上附加了一个盒子 2d 对撞机,当它与玩家接触时会触发。在该脚本中,我创建了一个公共 GameObject 叶粒子系统,并将粒子系统拖入其中。

但是,在我的代码中,我无法执行类似的操作

leafParticleSystem.maxParticles=500; 

leafParticleSystem.emission.rate=5.0f

我的代码也在说

"MissingComponentException: There is no 'ParticleSystem' attached to the "Herld" game object, but a script is trying to access it.
You probably need to add a ParticleSystem to the game object "Herld". Or your script needs to check if the component is attached before using it.untime/Export/Coroutines.cs:17)"

然而,这个“Herld”游戏对象不是粒子系统(我也不想给它添加一个)但是,它确实附有我将粒子系统(叶子粒子系统)拖到的脚本。我只是想从“Herld”对象中的代码修改叶粒子系统。

如果我能得到任何帮助将不胜感激

附上脚本

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

public class WindEffect : MonoBehaviour {
//  Rigidbody2D _rigidbody;
    // Use this for initialization

    //Storm Warning
    public GameObject AOE;
    public GameObject UIStormInterface;
    public GameObject UIWindZone;

    public GameObject LeafStormParticleSystem;


    public float ActivateFor=5.0f;
    public float stormLength=5.0f; 


    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
    void Awake () {

//      _rigidbody = GetComponent<Rigidbody2D> ();
    }

    void OnTriggerEnter2D(Collider2D col)
    {
    // Debug.Log("Object touched trigger");
    //  Debug.Log (col.transform.name); 
        if (col.gameObject.name == "Player") {
            Debug.Log ("Collided with Storm Herald");
            StartCoroutine (TemporarilyActivateStormWarning (ActivateFor));

        }
    }

    private IEnumerator TemporarilyActivateStormWarning(float ActivateFor) {
    //Show Storm Warning
        this.gameObject.GetComponent<BoxCollider2D>().enabled=(false);
        UIStormInterface.GetComponent<Text>().text="A Violent Storm is Approaching";
        UIStormInterface.SetActive(true);

        UIWindZone.SetActive (true);
        //Wait for 5 seconds then activate storm for 5 seconds
        yield return new WaitForSeconds(ActivateFor);

        UIStormInterface.SetActive(false);
        AOE.SetActive (true);

        //  ParticleSystem LeafStormParticleSystem = GetComponent<ParticleSystem>();
    //  LeafStormParticleSystem.emission.rate = 5.0f;
        LeafStormParticleSystem.maxParticles = 500;


        yield return new WaitForSeconds(stormLength);


        //Turn off Storm
        AOE.SetActive (false);
        //Tell user storm is stopped for 2 seconds.

        UIStormInterface.GetComponent<Text>().text="Storm has Passed";
        UIStormInterface.SetActive(true);
        yield return new WaitForSeconds(3);
        UIStormInterface.SetActive(false);
        UIWindZone.SetActive (false);
    }
    void OnTriggerStay2D(Collider2D col)
    {
        if (col.gameObject.name == "WindObject") {
            Debug.Log ("Collided");
            //  Debug.Log (col.transform.name); 
        //  Wind();
            //StartCoroutine(WindStart());
        }
    }
    /*
    IEnumerator WindStart(){
        Debug.LogError ("Slow Time.");

        //SlowTheTime();
    //  yield return new WaitForSeconds(3.5f);
        //  Debug.LogError ("Slow Time.");
    //  Wind ();
    }*/


    void OnCollisionEnter2D(Collision2D col)
    {
//      Debug.Log (col.transform.name); 
    }
    void OnTriggerStay(Collider col)
    {
        Debug.Log("Object is in trigger");

    }
    void OnTriggerExit(Collider other)
    {
        Debug.Log("Object left the trigger");
    }


    /*
    void Wind(){
        _rigidbody = GetComponent<Rigidbody2D> ();
        Debug.Log ("test got here");
        Debug.Log (this.gameObject.name);
        this._rigidbody.AddForce (-Vector2.left * 100 );
    }*/

}

【问题讨论】:

  • 你能包含附加到“Herld”游戏对象的脚本吗? leafParticleSystem 是对它的引用吗?
  • 包含脚本,是的,我将它拖放到公共游戏对象中,就像我用来访问分数和画布等的所有其他公共变量一样
  • 谢谢。所以让我看看我是否理解这种情况...leafParticleSystem 是一个公共 GameObject 变量,您将 GameObject“Herld”(附加了 WindEffect 组件)拖到该变量上?而你要访问的粒子系统存储在WindEffect脚本的公共变量LeafStormParticleSystem中?
  • 不,leafParticleSystem 是公共 GameObject 变量,我将粒子对象从 heirachy 拖到该变量上。是的,GameObject Herald 确实附加了 windEffect 组件,是的,我要编辑的粒子是 LeafStormParticleSystem
  • 嗯...嗯,leafParticleSystem 是带有粒子系统的游戏对象,还是 LeafStormParticleSystem?根据您的上一条评论,我无法想象这种关系。

标签: c# unity3d


【解决方案1】:

目前,您的 LeafStormParticleSystem 变量为您提供了对 ParticleSystem 组件所在的 GameObject 的引用,而不是 ParticleSystem 本身。因此,您无法访问粒子系统的成员,例如 maxParticlesemission。您可以采取两种方法来纠正此问题:

当您需要访问粒子系统时,请致电 GetComponent&lt;ParticleSystem&gt;() 如果过于频繁,这可能会导致代价高昂 - 修改成员的语法如下:

LeafStormParticleSystem.GetComponent<ParticleSystem>().maxParticles = 500;

将您的LeafStormParticleSystemGameObject 更改为ParticleSystem 这可以让您在编辑器中为LeafStormParticleSystem 分配对粒子系统的直接引用,并且比反复拨打GetComponent()。语法是:

// Change the datatype
public ParticleSystem LeafStormParticleSystem;

// [...]
// To modify members later, you can do as you're currently doing:
LeafStormParticleSystem.maxParticles = 500;

// Modifying the emission rate is a bit less straightforward, because emission is a struct
var newEmission = LeafStormParticleSystem.emission;
newEmission.rate = new ParticleSystem.MinMaxCurve(5.0f);
LeafStormParticleSystem.emission = newEmission;

希望这会有所帮助!如果您有任何问题,请告诉我。

【讨论】:

  • 太好了,谢谢。最后一件事,当我说: LeafStormParticleSystem.emission.rate=40.0f;
  • @UnknownCode 有趣,也许您正在尝试修改结构?错误是什么?
  • Cannot modify a value type return value of UnityEngine.ParticleSystem.emission'. Consider storing the value in a temporary variable Property or indexer UnityEngine.ParticleSystem.emission' 不能赋值(只读)不明白为什么会只读
  • @UnknownCode 那是因为emission 是一个结构体,在这里是不可变的。您需要获取该值的副本,修改其rate 变量,然后将其分配回emission - 我已相应地编辑了答案。让我知道它是否可以正常工作!
  • 排放量有一个最小值和最大值。
【解决方案2】:

编辑:现在我看到了您的脚本,并且...是的..您没有对 ParticleSystem 的引用

这里你没有访问 ParticleSystem 对象,你访问的是包含它的 GameObject: LeafStormParticleSystem.maxParticles = 500;

引用 ParticleSystem 本身,而不是 GameObject。

LeafStormParticleSystem.GetComponent<ParticleSystem>().maxParticles = 500;

旧: 您应该获得对您的粒子系统的引用(在我的情况下我停止它),例如在 Start 函数中:

private ParticleSystem ps;
void Start()
{
    ps = GetComponentInChildren<ParticleSystem>();
    ps.Stop();
}

之后,您可以启动或编辑粒子(在我的例子中,在一个单独的函数中播放和更改 maxParticles):

void StartEmission()
{
    ps.Play();
    ps.maxParticles = 500;
}

【讨论】:

  • 如果您在我的 Start 函数中有参考,请这样做: LeafStormParticleSystem.emissionRate = 32;如果你没有我的 Start 函数中的引用(只是 GameObject),请这样做: LeafStormParticleSystem.GetComponent().emissionRate = 32;
  • 在 Unity 5.5.0f3 (mine) 中,emissionRate 参数已过时但仍在工作。
【解决方案3】:

解决方案 1:

只需尝试将 LeafStormParticleSystem 的数据类型更改为 ParticleSystem。 这样就可以借助 LeafStormParticleSystem 变量来访问粒子系统相关的方法和属性了

public ParticleSystem LeafStormParticleSystem;

解决方案 2:

您不能直接访问 GameObject 的 ParticleSystem 方法和属性,除非您没有将该变量类型转换为 ParticleSystem 类型。

为此,您可以尝试:

LeafStormParticleSystem.GetComponent<ParticleSystem>().maxParticles = 500;

((ParticleSystem)LeafStormParticleSystem).maxParticles = 500;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-28
    • 1970-01-01
    相关资源
    最近更新 更多