Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Limiting Turret Rotation on Tank

Discussion in 'Scripting' started by The-NightflyAZ, Oct 29, 2017.

  1. The-NightflyAZ

    The-NightflyAZ

    Joined:
    Apr 27, 2015
    Posts:
    17
    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);


    }
     
    Westland likes this.
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Volume was super quiet in the video, but I got the idea anyways :)
    Please refer to this page for posting code on the forums: https://forum.unity.com/threads/using-code-tags-properly.143875/
    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 :
    Code (csharp):
    1. barrel.rotation = Quaternion.Euler(value, barrel.rotation.eulerAngles.y,/* z if used or 0 */);
    2. // use localRotation instead maybe. Which would probably mean the Euler 'y' portion above is simply 0 or fixed :)
     
    Westland, juanedmendo and Kurt-Dekker like this.
  3. The-NightflyAZ

    The-NightflyAZ

    Joined:
    Apr 27, 2015
    Posts:
    17
    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.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class TurretRotate_SciFiTank : MonoBehaviour
    6. {
    7.  
    8.     //Rotating Key Variables
    9.  
    10.     public GameObject sciFiTurretBase;  //reference to the turret base of the cannon for side to side movement
    11.     public GameObject sciFiBarrel;  //reference to the actual barrel of the cannon for up/down movement
    12.  
    13.     public string turretLeft; //key to rotate turret to left
    14.     public string turretRight; //key to rotate turret to Right
    15.     public string turretUp; //key to rotate turret barrel  Up
    16.     public string turretDown; //key to rotate turret barrel Down
    17.  
    18.  
    19.     public float barrelRotX;  //float value to plug into Vector3 that will be used w/Quaternion.euler value
    20.     public Quaternion barrelRotationFinal;  //quaternion to hold angle of barrel
    21.  
    22.     public float baseRotY;
    23.     public Quaternion baseRotationFinal;
    24.  
    25.     public float minBarrelRotX;  // min value to use in Mathf.Clamp to limit barrel up/down rotation
    26.     public float maxBarrelRotX;  // max value to use in Mathf.Clamp to limit barrel up/down rotation
    27.  
    28.     public float rotateSpeed;  //rotate speed multiplier for the turret and barrel
    29.  
    30.  
    31.     public Transform sciFiShotPoint;  //position in space to instantiate energy weapon of cannon
    32.     //public GameObject sciFiWeapon;  //reference to the weapon prefab
    33.     public string shootKey;  //reference to the shoot key of the weapon.
    34.  
    35.     public GameObject plasmaProjectile;  //projectile of sciFi Tank
    36.     //public GameObject plasmaMuzzleFlash;  //muzzle flash effect for plasma
    37.     public AudioSource plasmaCannonFire;  //  reference to the audio source containing the cannon fire wav
    38.  
    39.  
    40.     // Use this for initialization
    41.     void Start ()
    42.     {
    43.         rotateSpeed = 30f;
    44.     }
    45.    
    46.     // Update is called once per frame
    47.     void Update ()
    48.     {
    49.  
    50.         //limiting barrel up and down values
    51.  
    52.         if (barrelRotX > maxBarrelRotX)
    53.         {
    54.             barrelRotX = maxBarrelRotX;
    55.         }
    56.  
    57.         if (barrelRotX < minBarrelRotX)
    58.         {
    59.             barrelRotX = minBarrelRotX;
    60.         }
    61.         //...to here
    62.  
    63.             //CANNON MOVEMENT INPUTS - feeding into the float values
    64.         if (Input.GetKey(turretRight))
    65.         {
    66.             sciFiTurretBase.transform.Rotate (Vector3.up * rotateSpeed * Time.deltaTime);
    67.         }
    68.  
    69.         if (Input.GetKey(turretLeft))
    70.         {
    71.             sciFiTurretBase.transform.Rotate (Vector3.up * -rotateSpeed * Time.deltaTime);
    72.         }
    73.  
    74.         if (Input.GetKey(turretUp))
    75.         {
    76.             barrelRotX += Time.deltaTime * rotateSpeed;
    77.         }
    78.  
    79.         if (Input.GetKey(turretDown))
    80.         {
    81.             barrelRotX += Time.deltaTime * -rotateSpeed;
    82.         }
    83.  
    84.         barrelRotX = Mathf.Clamp (barrelRotX, -45f, 20f);  //clamp the value of barrelRotX
    85.         sciFiBarrel.transform.rotation = Quaternion.Euler (barrelRotX, sciFiBarrel.transform.rotation.eulerAngles.y, 0);  //plug into transform.rotation
    86.  
    87.         //END CANNON CONTROL INPUTS
    88.  
    89.  
    90.  
    91.         if (Input.GetKeyDown(shootKey))
    92.         {
    93.             FirePlasma();
    94.         }
    95.        
    96.     }
    97.  
    98.     void FirePlasma()
    99.     {
    100.        
    101.         //Instantiate(plasmaProjectile, sciFiShotPoint.position, barrelRotation);
    102.         //plasmaCannonFire.Play();
    103.     }
    104. }
     
    Westland and juanedmendo like this.
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Cool, glad it worked for ya :)
     
    Westland likes this.
  5. skinner92

    skinner92

    Joined:
    Feb 23, 2014
    Posts:
    112
    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.
     
  6. juanedmendo

    juanedmendo

    Joined:
    Oct 1, 2021
    Posts:
    1
    Thanks for sharing your final code, it was really helpfull.