如何在 Unity 中为特定的克隆游戏对象播放粒子?
How to play particles for a specific cloned game object in 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);
}
}
第一个脚本附加到圆锥体预制件,第二个脚本附加到立方体。但问题是,当一个锥体撞击立方体时,其他锥体会发射粒子,而不是撞击立方体的锥体。
我该如何解决这个问题?
非常感谢任何帮助!
从立方体中删除圆锥体相关逻辑:
private void OnCollisionEnter(碰撞碰撞)
{
如果 (collision.gameObject.CompareTag("cone"))
{
// move.PlayParticles(); //------------ 删除这一行
GameDirector.DecreaseHp(0.25f);
}
}
使粒子变量可在检查器中分配 - 添加 [SerializeField] 属性。并在 inspector 中赋值。
- 将碰撞处理添加到您的圆锥体脚本中。
- 从脚本中删除不必要的静态信息。
像这样:
public class move : MonoBehaviour
{
[SerializeField] //------- Add attribute and do not forget to assign PS in inspector
ParticleSystem particle;
//static move instance; //----- Remove
//Remove Start:
/*
void Start()
{
particle = FindObjectOfType<ParticleSystem>();
instance = this;
}
*/
//Remove PlayParticles:
/*
public void PlayParticles()
{
Change:
instance.particle.Play();
}
*/
//---- Add collision check
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("cube")) //----- Set proper tag to your cube
{
particle.Play();
}
}
}
正如我所看到的,您(ab!)对所有内容都使用单例模式并调用了很多应该实例化的东西 static
methods/properties。
所以假设每个预制件都有您的 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);
}
}
但似乎您也可以让您的播放器自己直接处理整个事情。而是将粒子系统附加到它上面,然后将 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;
并通过检查器引用它或(仅作为后备)通过
在运行时获取它
private void Awake()
{
if(!gameDirector) gameDirector = FindObjectOfType<GameDirector>();
}
这里 FindObjectOfType
似乎是 "ok" 因为 GameDirector
听起来像是在场景中只存在 一次 的东西。
我现在正在用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);
}
}
第一个脚本附加到圆锥体预制件,第二个脚本附加到立方体。但问题是,当一个锥体撞击立方体时,其他锥体会发射粒子,而不是撞击立方体的锥体。 我该如何解决这个问题? 非常感谢任何帮助!
从立方体中删除圆锥体相关逻辑:
private void OnCollisionEnter(碰撞碰撞) { 如果 (collision.gameObject.CompareTag("cone")) { // move.PlayParticles(); //------------ 删除这一行 GameDirector.DecreaseHp(0.25f); }
}
使粒子变量可在检查器中分配 - 添加 [SerializeField] 属性。并在 inspector 中赋值。
- 将碰撞处理添加到您的圆锥体脚本中。
- 从脚本中删除不必要的静态信息。
像这样:
public class move : MonoBehaviour
{
[SerializeField] //------- Add attribute and do not forget to assign PS in inspector
ParticleSystem particle;
//static move instance; //----- Remove
//Remove Start:
/*
void Start()
{
particle = FindObjectOfType<ParticleSystem>();
instance = this;
}
*/
//Remove PlayParticles:
/*
public void PlayParticles()
{
Change:
instance.particle.Play();
}
*/
//---- Add collision check
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("cube")) //----- Set proper tag to your cube
{
particle.Play();
}
}
}
正如我所看到的,您(ab!)对所有内容都使用单例模式并调用了很多应该实例化的东西 static
methods/properties。
所以假设每个预制件都有您的 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);
}
}
但似乎您也可以让您的播放器自己直接处理整个事情。而是将粒子系统附加到它上面,然后将 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;
并通过检查器引用它或(仅作为后备)通过
在运行时获取它private void Awake()
{
if(!gameDirector) gameDirector = FindObjectOfType<GameDirector>();
}
这里 FindObjectOfType
似乎是 "ok" 因为 GameDirector
听起来像是在场景中只存在 一次 的东西。