Shooting Script Issue

Hi everyone, I am having an issue with bullets that have been shot not travelling to their destination as I would like.

This is a gyazo of the issue: https://i.gyazo.com/503ff37c9925f170b04f1fb8bb81639f.mp4

As you can see the bullets start off travelling to their destination but then change destination mid-flight.

This is how my shooting is currently handled:
1. The player has a child object called ‘aim’ which is the current facing direction of the player (and therefore their weapon).
2. The weapon has a ‘Weapon’ script attached to it that checks when the player presses the shoot button.
3. When the player presses the shoot button their current ‘aim’ position is stored as a Vector2 and a ‘Bullet’ is instantiated.
4. Each bullet has a script attached that uses MoveTowards to travel to the stored ‘aim’ position set in step 3.
5. The bullet moves towards the stored ‘aim’ position and is unloaded after an unloadTime set in the editor before it reaches that point. (otherwise it gets there and stops dead which looks stupid)

The issue is that for fast firing weapons the bullets will change trajectory because the ‘aim’ position is being constantly updated as long as the fire button is being pressed and they are constantly trying to ‘MoveTowards’ the ‘aim’ position.

One thing that worries me is that every bullet has it’s own script, surely this can’t be the right way of handling things. This is my first project I have gone fully alone into so excuse any ‘rookie-ness’ but I am really eager to find a way I can setup a solid shooting script, any pointers would be great.

Thanks,
Corey

Every bullet having it’s own script is really not as bad as it sounds, as the difference between a GameObject with a transform, rigidbody, and a collider versus a GameObject with a transform, rigidbody, collider, and a single short custom script is really negligible (even more negligible if the bullet has a MeshFilter and MeshRenderer)- the big performance impact here comes from the Instantiation of the GameObject (the bullet) itself. Definitely look into “object pooling”, which is essentially just having some bullet manager creates a bunch of bullets and store them in a list, then dole them out to the player/enemies that ask for them, then deactivate and return them to the pool instead of destroying them when their role is finished. It really cuts down on a ton of the overhead in situations like these.

As to your actual problem, I don’t really see the point of using MoveTowards dynamically like this. If you simply set the bullet to “LookAt” the spot you want it to hit, you can do a simple forward movement using transform.forward each frame, or fire the bullet using a force and let the physics engine handle the rest, or you can keep using MoveTowards but cache the “target” position on the movement script on the bullet the same frame it’s fired and go off of that, rather than referencing a member of the gun/player.

The script on the bullet is really necessary, so you can keep track of damage types (like different bullet types, hollow-point, slug-nose, etc…), damage potential of the weapon that fired it and not necessarily the weapon the marksman is currently holding (would run into the same kind of problem as the bullet trajectory, with that kind of reference), etc… Everything has to be cached and calculated the moment the trigger is pulled and the bullet comes into existence- everything after that should just be the bullet relying on its own data and the physics engine.

1 Like

Thankyou for the awesome response, I’ll try out what you said :slight_smile:

The problem seems to still occur. The bullet is constantly trying to move towards the target and if the target moves mid-flight so will the bullet until it unloads. I don’t want to have to start looking at other people’s shooting scripts but I think I might have to at this point :confused:

Don’t MoveTowards a transform’s current positon, cache the position they were at when you first fired.

// class variable
Vector3 targetPos = Vector3.zero;
Vector3 startPos = Vector3.zero;

float speed = 2f;
float startTime = 0f;

// in fire function/start/whatever
startPos = transform.position;
targetPos = target.transform.position;
startTime = Time.time;

// in Update
transform.position = Vector3.MoveTowards(startPos, targetPos, (Time.time - startTime) * speed)

or something like that. Haven’t done this in awhile. I’m almost assuredly doing the speed portion wrong, I’ll have to look it up.

Yeah, the time portion in the MoveTowards is a value between 0 and 1 to stand for how far between the starting and ending points that the result is. In other words, this is calculated based off of the total time that you want something to take, and not the speed at which it is traveling. If you take the total number of seconds passed ( Time.time - startTime ) and then divide it by the distance divided by the speed ( Vector3.Distance(startPos, targetPos) / speed ) you should end up with something like “time passed” divided by “total time to target”, which is what you’d want I think. If the result is over 1, then you’ve gone past the destination.

float percentTraveled = (Time.time - startTime) / ((Vector3.Distance(startPos, targetPos) / speed);

if(percentTraveled >= 1f)
    // quit, destroy, whatever
else
    transform.position = Vector3.MoveTowards(startPos, targetPos, percentTraveled);

I haven’t tried this yet but I think this will have the same problem, everytime I shoot the targetPos will change and so every bullet currently on screen will want to move towards it :confused:

I need a way of storing a bullet in a list with a Vector 2 assigned strictly to that 1 bullet that it travels to. Do you have any idea how I can set that up?

Thanks again for the replies :slight_smile:

The code I’ve been writing assumes the script is on the bullet, not the gun or the person firing- “transform.positon =” means “set the position of this object to be a new value”, so I figured we were on the same page about how this was working- this object needs to be the bullet. As that’s the case, the “targetPos” value and everything else would be on the bullet as well, and making a new bullet wouldn’t change the value on any previous bullets.

Controlling an object from a distance (as in with a list of bullets and looping through them and moving them all a little each frame) is almost always a poor design approach- objects should always move themselves, even if they’re being “triggered” or “commanded” externally it should always be under their own power that they get from Point A to Point B.

Thankyou for the explanation, my code is currently attached to the bullet. I will try your solution when I am home from work :slight_smile:

Using your advice and a few other things online I have managed to fix my shooting script :slight_smile: Can’t thank you enough for baring with me lol. Now I’m just trying to find out how to remove the ‘Doppler’ effect on my bullets and I’ll be good to go xD Thanks again <3