Cannon Recoil Script Help

Hello,

I am attempting to simulate “recoil” on three similar cannon objects on a tank turret via code (a simple slide back and forth behavior), and I’m having trouble with the side cannons behavior. I am using the Lerp function to move the cannons back and forth. The middle cannon exhibits the behavior I need, however the other two “side cannons” actually move inwards towards the middle cannon, instead of straight back like I want them to, and I’m not sure why.

All cannons have the same exact script which I will post below. And again, the middle cannon works great. It’s the two side cannons that for some reason lerp inwards towards the center. Is there a reason for this? I have a feeling the fact that the tank turret rotates may have something to do with it, but I’m not sure. Thanks for any help.

UnityEngine;
using System.Collections;

public class CannonRecoil1 : MonoBehaviour {

    private Transform thisTransform;

    public bool shouldRecoil = false;
    private bool shouldReturn = false;
    private Vector3 startingPosition;

    private bool doOnce1 = true;
    private bool doOnce2 = true;
    private bool doOnce3 = true;

    private Vector3 localDirection;




    // Use this for initialization
    void Start () {
        thisTransform = GetComponent<Transform>();
    }
  
    // Update is called once per frame
    void Update () {
      
        if (shouldRecoil)
        {
            if (shouldReturn == false)
            {
                if (doOnce1)
                {
                    startingPosition = thisTransform.localPosition;

                    //Get the local forward direction
                    localDirection = thisTransform.InverseTransformDirection(thisTransform.forward);

                    doOnce1 = false;
                }

                thisTransform.localPosition = Vector3.Lerp(thisTransform.localPosition, -(localDirection * 0.3f), 0.7f * Time.deltaTime * 10.0f);

                if (doOnce2)
                {
                    StartCoroutine("ReturnCannonToOriginalState");

                    doOnce2 = false;
                }

            }
            else if (shouldReturn)
            {
                thisTransform.localPosition = Vector3.Lerp(thisTransform.localPosition, startingPosition, 1.0f * Time.deltaTime * 2.0f);

                if (doOnce3)
                {
                    StartCoroutine("StopRecoil");

                    doOnce3 = false;
                }
            }
        }

    }




    //-----------------   FUNCTIONS  ----------------------------------------------
    IEnumerator ReturnCannonToOriginalState()
    {
        yield return new WaitForSeconds(0.7f);

        shouldReturn = true;
    }

    IEnumerator StopRecoil()
    {
        yield return new WaitForSeconds(3.0f);

        shouldRecoil = false;

        //Allow cannon to recoil again on next attack
        shouldReturn = false;
        doOnce1 = true;
        doOnce2 = true;
        doOnce3 = true;
    }
}

What’s the GameObject hierarchy of these cannons? Are the side cannons’ transformed relative to the main cannon or to the tank itself? Or are all three cannons children of some empty that is parented by the tank?

My best guess so far is that “InverseTransformDirection” is the wrong method for getting the direction vector you want. From what I know, it’s giving you a vector that points away from whatever Transform your cannons are children of. This wouldn’t be a problem for the main cannon if it positioned in-line with its parent, which I’m assuming it is.

Hi CDMcGwire,

All three cannons are children of an empty gameobject, and then that empty gameobject is the child of the main gameobject’s transform. So essentially you have: Root Transform —> Tank Turret Empty Object —> All three cannons. You are correct in that the main/middle cannnon is lined up with the Tank Turret Empty Object (but only on the “z” axis). The other cannons are not lined up with the turret empty object on any axis.

So do you have any guesses on how I can get the proper vector I want? I somehow just want the cannons to lerp backwards relative to themselves when the tank fires, and then slowly recoil back into position.

The script itself is located on each individual cannon, and not on the empty turret object.

Thanks for the help.

Alright. I tested some of your code on a throw-away script. Two things to note:
1.) The transform of an object does not need to be retrieved if the script is attached to the object that is moving. Simply type “transform” in lowercase and it will refer to the attached GameObject’s transform object (that was a weird sentence).

2.) A GameObject’s transform stores vectors that represent basic local directions (forward, up, right) and those can be retrieved with a statement like “transform.forward”.

So, knowing that, a line like:

thisTransform.localPosition = Vector3.Lerp(thisTransform.localPosition, -(localDirection * 0.3f), 0.7f * Time.deltaTime * 10.0f);

Might work better if written as:

transform.localPosition = Vector3.Lerp(transform.localPosition, -(transform.forward * 0.3f), 0.7f * Time.deltaTime * 10.0f);

Of course, the rest of your code will have similar changes made to it. Let me know if that works.

Hi CDMcGwire, well I decided it would be easier if I just use Unity’s built-in Animation tool to animate the cannons recoiling. For now, it works better than coding, although I am still curious as to if I could solve it through coding. So for now, I’m just going to leave that code sit where it is, and probably won’t be testing any more in that regard (unless I’m forced to come back to it).

Thanks for your answers though, and if I have to come back to it, I’ll have somewhere to start again.

I would do it this way, animation is much safer than code for this approach.

1 Like

Definitely in agreement. Good on you, OP, finding better solutions and stuff. :smile:

1 Like