- Home /
Instantiating a bullet object from a 2D object that looks at mouse cursor
Hi, I have a 2D object that continuously looks at the mouse cursor. I am using an overheard view. Here is the code that I used for this:
Vector3 screen_pos = Camera.main.ScreenToWorldPoint (new Vector3 (mouse_pos.x, mouse_pos.y, 0));
transform.LookAt ( screen_pos, Vector3.forward);
Before I changed to using the mouse cursor I was just using left/right arrow keys to rotate the object and I was able to instantiate bullet objects using this code:
Instantiate (BulletPrefab, transform.localPosition+(transform.up *.5f)+(transform.right*-.3f) , transform.localRotation); // bullet instantiates from front right
The above code worked fine before but now with the mouse cursor code added in, the bullets move in random directions and sometimes instantiate in the wrong position.
Thanks.
Answer by equus_ligneus · Apr 11, 2015 at 12:01 PM
You are currently placing your bullet with hard-coded offset. Try this instead:
// get the vector from current pos to mouse (you have to cache your screen_pos)
Vector3 direction = (screen_pos - transform.position).normalized;
// Instantiate your bullet with 0.5 units offset to your position and your rotation
Instantiate(BulletPrefab, transform.position + direction * 0.5f, transform.rotation);
This code will crash at .normalized if your cursor's position equals your 2D-object's position because normalize will divide by the length of (screen_pos - transform.position) which, in that case, is zero.
To circumvent annoying bugs (bullet flies at camera...) with this system make sure to have the z-value of both screen_pos and transform.position aligned:
Vector3 screen_pos = Camera.main.ScreenToWorldPoint (new Vector3 (mouse_pos.x, mouse_pos.y, 0));
screen_pos.z = transform.position.z;
Ok, so it appears the bullet will start from the correct position but the bullet will still go in random directions. Now in the bullet class I have the code.
rigidbody2D.AddForce ( transform.up * speed);
Do I need to get the direction from the spaceship object (object shooting the bullet) and use that in the AddForce method of the bullet class in place of transform.up ?
Also, when I use the line screen_pos.z = transform.position.z;
for some reason the spaceship object disappears.
Yes, you need to use the direction from your spaceship. $$anonymous$$aybe create a method like this in your Bullet script:
public void SetDirection(Vector3 _direction)
{
GetComponent<Rigidbody2D>().velocity = _direction * speed;
}
(If you want to set the speed, do it directly :)) Then call it from your spaceship after initialization:
// ...
// Instantiate your bullet with 0.5 units offset to your position and your rotation
GameObject go = Instantiate(BulletPrefab, transform.position + direction * 0.5f - Vector3.forward * 0.1f, transform.rotation) as GameObject;
// Assu$$anonymous$$g the bullet class is Bullet
go.GetComponent<Bullet>().SetDirection(direction);
As for your problem with the disappearing bullets: $$anonymous$$aybe they were created behind your spaceship. I added an offset of 0.1 units towards the camera in the instantiate part. It should fix the problem if z-order was the issue.
Ok, so now the bullets shoot in the correct direction. However, the bullets are not moving with the front of the bullet towards the direction they are moving (sometimes they are diagonal, backwards, forward depending on direction).
Also, the spaceship is still invisible. I also noticed that when the spaceship is hidden I cannot move the spaceship up/down/sideways with the keys like I can when the spaceship is visible.
About the space ship: The problems lies at your LookAt call... For performance reasons backsides (or insides) of objects do not get rendered. By calling LookAt and setting Vector3.forward as the normal vector of the plane that is your spaceship, you turn the plane so that it faces away from the camera, thus the camera can't see it. Use -Vector3.forward as second parameter in your LookAt call.
As for your bullet rotation: I can't say what happens without you providing footage, especially with the rotation of your space ship being messed up.
Answer by Tomer-Barkan · Apr 14, 2015 at 07:59 PM
You're using transform.position + transform.up. transform.up is relative to the object, so when you rotate it with LookAt, the up direction changes as well. If you want it to be always on top of the object, regardless of where the object is facing, you can use Vector3.up instead.
If this is not what you want, you better explain yourself better, and a screenshot or schematic will help.
Answer by stockhouse50 · Apr 18, 2015 at 08:35 PM
Ok, I am willing to start from scratch on this rotation idea so if that means using an alternative to lookAt() I'm fine with that. I attached a schematic and I will try to explain it in further detail. The game is 2D with an overhead/birds eye view of the spaceship. Basically wherever the mouse cursor moves on the screen, I want the spaceship to rotate only around the z-axis ( basically if a rod came out from the screen, it would rotate around that as shown in the schematic.) and have the front facing towards the mouse cursor.
So in the schematic pretend the arrow is the cursor and the front is always facing the cursor. The green triangles in the schematic are the bullets. When the bullets are instantiated, the front of the bullet is in the same direction as the spaceship.
If I explained anything poorly or used wrong terminology please correct me because I am trying to learn the lingo along the way. Thanks.
Answer by stockhouse50 · Apr 19, 2015 at 12:31 PM
Alright finally after all my searching I found the answer. The solution I found doesn't use lookat() but does the job.
Vector3 diff = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
diff.Normalize();
float rot_z = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, rot_z - 90);