Like most Twin Stick shooters, my player both turns and shoots with the right stick. I use a Quaternion.Slerp() to smoothly rotate the player from the current rotation to the new rotation, however the player starts firing before reaching the new rotation. My question is what is the most optimal way to delay my player from shooting until they've reached the desired new rotation?

  • 4
    \$\begingroup\$ Be very careful when delaying player action, as it has a tendency to make your game feel sluggish and unresponsive, but in a way that's hard for a player to pin down — they just feel their frustration or boredom rising instead of getting sucked into the immediacy of your gameplay. Unless your rotation is very slow, you may want to allow the player to fire instantly as though they were already in the new orientation and let the visual rotation of their avatar catch up when it can. This will tend to feel snappier. \$\endgroup\$ – DMGregory Sep 9 '16 at 23:07
  • \$\begingroup\$ Yes it is snappy but the projectiles are then noticeably flying out at awkward angles. The turn rotation isn't slow by any means but I can have them getting frustrated at wasted bullets or confused as to why the bullets are shooting 90 degrees out of the barrel. \$\endgroup\$ – Doctor Win Sep 9 '16 at 23:10
  • 2
    \$\begingroup\$ In a fast-paced twin stick shooter, having the bullets fire when & how the player wants them to is likely to be more precious to their experience than the integrity of your barrel animations. If something's gotta give, in my own work I'd change the way I rotate my barrels before adding any frames of latency to the player's shots. It is of course your game and you can set priorities differently, just be very conscious of the impacts this will have on the player's experience of the game feel. \$\endgroup\$ – DMGregory Sep 9 '16 at 23:18
  • 1
    \$\begingroup\$ Either way, I need a solution. Not the lesser of two evils. \$\endgroup\$ – Doctor Win Sep 9 '16 at 23:39
  • \$\begingroup\$ Use coroutines. Just rotate inside coroutine, stop coroutine before starting a new one. Shoot after loop is done inside coroutine. \$\endgroup\$ – Candid Moon _Max_ Mar 6 '17 at 10:58

I think getting rid of Slerp or using a high t so that it's fast enough would be the best as far as gameplay goes.

However, I think this gets close to what you want: find the difference in rotation between the stick and the character and shoot only if the two are close enough. I think this is the closest thing to what you actually want.

Here are two ways you can do this:

If you have vectors for stick direction and character front, probably most efficient:

Vector3 stickDirection;
Vector3 characterFront;
float maxShootingAngleDifference = 10;
if (Vector3.Angle(stickDirection, characterFront) < maxShootingAngleDifference) {

If you have rotations for stick and character:

Quaternion stickOrientation;
Quaternion characterOrientation;
float maxShootingAngleDifference = 10;
// documentation does not say, but if this can return negative, put it in Mathf.Abs()
if (Quaternion.Angle(stickOrientation, characterOrientation) < maxShootingAngleDifference) { 

This would make it fire after the character gets closer than 10 degrees to the stick direction.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.