Limiting Turret Rotation on Tank

Hi Everyone. This should not be as hard as it is but I’m just trying to limit the up/down motion of the barrel of the tank. Here’s a video that hopefully illustrates the problem.

I’m just using Transform.Rotate (Vector3. up and Vector3.Right for the turret base and barrel’s rotation since they are two separate objects and it seems to work fine but I just cannot get the clamping to work on the up/down motion when using the transform.Rotate(Vector3.Right. It’s funny that you can make the tank look like it’s on a pogo stick but not optimal for making the barrel behave realistically.

Any suggestions would be appreciated.

Here’s the relevant code…

Thanks!

public class TurretRotate_SciFiTank : MonoBehaviour
{

//Rotating Key Variables

public GameObject sciFiTurretBase; //reference to the turret base of the cannon for side to side movement
public GameObject sciFiBarrel; //reference to the actual barrel of the cannon for up/down movement

public string turretLeft; //key to rotate turret to left
public string turretRight; //key to rotate turret to Right
public string turretUp; //key to rotate turret barrel Up
public string turretDown; //key to rotate turret barrel Down

public Quaternion barrelRotation; //quaternion to hold angle of barrel
public float barrelRotX;
public Quaternion baseRotation;
public float baseRotY;

//public float maxBarrelRot;
//public float minBarrelRot;

public Transform sciFiShotPoint; //position in space to instantiate energy weapon of cannon
//public GameObject sciFiWeapon; //reference to the weapon prefab
public string shootKey; //reference to the shoot key of the weapon.

public GameObject plasmaProjectile; //projectile of sciFi Tank
//public GameObject plasmaMuzzleFlash; //muzzle flash effect for plasma

// Use this for initialization
void Start ()
{

}

// Update is called once per frame
void Update ()
{
//CANNON MOVEMENT INPUTS
if (Input.GetKey(turretRight))
{
//baseRotY += Time.deltaTime * 100f;
sciFiTurretBase.transform.Rotate (Vector3.up * 50f * Time.deltaTime);
}

if (Input.GetKey(turretLeft))
{
//baseRotY -= Time.deltaTime * 100f;
sciFiTurretBase.transform.Rotate (Vector3.up * -50f * Time.deltaTime);
}

if (Input.GetKey(turretUp))
{
//barrelRotX += Time.deltaTime * 100;
sciFiBarrel.transform.Rotate (Vector3.right * 40f * Time.deltaTime);
}

if (Input.GetKey(turretDown))
{
//barrelRotX -= Time.deltaTime * 100;
sciFiBarrel.transform.Rotate (Vector3.right *-40f * Time.deltaTime);

}

1 Like

Volume was super quiet in the video, but I got the idea anyways :slight_smile:
Please refer to this page for posting code on the forums: Using code tags properly
It will show up looking much nicer.

One of the easiest solutions to your situation is keep track of the angle of (local)rotation.
It goes up/down based on input… next, you clamp it before assigning it.
Lastly, of course, you assign it. Maybe :

barrel.rotation = Quaternion.Euler(value, barrel.rotation.eulerAngles.y,/* z if used or 0 */);
// use localRotation instead maybe. Which would probably mean the Euler 'y' portion above is simply 0 or fixed :)
3 Likes

Hi Methos5k! Thanks for the input! This has been driving me nuts for the last couple of days!

The logic of Quaternions still eludes me but your suggestion worked perfectly. I left the horizontal rotation of the turret base the same but applied your code to the barrel and viola! It works! Thanks so much. For anyone else who has the same problem here’s the code for rotating the tank turret and barrel.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TurretRotate_SciFiTank : MonoBehaviour
{

    //Rotating Key Variables

    public GameObject sciFiTurretBase;  //reference to the turret base of the cannon for side to side movement
    public GameObject sciFiBarrel;  //reference to the actual barrel of the cannon for up/down movement

    public string turretLeft; //key to rotate turret to left
    public string turretRight; //key to rotate turret to Right
    public string turretUp; //key to rotate turret barrel  Up
    public string turretDown; //key to rotate turret barrel Down


    public float barrelRotX;  //float value to plug into Vector3 that will be used w/Quaternion.euler value
    public Quaternion barrelRotationFinal;  //quaternion to hold angle of barrel

    public float baseRotY;
    public Quaternion baseRotationFinal;

    public float minBarrelRotX;  // min value to use in Mathf.Clamp to limit barrel up/down rotation
    public float maxBarrelRotX;  // max value to use in Mathf.Clamp to limit barrel up/down rotation

    public float rotateSpeed;  //rotate speed multiplier for the turret and barrel


    public Transform sciFiShotPoint;  //position in space to instantiate energy weapon of cannon
    //public GameObject sciFiWeapon;  //reference to the weapon prefab
    public string shootKey;  //reference to the shoot key of the weapon.

    public GameObject plasmaProjectile;  //projectile of sciFi Tank
    //public GameObject plasmaMuzzleFlash;  //muzzle flash effect for plasma
    public AudioSource plasmaCannonFire;  //  reference to the audio source containing the cannon fire wav


    // Use this for initialization
    void Start ()
    {
        rotateSpeed = 30f;
    }
   
    // Update is called once per frame
    void Update ()
    {

        //limiting barrel up and down values

        if (barrelRotX > maxBarrelRotX)
        {
            barrelRotX = maxBarrelRotX;
        }

        if (barrelRotX < minBarrelRotX)
        {
            barrelRotX = minBarrelRotX;
        }
        //...to here

            //CANNON MOVEMENT INPUTS - feeding into the float values
        if (Input.GetKey(turretRight))
        {
            sciFiTurretBase.transform.Rotate (Vector3.up * rotateSpeed * Time.deltaTime);
        }

        if (Input.GetKey(turretLeft))
        {
            sciFiTurretBase.transform.Rotate (Vector3.up * -rotateSpeed * Time.deltaTime);
        }

        if (Input.GetKey(turretUp))
        {
            barrelRotX += Time.deltaTime * rotateSpeed;
        }

        if (Input.GetKey(turretDown))
        {
            barrelRotX += Time.deltaTime * -rotateSpeed;
        }

        barrelRotX = Mathf.Clamp (barrelRotX, -45f, 20f);  //clamp the value of barrelRotX
        sciFiBarrel.transform.rotation = Quaternion.Euler (barrelRotX, sciFiBarrel.transform.rotation.eulerAngles.y, 0);  //plug into transform.rotation

        //END CANNON CONTROL INPUTS



        if (Input.GetKeyDown(shootKey))
        {
            FirePlasma();
        }
       
    }

    void FirePlasma()
    {
       
        //Instantiate(plasmaProjectile, sciFiShotPoint.position, barrelRotation);
        //plasmaCannonFire.Play();
    }
}
2 Likes

Cool, glad it worked for ya :slight_smile:

1 Like

I know you already solved your problem, but I think a (perhaps) cleaner solution to your problem is using Mathf.Clamp to clamp your barrel’s rotation between 2 predefined angles.

Thanks for sharing your final code, it was really helpfull.