- Home /
Aim at Something with Delay
Hi, all!
I was just wondering if there was a type of SmoothLookAt function that looks at the player's position x seconds ago. This would be great to use for a simple enemy AI.
If there are no community scripts, does anyone know how I could do this? Somehow store the player's position x seconds ago? This would be a great simulation of 'accuracy' (if the player is moving a lot, the player will generally not take much damage).
Hopefully this is the correct approach to basic AI shooting functionality. ;)
Thanks! - YA
I'd like to take a crack at this, but I have a question first. It seems to me that your end goal is not necessarily to know how to store the player's past movements, but is actually to create a decent enemy ai$$anonymous$$g AI. Is this correct? If so, I definitely have some ideas and approaches on how to do this.
If you simply want to store the players past positions, then this is possible also. Let me know which you prefer, and I'll be glad to post an answer.
Well If there can be better steps taken towards developing a more decent ai$$anonymous$$g AI I'm all for it! I've never attempted something like this but I'd like to consider myself a pretty decent coder. Decent ai$$anonymous$$g AI it is ;) What were your ideas for a separate -better- method?
It looks like @sparkzbarca laid out a decent and easily modifiable alternative. I'm sure there are many approaches though. I would take one key point away from @sparkzbarca's post:
"What you really need to do is sit down and ask yourself what things affect accuracy."
It all depends on your game, are you adding bullet drop, wind, recoil, breathing sway, etc...? I personally would have enemies have an accuracy amount, and choose a random number per shot. The accuracy would dictate the radius of a circle, whereas the random number is clamped to the size of that circle. This is basically @sparkzbarca's approach below. Now to deter$$anonymous$$e the center of the circle, you need to decide where the enemy is specifically ai$$anonymous$$g. So with perfect accuracy, the enemy hits dead-center in that circle, because the circle would be absolutely tiny.
The interesting part is deciding how to deter$$anonymous$$e where the enemy aims, and if you want to add some variables that affect that or not. You can go for the easy approach, and just have the enemy aim at center mass (your torso), or you figure out what you want to affect this. One thing is wind speed and bullet drop. Does the enemy take these things into account? If not, then when they aim center mass at a target 400m away with an assault rifle, the aim point may end up being at the legs somewhere. If the wind is also blowing pretty hard, the aim point may then end up just to the left/right of the target.
Even if the enemy is going to be knowledgeable of these things, it purely depends on the situation. If it's a sniper, and he has a spotter to check distance and wind speed, and he has time to calculate everything, then yeah, the aim point will likely be pretty close to right on. If it's just some random enemy running around, and they have suppressive fire being laid down on them, it's likely that their aim point will be completely off.
All in all, there are many things to consider, and you'd need to really sit down and decide the specifics of what you want for your aim system, as well as the complexity. Less is going to be easier, but less realistic. $$anonymous$$ore realistic doesn't always mean more enjoyable though.
Thank you, justin. As I mentioned earlier, this game is quite simple, and enemy accuracy will have very few variables to affect it, but enough to make it interesting. Although you give an awesome comment, I'm going to go ahead and mark sparkzbaraca as the answer, but upvote your comment as well. I did not think of the circle idea and it is truly genius. Thank you very much, the both of you, for your help. I hope this post gets seen a lot, because it is a really great solution (and extremely modular, to say the least) to such a common problem.
Answer by sparkzbarca · Jan 21, 2013 at 02:01 AM
I wouldn't do it that way.
just make an accuracy algorithm and factor in movement and distance.
what your really going to do is use an algorithm to find the radius of a circle and then RANDOMLY target 1 point inside that circle.
the algorithm can be as complex or as simple as you want. Here are some ideas though
accuracy = fired_recently distance ai_velocity player_velocity ai_base accruracy
fired_recently would be a number that KEEPS INCREASING up to a max value if you keep firing. It basically makes each shot successively less accurate.
the multiplying is imporant. What you really need to do is sit down and ask yourself what things affect accuracy. in the above i went with.
shooter velocity, target velocity, recoil(if you fired recently), distance to target, shooter skill.
Then you need to ask yourself how much each should affect it relative to a base amount.
if you say for example a prone sniper AI shooting at a a stationary target at close range(or whatever your best case scenario is) will hit somewhere within a 1 x circle. it should be 1 of something. it could be 1 inch or for example it could be 1 half inch. if it's 1 half inch convert it later. You want your base to be one for multiplying to work to produce 1 in a perfect case and be based off that for other cases.
Now what you do is
base = 1
and now everything is relative to the base
then how much would a moving target affect it. 3 times as much lets say, and how much harder is standing up than laying down? twice as much lets say
standing = 3; crouched = 2; prone = 1;
target_moving = 3; target_still = 1;
ok then accuracy = target_moving * standing; so its a 6 inch circle because its 6 times harder to hit a moving target while standing than a stationary one while prone.
you keep doing that for all your variables remember though its all based on a base, that means each variable should have one possibility (and the best possiiblity) be 1.
so if prone is the best stance prone is 1. You shouldnt have something that is less than 1 because that means someone could have an accuracy that is greater than whatever you think is perfect nearly (it's natural to assume even the best shot wouldn't PERFECTLY hit exactly what they aimed at). The only reason for a value of less than 1 would be maybe an ability that improves accuracy for a short period.
so you now find the radius of the circle with the algorithm and then its just a matter of a function call to randomly pick a point within its bounds. send the bullet right at that point.
for example if its 3 times harder to hit while moving than
I am still a bit confused. Sorry, guys. I have implemented the code, and for a test I set the base unit variable to 0. (shouldn't that allow for pinpoint accuracy?) When my enemies fire, they are quite a ways off from hitting the ship. What is wrong?
Here is the script. Thanks!- YA
#pragma strict
@HideInInspector
var stats : EnemyStats;
@HideInInspector
var ship : Player;
var myTarget : Transform;
var myBullet : Transform;
function Start () {
stats = transform.parent.GetComponent( EnemyStats );
ship = GameObject.Find("$$anonymous$$aster").GetComponent($$anonymous$$aster).slotArray[$$anonymous$$aster.currentSlot].ship;
myTarget = GameObject.Find( "Ship" ).transform;
}
function Shoot(){
//Calibration
var baseUnit : float = 0.0; //Haven't yet decided how much of a unit a base unit should be.
var baseAccuracy : float = stats.accuracy;
var randomAccuracy : float = Random.Range( 1.0, 2.5 );
var damagedAccuracy : float = ( stats.hp.current <= ( stats.hp.max )/2 ) ? 1.5 : 1;
var player$$anonymous$$oveAccuracy : float = 1.0;
if( ship.state == PlayerState.$$anonymous$$oving ) player$$anonymous$$oveAccuracy = 3.0;
if( ship.state == PlayerState.Charging ) player$$anonymous$$oveAccuracy = 1.5;
var accuracy = baseUnit*baseAccuracy * randomAccuracy * damagedAccuracy * player$$anonymous$$oveAccuracy; // This defines the radius of our ai$$anonymous$$g circle
var aimPoint : Vector3 = Vector3(
Random.Range( myTarget.position.x - accuracy, myTarget.position.x + accuracy),
Random.Range( myTarget.position.y - accuracy, myTarget.position.y + accuracy),
myTarget.position.z );
yield WaitForSeconds( 0.5 );
Instantiate(myBullet, transform.position, Quaternion.Euler( aimPoint ));
}
Whoop never$$anonymous$$d. Fixed the issue. $$anonymous$$y bullets were moving backwards -_-
Still have a question though: I am working with lasers (so actual collisions ). This means that the lasers travel at a set speed.
This means that if the ship is moving, even a shot with pinpoint accuracy might not hit it simply because the ship moved. Is there any way I can fix this?
$$anonymous$$aybe choose a point relative to the ship's position, and update that point as the ship moves, and have the bullet 'home' to that point?
Give me your views, please :D
If you update the point, then your laser will not look like a laser, but a ho$$anonymous$$g missile. You want the laser to go where the enemy shot it, in a straight line. Just factor in the movement vector (speed and direction) of the target and the distance from shooter to target, and adjust your aim point accordingly. So basically, you need to know how far you are from your target, the speed of your round (laser). With that, you can calculate how long it will take to make it to the target. Now if you know how fast your target is moving, and what direction it is moving, you can calculate how long it will take to get to the intersecting point, i.e. your enemies adjusted aim point. This should be calculated prior to the laser being fired. The cool thing is, is that it will be realistic, so if you are moving left, and the enemy shoots where they think you will be (leading the target), then you juke right real quick, they may still miss, not because their are inaccurate, but because you 'dodged' it. Now, depending on the speed of the lasers, and the targets movement speed, it may not be possible to actually dodge the round.
Interesting. Thank you for the advice. Luckily, I am not using physics, so my ship and bullets are moving at a set rate. This shouldn't be too hard to calculate.
The Z distance from enemy to ship also never changes.
I assume I would be solving for the angle of the hypotenuse of the triangle formed with the vertical leg being the distance from enemy to ship, and the horizontal leg being a vector with the direction the ship is traveling in and a magnitude of the ship's speed*(bullet speed / vertical leg), and setting the bullet's trajectory to that value.
Where can I find the trigonometric functions ( most importantly, ArcTangent ) ?
Thanks! - YA
mathf.function for example
mathf.atan(float f)
given an angle in radians 'f' it returns the the arc tangent of that angle
Your answer
Follow this Question
Related Questions
Shoot Delay Problem[HELP] 1 Answer
How to make a gun shoot in burst. 2 Answers
Slowing down the speed of my bullets whilst holding in the key. 1 Answer
How to add a delay to my script. 3 Answers
Shoot Bullet Delay Enemy 0 Answers