0
\$\begingroup\$

I haven't been at my computer learning code or game dev in a few months and am just starting again. I am trying to make a game very similar to Asteroids. In 3d but fixed camera from above so basically disregarding the Y Axis at the moment.

I have everything working fine so far such as the rocket stays in middle and can rotate, and fire weapon. The Asteroids for now all come from the top side of the screen, and have some code to randomise the X location and speeds.

When the laser hits the Asteroid I want it to destroy that Asteroid and create two more that are half the size and with a Rotation added of 45/-45 degrees.

I have the code that I thought would work but it is only creating one more and not two. (note: as you'll see I have tried making tempAsteroid2 and even asteroidPrefab2, before this I just had the one which I tried to instantiate twice).

What am I missing? why does this code not make two more appear upon laser collision??

Any help massively appreciated as always. Many thanks:

public class Asteroid : MonoBehaviour {
float speed;
public GameObject asteroidPrefab, asteroidPrefab2;
public int sizeKey = 2;
// Use this for initialization
void Start () {
    if (sizeKey < 1)
    {
        Destroy(this.gameObject);
    }
    transform.position.Set(transform.position.x, 0f, transform.position.y);
    speed = Random.Range(0.5f, 2f);
}

// Update is called once per frame
void Update () {
    GetComponent<Rigidbody>().transform.Translate(Vector3.forward * speed * Time.deltaTime);
}

private void OnTriggerEnter(Collider other)
{
    if (other.tag == "Laser")
    {
        BreakAsteroidInHalf();
        Destroy(other.gameObject);
    }
}

void BreakAsteroidInHalf()
{
    GameObject tempAsteroid = asteroidPrefab;
    tempAsteroid.transform.position = transform.position;
    tempAsteroid.transform.Rotate(0, -45, 0);
    tempAsteroid.transform.localScale *= 0.5f;
    tempAsteroid.GetComponent<Asteroid>().sizeKey -= 1;
    Instantiate(tempAsteroid);
    GameObject tempAsteroid2 = asteroidPrefab2;
    tempAsteroid2.transform.position = transform.position;
    tempAsteroid2.transform.Rotate(0, 45, 0);
    tempAsteroid2.transform.localScale *= 0.5f;
    tempAsteroid2.GetComponent<Asteroid>().sizeKey -= 1;
    Instantiate(tempAsteroid2);
    Destroy(this.gameObject);
    Debug.Log("Asteroid destroyed and replaced by 2 more");

}
\$\endgroup\$
2
\$\begingroup\$

It's important to remember that C# is an Object Oriented Programming language. As such, this is a bad example of how to use it.

Instead of the current solution, try using:

void BreakAsteroidsInHalf() {
float rot = 45;
for(int i = 0; i < 2; i++){
GameObject asteroid = Instantiate(asteroid, transform.position, transform.rotation) as GameObject;
asteroid.transform.localScale(0.5,0.5,1);
asteroid.transform.Rotate(0, rot,0);
asteroid.GetComponent<Asteroid>().sizeKey -= 1;
rot -= 90; // If you increase you "i" limit, this will allow you asteroids 
rotate at different degrees.
     }  
Destroy(gameObject);
} 

This keeps your code succinct, readable, and most importantly, object oriented.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ I like this solution. It is definitely more of a clean way of doing this. I never would have thought to loop the code for creating new objects, instead of simply writing it twice! \$\endgroup\$ – The Mattbat999 Nov 11 '17 at 3:52
  • 1
    \$\begingroup\$ @SuperMegaBroBro Absolutely. So essentially OOP requires that you use and reuse classes and objects as much as possible. That means reasonable functions, parameters, constructors, destructors etc to allow for a single "parent" object to be used in many different ways. So while what you were doing isn't "wrong" what you've effectively done is try to make the same object twice by writing identical conditions. Why try to replicate the same object, when you could literally create fewer lines of code that allow an exact clone to be made, but be created in a different environment or have a ... \$\endgroup\$ – cmprogram Nov 11 '17 at 15:50
  • 1
    \$\begingroup\$ ... different purpose. Think of it like creating two humans. The two humans have entirely different goals and things they prioritise, they have different people they care for etc, but regardless, they are humans. Meaning they have eyes, ears, hearts, lungs etc. So instead of many lines of code, writing what a human is, and then rewriting that code to define human 2 and making them roughly similar, we just write a human class and control the parameters we send at the creation of the object (human) \$\endgroup\$ – cmprogram Nov 11 '17 at 15:52
  • 1
    \$\begingroup\$ E.g. createHuman(goals, priority){ //blah } The for loop is equally just a nice touch as in keeping with these rules, it allows you to change one number and the code will still run perfectly well, but the overall outcome will be slightly different. (Three asteroids instead of two etc) \$\endgroup\$ – cmprogram Nov 11 '17 at 15:53
  • 1
    \$\begingroup\$ Does that make a bit of sense? \$\endgroup\$ – cmprogram Nov 11 '17 at 15:54
2
\$\begingroup\$
void BreakAsteroidInHalf()
{
    GameObject tempAsteroid = Instantiate(asteroidPrefab);
    tempAsteroid.transform.position = transform.position;
    tempAsteroid.transform.Rotate(0, -45, 0);
    tempAsteroid.transform.localScale *= 0.5f;
    tempAsteroid.GetComponent<Asteroid>().sizeKey -= 1;

    GameObject tempAsteroid2 = Instantiate(asteroidPrefab2);
    tempAsteroid2.transform.position = transform.position;
    tempAsteroid2.transform.Rotate(0, 45, 0);
    tempAsteroid2.transform.localScale *= 0.5f;
    tempAsteroid2.GetComponent<Asteroid>().sizeKey -= 1;

    Destroy(this.gameObject);
    Debug.Log("Asteroid destroyed and replaced by 2 more");
}

Explanation:

Actually, you still have 2 copies, but they have identical transforms.

In your code, you are modifying the prefab here:

GameObject tempAsteroid = asteroidPrefab;             //tempAsteroid is the prefab right now, not an instance in the scene
tempAsteroid.transform.position = transform.position; //modifying prefab
tempAsteroid.transform.Rotate(0, -45, 0);             //modifying prefab
tempAsteroid.transform.localScale *= 0.5f;            //modifying prefab
tempAsteroid.GetComponent<Asteroid>().sizeKey -= 1;   //modifying prefab
Instantiate(tempAsteroid);                            //creating an instance

The problem with this approach is, when you are using a prefab as the original object, Instantiate function will wipe the transform values of the top transform in the hierarchy of prefab, right after the creation of a new instance. So all of your previous modifications to prefab will be replaced by some other values on the new instance.

So instead, we first need to instantiate and then modify the instance on the scene.

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ I was just about to put up an answer that was practically the same thing. \$\endgroup\$ – The Mattbat999 Nov 10 '17 at 23:23
  • \$\begingroup\$ thank you so much guys. So I just need to make a container for each of the two possible new objects, and instantiate it prior to setting any parameters such as position, rotation etc. I'll give this a try now. Thanks again. \$\endgroup\$ – Big T Larrity Nov 11 '17 at 1:00
  • \$\begingroup\$ Just to make sure i understand.... Would this be ok: private GameObject newAsteroid1, newAsteroid2; (as declarations) , then instead of using tempAsteroid just use them directly like that?? \$\endgroup\$ – Big T Larrity Nov 11 '17 at 1:02
  • 1
    \$\begingroup\$ @SuperMegaBroBro I can't say I understand that. May you elaborate? \$\endgroup\$ – S. Tarık Çetin Nov 11 '17 at 11:22
  • \$\begingroup\$ hi mate, what I was trying to say was . was the problem that I was Instantiating the same copy of asteroidPrefab? and if so, would a solution be to create two variables called newAsteroid1 and newAsteroid2 and then Instantiate them both at the StartI() and then I can just re-set them to the position etc upon Laser collision? - its hard to explain so I will attempt it and then edit the code but I cant get back to it for about another hour . \$\endgroup\$ – Big T Larrity Nov 11 '17 at 15:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.