Instantiate bullet shells wrong rotation

Hello all. I’ve tried to research this issue but haven’t found anything specific. So the problem I’m having is that I have a weapon that ejects bullet shells. I’ve scripted it using this:

clone.velocity = transform.TransformDirection(Vector3.right * projectilePower);

I use that because I have an empty game object as the “ejector” that has the x axis pointing towards the right which is where the bullets eject towards. I created a bullet prefab from a cylinder to test it out, but every single time the bullets eject facing up and down. I rotated the bullet prefab but it continues to do it. I created an empty game object to hold the bullet as a child object and made that the prefab but then the bullets just instantiate and fall straight to the ground with no force being applied to them. It seems like I can either get it to forcefully eject bullets, or have the correct rotation. How do I fix this? I was able to get it right last time but have no clue why it worked. When I exported the “ejector” from the project that I was able to get it to work, it still does the same thing with my new project. It’s really annoying. Someone please give me some guidance here. I’ve attached a video of the issue.

http://xenosmash.com/wp-content/uploads/2013/06/wrongRotation.mp4

Could you post the code that instantiates the projectile prefab? The issue is most likely the rotation you specified when you called Instantiate.

One way to fix that would be to use Quaternion.Euler(transform.TransformDirection(Vector3.right)) or transform.right. Try it out and let us know how it works. :slight_smile:

That is my full script, I was playing around with it today to instantiate objects with the button held down but that’s about all I’ve changed. Like I mentioned before this seems to work just fine in another project, but when I tried to recreate it in new project I get this issue. I had this issue before with the previous project, going back and forth and suddenly it just started working. Thanks for the help!

Also just so I understand, the clone.velocity = transform.TransformDirection(Vector3.right * projectilePower); section is referring to the rotation of the actual projectile correct?

clone.velocity is referencing the rigidbody on clone and setting the velocity (how fast the object is moving), which is the object you instantiated. Rigidbody is the physics component. Transform is the component that handles the location, rotation, and scale.

Here’s the parameters for Object.Instantiate:
Instantiate(GameObject prefab, Vector3 position, Quaternion rotation)
The prefab and position parameters are self-explanatory, so I won’t go into those. Rotation is the rotation of the object, rotated along the x-axis, then y, then z. Quaternions use 4 dimensions, however, x, y, z, and w, which you shouldn’t change on their own according to the script reference. Supposedly they’re less memory-intensive than Euler angles (x,y,z), but I don’t understand or hope to understand why. The identity rotation (0, 0, 0) has the forward (+Z, Blue) axis of the object along the +Z axis of the world. If you’re using the rotation of the spawner object as the base rotation, then +Z of the Instantiated object will match the +Z of the spawner. If you’re moving the object along the +X (Right, Red) axis of the spawner and you want the Instantiated object’s forward vector to match the direction of it’s velocity, you could use [clone.forward = clone.velocity;], minus brackets, which will match the Instantiated object’s forward vector to the velocity vector.

What you’re doing in a step-by-step format (Code in Green):

  1. Code instantiates (Instantiate() projectile (projectile) at the current position (transform.position) and rotation (transform.rotation))
  2. Code sets the new object’s velocity (clone.velocity) to value V along the x-axis of the current object (= V*transform.right)Note that the x-axis of clone is the same as the x-axis of the object with the script on it! You will thus be moving the projectile right relative to the projectile’s forward axis.

What you want to be doing:

  1. Code instantiates projectile… blah blah blah
  2. Code sets the instantiated projectile’s forward vector (clone.forward) to be equal to the right vector of the object with the script (= transform.right)
  3. Code sets the projectile’s velocity (clone.velocity) to value V along the x-axis of this object (= V * transform.right)Note that this does not move the projectile right, as you might think, but it moves the object right relative to this object, which, due to step 2, is forward relative to the projectile.

You could also do this when instantiating the projectile: clone = Instantiate(projectile, transform.position, Quaternion.Euler(transform.right))Why do this? This does steps one and two in “What you want to be doing” in a single step: it creates the new projectile and correctly orients it so that it will appear to be moving forward.

And actually, var clone: Rigidbody; is not a variable within a variable, it is identifying the type of the variable “clone.” If you didn’t do this, “clone” could be a Transform, a Collider, or anything. By stating clone: Rigidbody; you are making sure that “clone” will be a rigidbody, requiring you to reference other objects as rigidbodies before you can assign them to “clone.”

Thanks for the info. I’ll try to include it all within the instantiate line and see if that helps. I understand how it all works for the most part, but it’s just driving me nuts because it was working just fine before and now it’s not. Oh and by the “variable within a variable” that was mostly me saying “we’re going to include our projectile variable within the clone variable on the next line”. So essentially we’re including a variable within a variable.

Also I’m a bit confused. Does the Instantiate line determine how the projectile will come out? I mean is that where I will look to make changes to the rotation of the actual projectile? For some reason I thought it was the velocity line, but it makes more sense that it’s just adding a force “right” to the relative position of the empty game object.

So under Instantiate(projectile, transform.position, transform.rotation); I would change the transform.rotation so that my projectile (bulletShell) is properly rotated the way I want correct? Couldn’t I keep it the way it is and just try to rotate the actual bulletShell prefab? I tried using local and global but it didn’t seem to matter, it still shot out the same orientation (up and down). Thanks for the help!

If you have the mesh set as a child of the main prefab object, then yes, you can rotate the mesh inside of the prefab so that it is oriented correctly.

Instantiate will ignore the transform.position and transform.rotation variables in the prefab and set them to the ones you define in the call to Instantiate. Changing transform.rotation will change the rotation of the prefab when it is created, so using Quaternion.identity will create a new instance of the prefab with rotation (0, 0, 0), while using transform.rotation will create the prefab with rotation (transform.rotation) (for example, if transform.rotation = (12, 45, 0) then the prefab will be created with rotation (12, 45, 0)).

Setting clone.forward (or clone.up in your case, from what it sounds like) to transform.right will change the rotation of the prefab from, say, (0, 0, 0) to (-78, 45, 0) or whatever the correct rotation is. An easier, more accurate way to say this is changing the vector of the long axis of the bullet from (0, 1, 0) to the unit version of (12, 45, 0). Unit version means that the magnitude of the vector is equal to 1.

Depending on the orientation of the bullet prefab, you may want to use either the first or the second method. The first is good for things that are all lined up on the same axis (so +Z to +Zlocal) while the second is good for things that aren’t (+Y to +Xlocal). I can work on some graphics for visualizing the concept better.

For now, try adding clone.up or whatever vector is the long axis of the bullet = transform.right; underneath the Instantiation but before you set the velocity of “clone.” Seeing it in action should help you understand it better. :slight_smile: