- Home /
How to rotate an instance relative to the parent and give it force?
I have a GameObject that rotates itself and has 4 guns that are children, I created the empty GameObject at the end of every gun and I would like to instantiate the bullet prefab the way the gun is rotated and give them force to go to that direction Here is how the game looks: https://imgur.com/a/qpIEuRk And this is my script to spawn, but don’t know how to give force:
public GameObject bullet;
public Transform gun;
public float time;
void Spawn()
{
Instantiate(bullet, transform.position, gun.transform.rotation);
}
void Start()
{
Invoke("Spawn", time);
}
Answer by Ermiq · Jun 30, 2018 at 07:32 PM
You need to change bullet's position in Update(). For example you could do this:
Change your instantiate code:
//Make an array to store all instantiated bullets.
// we'll need this to move each bullet in it's own direction later
private ArrayList bullets = new ArrayList ();
private void Spawn()
{
//Store instantiated bullet as local variable 'clone'
GameObject clone = Instantiate (bullet, transform.position, gun.transform.rotation);
//Add bullet to the list
bullets.Add (clone);
//Call delayed method to delete bullet which is first in the bullets array
// we need it to prevent performance issues when there's too much bullets in the scene
// so we're adding 1 new bullet and deleting 1 old bullet
Invoke ("DestroyBullet", 2f); //bullet will be destroyed in 2 seconds
}
private void DestroyBullet ()
{
GameObject bulletToDestroy = bullets[0] as GameObject; //very first bullet in the array
bullets.RemoveAt (0); //remove bullet from the array
Destroy (bulletToDestroy); //destroy bullet's gameObject itself
}
Now in Update() you'll change each bullet's position:
void Update ()
{
//Moving every bullet in the array relative to it's position and direction
for (int i = 0; i < bullets.Count; i++) {
GameObject bullet = bullets [i] as GameObject;
bullet.transform.position =
bullet.transform.position + bullet.transform.forward * Time.deltaTime;
//Time.deltaTime here
//is a multiplier for move speed. Now bullet will move for 1 meter per second.
}
}
The Rotator (big black dot with 4 guns) moves around scene and rotates at the same time, with your code, this is the result: https://imgur.com/a/Fw3fFx1 ;
So I changed a part of your code:
//GameObject clone = Instantiate(bullet, transform.position, gun.transform.rotation); GameObject clone = Instantiate(bullet); //Instantiate the bullet clone.transform.rotation = transform.parent.rotation; //Set the rotation of the clone to the rotation of the parent (gun)
And this is the result: https://imgur.com/a/9uCQ5ls
But none of the solutions has the velocity or force, the bullet just stays where it spawns and destroys after two second
Ok, let's figure out who is who in your project. Rotator is the big dot. Guns are children of the Rotator, right? And these guns have empty game objects as children attached to edges of the guns, right? So hierarchy of Rotator in editor looks like this:
R-> Gun1 -->Gun edge1 (empty game object) -> Gun2 -->GunEdge2 (empty) -> Gun3 -->GunEdge3 ->Gun4 -->GunEdge4 Right? If the script is attached to the Rotator then 'transform' will return the Rotator's transform, so when you write clone.transform.rotation = transform.parent.rotation; you're applying Rotator's parent rotation to the bullet. It's not good. To make it work correctly, you should check GunEdge's positions and directions in editor, their blue arrows (Z axis) should point to the direction away from the Rotator. These arrows represent their 'transform.forward' vectors which you need to apply direction for bullets to go to. And when you instantiate a bullet you should set its position to GunEdge's position, and rotation to GunEdge's rotation. Hmm... Looks like we need to deter$$anonymous$$e at which GunEdge the bullet going to be instantiated as well. But at first, we need to make it work with one of the guns at least. $$anonymous$$ake a public variable of type Transform in your script, name it 'GunEdge', attach the script to the Rotator, drag and drop one of your GunEdge empty objects on this variable field in the inspector window. $$anonymous$$ake sure this gun edge has a proper direction (blue Z axis points away from the Rotator's center). Then try to instantiate a bullet with: GameObject clone = Instantiate (bullet, GunEdge.position, GunEdge.rotation);otator
The script is attached to the empty gameobject at the end of the gun and spawns the bullet just perfect, here is the screenshot: https://imgur.com/a/v4Iv4$$anonymous$$S
Bullets are at the position where the guns where a couple of frames before, I can't screenshot with perfect ti$$anonymous$$g but it works, it works with this script:
GameObject clone = Instantiate(bullet); //clone has the value of instantiating the bullet
clone.transform.rotation = transform.parent.rotation; //Set the value of clone rotation to the rotation of it's parent (gun)
Now it's just the force we need, if transform.forward is used, most probably it wouldn't work as it would affect the Z axis, my game is 2D, so we need X, Y only
@Cuki Oh, sorry, I completely forgot it's a 2D. In 2D you need to use 'transform.up' or 'transform.right' to move object at its X or Y axis. In 2D 'Transform.forward' moves object in camera direction so it seems like it's not moving. In Update() code try to use
bullet.transform.position = bullet.transform.position +
bullet.transform.up * 1f * Time.deltaTime;
or
bullet.transform.position = bullet.transform.position +
bullet.transform.right * 1f * Time.deltaTime;
You can change '1f' multiplier to any value to get moving speed you want.
It works now, thanks a lot, however I changed spawning with a rotation a bit, yours was correct, but I did it with no gun this time, I used parent ins$$anonymous$$d, last time it was really a prototype with weird dimension sprites so maybe that's why it didn't work correctly but now I changed them. This is the final code: public Rigidbody2D bullet; public float time; public float speed;
void Start()
{
Invoke("Spawn", time);
}
void Update()
{
bullet.transform.position += bullet.transform.up * speed * Time.deltaTime;
}
void Spawn()
{
bullet = Instantiate(bullet, transform.position, transform.parent.rotation);
Invoke("DestroyBullet", 3f);
}
private void DestroyBullet()
{
Destroy(this.bullet);
}
This is only one bullet per script, the prototype was the most important, upgrading the script for multiple bullets should be easier now and since it was just a prototype, I came up with few more ideas about the core mechanics of the game so maybe there even won't be multiple bullets