- Home /
Destroy GameObject without "killing" Parameters
Hi together,
I am developing at the moment a small Space Shooter and have some problems with a Gameobject and/or the Scripting and hope you can help a beginner like me to solve that Problem.
The actual situation:
I have build a Shield Prefab which shall be activated when the Player is colliding with a Powerup Gameobject. In my Player Script I check if the Shield PowerUp is active (with a boolean variable). If the boolean is true I initiate the Shield Prefab. This works fine, but I have the problem, that the Shield Gameobjects are not disappear. So I also have a lots of Shield Gameobjects in the Hierarchy. I could destroy them immediately because with the next Update Call the next Shield will generated. But I also want to hand over a value for the Shield Power (3 at the beginning). If the shield is colliding with another object (enemy) the power shall get lower. But with the Destroying of the Gameobject of the Shield to solve the problem above the Shield Power will be always 3 because I initiate the original ShieldPrefab.
I tried to handle it with parameters in the method in the Script for the player, but that didn't work (or I didn't write the right code).
Have maybe someone of you a hint for me how I can solve that problem? I hope the description was understandable. If not don't hesitate to ask for more information.
Thanks in advance.
Good day.
I i correctly understand what are you asking...
Your shield capacity is always:
ShieldCapacity = 3 + Number of collected shield
Correct?
so, if you destroy all shields the it will be always 3. You can make shieldCapaccity to start at 0, and give 3 ShiledOBjects at the begining.
Anyway. Is not recommended to have multiple shield gameobjects active... is better to have only one and control by script its power.
Hello. Thanks for your reply! Yes, my goal is to use only one Gameobject for the shield and to control it via script. Otherwise will suffer the performance sooner or later.
Your idea sounds good, but I am not sure if it will solve my problem. I only have a Shield Capacity of 3 (at the beginning). I don't add the number of the shields. I think I maybe described it a little bit confuse, sorry!
When the Shield is activated the Value is 3. It will activate if the trigger is true). In my Player-Script I Initiate the ShieldPrefab (which is following the Player). So far so good.
The value shall decrease by 1 when the Player is being hit by another Gameobject (Enemy, Laser, Asteroid, and so on). If it is zero than the Shield has to be destroyed. This logic I handle in the Shield Script. But with this code there will be plenty of active ShieldPrefabs active.
So I am looking for a solution that makes it possible that I only have one ShieldObject which "follow" the Gamer and store the actual Capacity of the Shield.
But if I understand you right you say that I shall create 3 Shield objects and one is "hit" this one will get destroyed, right? And if all are destroyed the player will not have any shield anymore? Is that correct or do I understand you wrong?
Thanks a lot for your help!
Greets!
Answer by Harinezumi · Apr 18, 2018 at 10:13 AM
I think you are instantiating a new instance of the shield prefab in every Update() while the shield power up boolean is true. That is not necessary, you can keep an instance and its state while the shield lasts.
You can do this by creating a new shield instance only when you pick up the power up (and now you don't even need the boolean in the player script), and then have the shield script keep the shield capacity and decreases every time it collides. When it reaches 0, you destroy the shield game object instance.
Doesn't that sound a lot easier?
(Maybe your question is about moving the shield with your space ship... you can attach it to the space ship by using shield.transform.SetParent(spaceShip.transform);
).
That sound much easier! Thanks a lot!
I'll try it out soon!
Hi, thanks for your hints. The problem with the new Instances of the shield is solved. I also changed the precondition that I need a boolean. Works fine!
$$anonymous$$y "new"/old problem is still, that when the shields get activated it isn't moving.
Could you maybe give me some more information how I can handle your code?
Harinezumi shield.transform.SetParent(spaceShip.transform);
I tried it to implement it in the class for the Shield and also for the Player. But my problem is, that the Player isn't a Gameobject in my Player-Script. It is just in the Hierarchy.
$$anonymous$$y code was _shieldPrefab.transform.setParent(xyz.transform)
xyz should stands for the Player/Spaceship, but I can't access it. So do I have to I have to declare the Player as an Prefab too?
THX in advance.
Look you would make our job way easier when you would have shown your actual instantiate code in your question. What is "_shieldPrefab"? If it's the actual reference to the prefab, of course this line doesn't work. A prefab is not part of the scene. When you Instantiate a prefab you actually create a concrete object in the scene based on the prefab. The Instantiate method returns that new instance. You have to parent that new instance to your player, not the prefab itself.
Answer by wbreaker79 · Apr 21, 2018 at 12:45 PM
Bunny83
Hi, thanks for your advise to show the instantiate code. So, here it comes.
When the Player collide with the PowerUp for the shield, I call the class PowerUp.
public class PowerUp : MonoBehaviour {
[SerializeField]
private float _speed = 2.0f;
[SerializeField]
private int _powerupID;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update ()
{
transform.Translate(Vector3.down * _speed * Time.deltaTime);
if (transform.position.y < -5.8)
{
Destroy(this.gameObject);
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
Player player = other.GetComponent<Player>();
if (player != null)
{
if (_powerupID == 2)
{
player.ShieldPowerUpOn();
}
}
Destroy(this.gameObject);
}
}
}
The PowerUp Class calls the method ShieldPowerUpOn in the player class:
public class Player : MonoBehaviour
{
//Shield
public float shieldCooldown = 10.0f;
public bool shield = false;
[SerializeField]
private GameObject _shieldPrefab;
[SerializeField]
private float speed;
// Use this for initialization
void Start ()
{
transform.position = new Vector3(0, 0, 0);
}
// Update is called once per frame
void Update()
{
}
private void Shield()
{
Instantiate(_shieldPrefab, transform.position, Quaternion.identity);
Debug.Log("Shield on");
}
//Shield
public void ShieldPowerUpOn()
{
Shield();
}
}
I also have a shield-Method with should control how often the shield was hit. This class is connected with the ShieldPrefab.
public class Shield : MonoBehaviour {
[SerializeField]
private float _shieldCapacity = 3.0f;
[SerializeField]
private GameObject _shieldPrefab;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
if (_shieldCapacity <= 0.0f)
{
Destroy(this.gameObject);
}
}
}
I guess, my problem is (if I am correct) that I don't have the behaviour of the shield in any Update-Method. But I don't know I can handle that. Maybe you have a solution for that?
Hope it is now better to understand with the code. Sorry again.
Thanks in advance!
Greets!
Thanks for sharing the code, however, I am quite confused now what the problem is.
The original question is about the shield capacity not changing - that should be resolved by not instantiating a new shield. Then in the comment you mention that the shield is not moving with the spaceship - but in the code you shared you instantiate the shield as a child of Player script (if you specify a transform as the second parameter of Instantiate()
it will be created as a child), so now it must move (maybe it is not exactly on it - that can be solved by setting its transform.localPosition
to Vector3.zero
).
So what is not working at the moment?
Also, you say that "the Player isn't a Gameobject in my Player-Script. It is just in the Hierarchy", which is very confusing. Isn't the Player script attached to a game object that represents the spaceship? Based on the latest code, it should be, otherwise you would not be able to get the Player component in the collision handling of the PowerUp script. If this is still relevant to the problem, please clarify this.
Sorry for confusing! You are right, my first question about the capacity of the shield was answered. Thanks for that! But not the second one. :( If I understand you right, the shield should be moving with the space ship now? I was thinking that it have to work too, but unfortunately it isn't working. The shield is getting activated, but it doesn't move an inch. It stands still on the position where the space ship is colliding with the PowerUp. So my problem is: the shield isn't still moving. $$anonymous$$y words about "the Player isn't a Gameobject in my Player-Script" is wrong I guess. I want to say, that the ship is not a Prefab. The Player Script is attached to a Gameobject in the Hierarchy. I am really sorry about confusing you all!Harinezumi
Hey, no worries, at least now it's clear.
The solution is fortunately simple: assign the parent transform of the shield instance when it is created, either by using SetParent()
or using a version of Instantiate
that has a parent
parameter (see here).
For example:
private void Shield () {
Instantaite (_shieldPrefab, transform); // this will create the shield exactly where the Player script's game object is (hopefully, that is the spaceship, but with the same rotation as well (which may not be what you want)
// this is the same as above, but in 2 steps
GameObject shield = Instantiate (_shieldPrefab, transform.position, Quaternion.identity);
shield.transform.SetParent(transform);
}
Your answer
Follow this Question
Related Questions
Detect if build target is installed 1 Answer
How do I solve a BuildAssetBundles Compilation Error that only occurs in the Editor? 1 Answer
Arrays/Lists in the inspector of Editor Extension scripts 0 Answers
There is no GameObject attached to this GameObject 2 Answers
Editor Scripting - Add Component if certain Tag is selected 0 Answers