- Home /
Why are my projectiles moving at an angle?
First of all:
The projectile prefab is on a layer and the physics have been set to ignore collision with the player and other projectiles in the project settings. The projectile has a rigidbody with all the rotation axes disabled. It also has the axis that I'm not using in my 2D game disabled.
When I fire the projectiles from my player, they fire the way I want them too, but as soon as they start to collide with another object with a rigidbody, some of the change direction. Then, after a while of firing, all the projectiles start doing the same thing and it stays that way until I end the play session.
I'd also like to add that the projectiles are not randomly changing direction, it is predictable and has the same pattern of movement throughout the firing of the cloned projectiles.
public class FireProjectile : MonoBehaviour
{
public GameObject projectilePrefab;
public GameObject[] clone;
private Transform thisTransform;
private int ammo;
private int lastBullet;
private int curBullet;
private bool locked;
private float rof;
void Awake()
{
ammo = 50;
lastBullet = 0;
rof = 0.05f;
clone = new GameObject[ammo];
thisTransform = this.transform;
InstantiateProjectiles();
}
// Update is called once per frame
void Update ()
{
if(Input.GetKey(KeyCode.Space))
{
if(IsInputLocked()){}
else
{
ActivateProjectiles();
Lock();
}
}
}
private void InstantiateProjectiles()
{
for(int i = 0; i < clone.Length; i++)
{
clone[i] = (Instantiate(projectilePrefab, thisTransform.position, thisTransform.rotation) as GameObject);
clone[i].SetActive(false);
}
}
private void ActivateProjectiles()
{
curBullet = GetNextBullet();
if(clone[curBullet].activeSelf == false)
{
clone[curBullet].SetActive(true);
clone[curBullet].GetComponent<Projectile>().Activate();
clone[curBullet].transform.position = thisTransform.position;
}
}
private void Lock()
{
locked = true;
Invoke("Unlock", rof);
}
private void Unlock()
{
locked = false;
}
private bool IsInputLocked()
{
return locked;
}
private int GetNextBullet()
{
lastBullet += 1;
if(lastBullet >= ammo-1)
{
lastBullet = 0;//reset the loop
}
Debug.Log("LastBullet = " + lastBullet);
return lastBullet;
}
}
public class Projectile : MonoBehaviour
{
private float projectileSpeed;
public PlayerBounds bounds;
private float time;
private float lifeTime;
private Transform thisTransform;
void Awake()
{
lifeTime = 2.0f;
projectileSpeed = 5.0f;
thisTransform = transform;
}
// Update is called once per frame
void Update ()
{
LifeSpan();
MoveProjectile();
}
private void MoveProjectile()
{
float movement = projectileSpeed * Time.deltaTime;
thisTransform.Translate(Vector3.right * movement);
}
public void Activate()
{
time = Time.time + lifeTime;
}
public void Deactivate()
{
gameObject.SetActive(false);
}
private void LifeSpan()
{
if(time <= Time.time)
{
Deactivate();
}
}
}
Post some code please :) It sounds like somehow the prefab is being modified ins$$anonymous$$d of each instantiated object.
clone[curBullet].transform.TransformDirection(1,0,0);
Are they veering to the right?
GetComponent<Projectile>()
I dont get this bit. Why the () after ?
To answer your first question, no. I was using that to check if setting the transform direction could keep them going in their forward direction. Right now, relative to the World transform, my forward direction is +x. Do you think that is the problem?
As for your second question, that's how you call GetComponent in C#.
@meat5000 I guess you're not familiar with C# generics. GetComponent
is a method call, and thus requires a pair of brackets to denote it as such (even if there are no arguments). The triangle brackets define the generic type, and so the full structure:
GetComponent<Projectile>
becomes the name of the method. So, like you would use () to call the method GetNextBullet
, the brackets are still required to actually call the method.
Answer by RyanZimmerman87 · Sep 12, 2013 at 12:43 AM
To me it looks like you are over complicating things with that code. Why do you use:
clone[curBullet].GetComponent().Activate();
Whenever I do projectiles I create one public GameObject or Rigidbody for the original projectile prefab. And I have a separate private GameObject or RigidBody for each instantiated projectile.
For example:
public Rigidbody dartObject;
Rigidbody instantiateDart;
void enemyAttackAnimationEventFunction()
{
instantiateDart = (Rigidbody)Instantiate(dartObject, dartStartPoint.position, dartStartPoint.transform.rotation); //or Quaternion.identity
instantiateDart.AddForce(transform.forward * dartVelocity);
Destroy(instantiateDart.gameObject, 8);
}
I've never had to GetComponents or create any kind of indexes/arrays with []. That kind of thing could be useful if the order or state of individual projectiles matter in your project. In all my projects so far the only thing that matters is whether the projectile hits something within the time before it destroys.
Well, from your perspective, you must be using instantiate in update, I'm not. The InstantiateProjectiles() function is being called in Awake. Therefore, it is creating the clones ahead of time and activating them on the key press, for which then each clone has a Projectile script. On that script it moves the object and deactivates the projectile after a time.
I also have the clones controlled with this:
private int GetNextBullet()
{
lastBullet += 1;
if(lastBullet >= ammo-1)
{
lastBullet = 0;//reset the loop
}
Debug.Log("LastBullet = " + lastBullet);
return lastBullet;
}
From what I've learned from many people from the community, is that destroying is much more intensive, but they could be wrong. I'm just going with what I've learned.
Read this if you want to see what I mean:
http://answers.unity3d.com/questions/7877/how-do-you-use-a-pool-of-objects-rather-than-creat.html
Hmm I see what you are saying with recycling the ammo ins$$anonymous$$d of destroying them. I think it depends on how many bullets you would have active on average when you are playing. The more projectiles you have flying around the mores useful that method may be. But if you don't have a lot flying around it seems excessive to instantiate 100-1000 bullets on Awake and have that just floating around idle in the memory.
I have never made a project where there are a ton of projectiles so I cant say anything definitive about the performance implications.
$$anonymous$$y projectiles have always been called on an event whether it be an Animation Event of an enemy or a key press of the player. But never even tried any rapid fire stuff.
So in that case it seems like your problem is just that the recycled bullets are not setting to their correct rotation. What is thisTransform? Is that a public variable of some child object on the player? If so you may just need something like this in addition:
clone[curBullet].transform.position = thisTransform.position;
clone[curBullet].transform.rotation = thisTransform.transform.rotation;
not sure if you would need this:
clone[curBullet].transform.TransformDirection(1,0,0);
On first glance it seems that having to activate the clone, get the component then call a function on it, then reset it's position & rotation, and then finally fire it and later deactivate it would be just as resource intensive as instantiating an object at the correct position/location, firing it, and later destroying it. Especially if you have a lot of inactive clones just sitting around in the background.
Given the ever increasing speeds of processors these days I am very curious how much of a performance difference this would actually be and if it would actually effect frame-rates. If Destroy or Instantiate is really that expensive at run-time it's very well possible with lots of bullets. Interesting subject hope you get it sorted out!
First of all, thisTranform is me attempting to make a cached version of the transform for that object. Am I doing that wrong?
Are these lines meant for ActivateProjectiles() ?
clone[curBullet].transform.position = thisTransform.position;
clone[curBullet].transform.position = thisTransform.transform.rotation;
If that is so, clone[curBullet].transform.position = thisTransform.position;
is already in there.
The second line makes no sense to me. Wouldn't that just overwrite the previous line?
I also tested this using the usual method, and found that it was was really slowing down the game (It went from about 65FPS, to about 20FPS).
You would be right that would be less intensive (I believe) if we were talking about non-rapid firing projectiles.
Your answer
Follow this Question
Related Questions
2d colliders on 3d colliders 0 Answers
Ignore Collision In Physics settings, Doesn't Work?? 1 Answer
Ignore collisions between a certain collider and a layer 2 Answers
Help using fixed joints 1 Answer