- Home /
Simple shooting script causing heavy lag
Hi all,
I have two scripts, a WeaponController (which instantiates a bullet prefab and sets the direction) and a Projectile script which fires it (by translating it forwards).
For some reason when I fire a number of bullets it seems to lag the game very heavily and I'm not quite sure what this is down to. The bullet prefab has a Projectile script attached.
If anyone can help that would be great :)
WeaponController
public class Weapon_Controller : MonoBehaviour
{
// The weapons that are available
public GameObject[] weaponPrefabs;
// The position to fire the weapon from - Right bullet spawner
public Transform BulletSpawnerR_obj;
private Projectile tempProjectile;
// Shoot!
public void Shoot()
{
// Instantiate a new projectile at the bullet spawner position
GameObject newProjectile = Instantiate(weaponPrefabs[currentWeapon],
BulletSpawnerR_obj.position,
BulletSpawnerR_obj.rotation) as GameObject;
// Access the Projectile script on the projectile just instantiated.
// Calling the script will fire the projectile straight away (called
// inside its Start())
tempProjectile = newProjectile.GetComponent<Projectile>();
// Make the targetPoint transform point in the bullet spawner's
// forward direction
tempProjectile.targetPoint = BulletSpawnerR_obj.forward;
//Set the weaponControllerReference to point to the current projectile
// just instantiated.
tempProjectile.weapon_ControllerReference = this;
}
}
Projectile script
public class Projectile : MonoBehaviour
{
[System.NonSerialized]
// This is the target at which the projectile will be fired
public Vector3 targetPoint = Vector3.zero;
// Use this for initialization
void Start ()
{
// Make the projectile face the target position
transform.LookAt(targetPoint);
// Destroy the projectile after a delay
Destroy(gameObject, timeToLiveInSeconds);
// Call the DoMovement() coroutine to fire the projectile forward
StartCoroutine(DoMovement());
}
IEnumerator DoMovement()
{
// While the object that this script is attached to exists..
while (true)
{
// Move projectile forward
transform.Translate(targetPoint * Time.deltaTime * 100);
}
// Waits until next fixed frame rate update function.
yield return new WaitForFixedUpdate();
}
}
Answer by Gizmoi · Jan 25, 2013 at 08:34 PM
The while(true) loop in your DoMovement coroutine looks to be causing the lag.
I assume you want the projectile to constantly travel in a given direction? You would be best off using FixedUpdate instead of a coroutine.
void FixedUpdate()
{
transform.Translate(0, 0, 1, Space.Self);
}
This will move the gameObject that the script is attached to forward by 1 unit each FixedUpate. Adjust the 1 if you'd like it to move faster or slower.
It is not a good idea to not scale transformations/calculations in any of the Update functions with Time.deltaTime. While not so much a problem in FixedUpdate, a missing Time.deltaTime would still cause a change of speed if you were to choose a differen FixedUpdate interval.
I agree. Personally I prefer to use Update and multiply by Time.deltaTime, or better yet, use forces and the physics engine.
Answer by Wolfram · Jan 25, 2013 at 08:41 PM
In your coroutine you have an infinite loop that never exits. So each projectile you spawn creates a new blocked coroutine that eats CPU. My guess is you wanted to put the yield into the wile loop?
However, don't use a coroutine for this simple translation. Since all you do is to wait for the next FixedUpdate anyway, just put the transform.Translate directly into FixedUpdate();
Thanks for the tips! :)
I'll address the comments in no particular order and not necessarily to each person.
Gizmoi:
Wrt using Fixed Update as you mention, firstly this seems to fire the projectile backwards. That is, in the opposite direction to the forward direction of the bullet spawner (as its now independent of its direction). Also, for simple Translations, is it not standard practice to use Update and use FixedUpdate for Rigidbodies?
Secondly, I would like to be able to fire the bullet in which ever direction the bullet spawner is facing (as it will lock-on to certain objects). So I'd like to pass the Projectile script the forward direction of the spawner, which it then fires the projectile along.
Thirdly, you mention you prefer to use forces to move the objects. This was the method I was using before going down the co-routine route. I was interested in seeing which method is less CPU intensive (Addforce, or Translate() / position += position * Time.deltaTime). Would you recommend I stick with applying forces?
Wolfram:
The blocked co-routine problem you describe does make a lot of sense. I had a feeling it could be that, if the instantiations are far apart it appears to be fine.
When you say "not a good idea to not scale transformations/calculations in any of the Update functions with Time.deltaTime." By scaling do you mean changing the z-value, for example, can you elaborate on this a little? " a missing Time.deltaTime would still cause a change of speed", as in a change to Time.deltaTime might not get polled by Update() during a frame (causing apparent speeding up) but would be polled in a FixedUpdate() as it not framerate-dependent?
First: all FixedUpdate does is give you a frame-rate independent place to do movement and other functionality. You can achieve the same by multiplying by Time.deltaTime; it's just prettier to use FixedUpdate.
Second: I would recommend moving your Start function to a Fire function, similar to this:
public void Fire(Vector3 direction)
{
transform.forward = direction;
m_Fired = true;
}
void FixedUpdate()
{
if (m_Fired == true)
{
transform.Translate(0, 0, 1, Space.Self);
}
}
Third: Physics is easier I think, depending on what you want to do with the projectiles. You can use the Physics engine and implement a fire-and-forget system, where you just spawn your bullet, give it force and then leave it on its way, you don't need to touch it again except for checking collisions.
You don't need to move it each frame (as long as it has no drag) it will go forever until it hits something. Thought I recommend you destroy it after so much time or so much distance.
I would recommend using forces unless you encounter some difficulty with it and find direct translations easier. The integrated Physics are quite well optimised.
Edit: if it's still going backward, -1 ins$$anonymous$$d of 1 ;)