- Home /
How to spawn a prefab in a cone in front of player?
I am making a game when the player is constantly moving up the screen. I want to create an enemy player a specific distance in front of the player, at a random angle from where the player is currently facing (a 45 degree cone). I thought this would be easy to do, but I am really struggling.
I can create the prefab directly in front of the player (2d like game) with the following:
obj = Instantiate(meteorSmall, pos + ship.transform.up * spawnDistance, Quaternion.identity);
This however doesn't allow me to specify an offset front the player. I have also tried using the Mathf.sin and Mathf.cos functions but again I just can't seem to make it work.
Any ideas?
Answer by Owen-Reynolds · Sep 19, 2012 at 08:16 PM
Idea here is that we are facing `transform.rotation,` so combine that with a local random +/-45 to get the new angle, then "shoot" that way to get final position. Not tested, but the general idea has been used a lot:
// random left/right +/-45 Y angle:
Quaternion randAng = Quaternion.Euler(0, Random.Range(-45,45), 0);
// NOTE: this is 45 left/right from due north
// combine +/-45 with our current facing, to get +/-45 FROM US:
randAng = transform.rotation * randAng; // this might be backwards
// use that angle to get a distance from us:
Vector3 spawnPos = transform.position + randAng * Vector3.forward * 15;
It takes a while to get used to how times(*) combines to rotations, and also applies a rotation to a Vector. Then trying to remember if you want it on local or global axis. Can use Sin/Cos, but quaternions do all that math for you.
Brilliant. That did the trick. $$anonymous$$any thanks.
Answer by AlucardJay · Sep 19, 2012 at 08:19 PM
This should work. Create an empty gameObject called SpawnPoint, make it a child of the ship, place it at Transform(0, 0, 1) to the ship, then move that around with RotateAround, then use it's position as the spawn point :
function SpawnObject()
{
spawnPoint.localPosition = transform.forward * spawnDistance;
spawnPoint.RotateAround( ship.transform.position, ship.transform.up, Random.Range( -45.0, 45.0 ) );
spawnPoint.RotateAround( ship.transform.position, ship.transform.right , Random.Range( -45.0, 45.0 ) );
var obj : Transform = Instantiate( meteorSmall, spawnPoint.position, Quaternion.identity );
}
http://docs.unity3d.com/Documentation/ScriptReference/Transform.RotateAround.html
Think line#1 should be `SP.localPosition=transform.forward*spawnDist;` (and leave out the spawn dist at the end.)
Otherwise SP is placed near the origin, rotates in a huge arc and the final multiply shoots it away from (0,0,0) ins$$anonymous$$d of the ship.
To get the cone (current is only sideways rotating,) use line 3 again, but with transform.right -- adds random up/down rotation.
Thankyou for fixing my script. It's almost like answering 2 questions at once! I only tested as far as rotating the ship on which was the origin so I didn't notice. I also was imagining a 2D shooter for some reason.
I offered this as an alternative, for RotateAround has helped me alot, am not very capable with Quaternion math, only to build a q.Euler and directly feed it to the rotation (based on a cached reference of the start rotation +/- player inputs), also some Sin and Deg2Rad, lately been starting to lean on LookAt.
I have fixed my answer with your help but am considering dropping it to a comment or deleting.
Thanks for this. Not a bad idea and looks like it will work. I prefer the other solution though because it doesn't require a prefab. Thanks again
Thankyou. I would go with Owen's too! I sometimes use the object as a visual 'flag' also and control the renderer, but your points are absolutely valid. I wish I could fathom the quaternion. Have fun.
Theres something to be said for using things you know. RotateAround on a gameObject makes sense, easier to visualize, and might be easier to modify later.
There's probably also a way to avoid the prefab -- just use a Vector3 var with RotateAround (but the other rule of coding is: don't fix what ain't broke.)
Your answer
