2
\$\begingroup\$

I'm developing a demo of a 3D Space Ship game concept in Unity, just for learning purposes.

I have a cube representing my space ship in the scene, and a laser prefab that is instantiated at the 2 sides of the space ship any time the user presses the spacebar, i use this C# code (placed in the script attached to the space ship, just a cube right now) to calculate the position of the lasers and instantiate them:

Vector3 laser1Position = 
    this.transform.position + this.transform.forward + this.transform.right;
Vector3 laser2Position = 
    this.transform.position + this.transform.forward - this.transform.right;

Instantiate (laser, laser1Position, this.transform.rotation);
Instantiate (laser, laser2Position, this.transform.rotation);

At this point, everything worked perfect, and the lasers are instantiated correctly at the sides of the cube, exactly at the middle of the 2 sides.

The problem came yesterday, when i replaced the cube by a real space ship model, a simple design made by my brother in Blender, and attached the same script my cube had, the lasers are instantiated very above from the space ship, producing the effect seen in the next image, the lasers are spawned at the red line i drew just for showing purposes, when i need them to be instantiated at the green line:

Space ship model firing lasers

Here you can see the space ship model vs the cube, both firing lasers: Space ship vs Cube

We designed the space ship model in blender, in the origin of coordinates, without any other objects or light sources, so my doubts are:

  1. Why are the lasers spawned that high if the model is not there? Is really the model bigger than i see in the editor? (The green box is a box collider i added for collisions managing) Ship at design time
  2. Should we configure or touch something in the Blender project to stablish the real size or axis of the model when we import it?
  3. Is there a better method of calculate where the lasers should be spawned that this one i am using? Imagine that i want to spawn them in the point of the wings, in front of them. Is there any marker or method i could use to easily spot the place where the lasers should be spawned at runtime? Instead of manual calculating it or by test-error.

I don't have the model here right now, if you need it please let me know and i will try to upload it to somewhere later.

Thank you so much for your help!

\$\endgroup\$
0
\$\begingroup\$

Verify in Blender that the center of the object is, in fact, at or near the center of the mesh. Just modeling at the origin means nothing. The center of the object will be, as I recall, an orange dot. Since your one-over and one-forward isn't spawning where you think it is, the center of your object isn't where you think it is.

There are better ways to do this, though (the two I'll suggest both boil down to the same thing). B is how I prefer to do it, though there are doubtless many ways:

A) The first is to add a rig (i.e. bones) to the model in blender. One will need to be the root. Add two more at the appropriate points, the wing tips, pointing forward with the model. When the model is imported into Unity those bones will be gameObjects. You can name them (the bones in blender) and find them using any method you care to and simply spawn at their location, with their orientation.

B) Similar but simpler, after you import the model add some empty game objects as children and position them where you want the laser bolts to spawn (correct position and facing). Then make a prefab out of this, and use it. You then find those objects and spawn on their location/orientation (by name, or by tag or any other method you choose).

As a suggestion, you'll probably want the prefab to be an empty game object with the model and laser markers as children. If you add all this under the model you may lose them if you re-import the model file. As long as they are all positioned relatively, there is no reason for anything to be an actual child of the mesh-containing objects.

Both approaches result in the same thing. The second just avoids messing around with bones in Blender, which is trickier than adding a few gameObjects in the Unity editor.

You might also consider creating a 'laser spawner prefab', an empty gameObject with a script to spawn your laser bolt at

GameObject.Instantiate (laser, transform.Position,transform.Rotation);

Then you'd apply those prefabs to your model-prefab. Then you could reuse these on any other model as well, though you'd need some method of sending fire messages to them.

\$\endgroup\$
  • \$\begingroup\$ Your idea of creating an empty GameObject to act as Spawner is just brilliant! That's much more accurate than the method i mentioned and just what i needed, thank you so much. I marked yours as the answer, but i'm going to post another answer too to explain in detail how i follow your solution. \$\endgroup\$ – IsaacRF Mar 16 '15 at 21:58
0
\$\begingroup\$

I followed the answer of DrHeinous and used spawners for the lasers, and now it works just great and i can mark exactly where i want the lasers to be spawned.

These are the steps i followed:

  1. Created an empty GameObject and called it laserSpawner, dragged it to my prefabs folder and attached a C# script called "LaserSpawnerBehaviour" with this code:
using UnityEngine;
using System.Collections;

public class LaserSpawnerBehaviour : MonoBehaviour {

    //This will referenciate the laser prefab
    public Transform laser;

    // Use this for initialization
    void Start () {

    }

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

    }

    //Fires a laser at the Spawner position
    public void fire()
    {       
        Instantiate (laser, this.transform.position, this.transform.rotation);
    }
}
  1. Attach the laser prefab to the script public variable "laser", so it can be instantiated Drag the laser prefab here
  2. Dragged the laserSpawner prefab i just created as my ship GameObject child, you can place it wherever you want in the designer: Placing laser spawners
  3. Created a public Transform variable in my Ship script called "LaserSpawnerFront", and dragged the LaserSpawnerFront child of my ship to it: Creating laser spawners in the ship
  4. In the Update() method of my Ship Script, when the spacebar is pressed and the timing allows it, i get the LaserSpawnerBehaviour Script from the Transform and i call the fire() method:
if (Input.GetKey (KeyCode.Space) && Time.time > nextLaserTime) 
{
    //Fire lasers using Laser Spawners
    laserSpawnerFront.GetComponent<LaserSpawnerBehaviour>().fire();
}

Now the laser is spawned at the exact position i choosed placing the LaserSpawner: enter image description here

\$\endgroup\$

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.