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\$
0

2 Answers 2

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.

\$\endgroup\$
9
  • 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\$ Commented Nov 11, 2017 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\$ Commented Nov 11, 2017 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\$ Commented Nov 11, 2017 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\$ Commented Nov 11, 2017 at 15:53
  • 1
    \$\begingroup\$ Does that make a bit of sense? \$\endgroup\$ Commented Nov 11, 2017 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.

\$\endgroup\$
8
  • 2
    \$\begingroup\$ I was just about to put up an answer that was practically the same thing. \$\endgroup\$ Commented Nov 10, 2017 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\$ Commented Nov 11, 2017 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\$ Commented Nov 11, 2017 at 1:02
  • 1
    \$\begingroup\$ @SuperMegaBroBro I can't say I understand that. May you elaborate? \$\endgroup\$ Commented Nov 11, 2017 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\$ Commented Nov 11, 2017 at 15:40

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.