Search Unity

How to do efficient charging or buildup on a gun

Discussion in 'Scripting' started by VaunMakuza, Mar 17, 2013.

  1. VaunMakuza

    VaunMakuza

    Joined:
    Sep 20, 2012
    Posts:
    40
    Hello all!


    Trying to make a gun fire more of a clip out of a gun if you hold it down. Picture the laser from Halo, where you have to charge it before firing. In my case, the longer you hold it, the more damage it does when you release, but also more of the clip it eats up.

    TLDR; How can I get my laser to do different damage/ammo ussage dependent on how long someone holds down the fire button.

    I should specify using C#.

    Thanks!
     
    Last edited: Mar 17, 2013
  2. ardo314

    ardo314

    Joined:
    Jul 7, 2012
    Posts:
    345
    You could use GetButtonDown / GetKeyDown to start a timer. Then use GetButtonUp / GetKeyUp to fire the weapon considering the time you took to charge the weapon.
     
  3. VaunMakuza

    VaunMakuza

    Joined:
    Sep 20, 2012
    Posts:
    40
    That's what I was thinking.

    Something along these lines.

    Code (csharp):
    1. bool running = false;
    2. float timeElapsed = 0;
    3.  
    4. void Update()
    5. {
    6.      if(running)
    7.     {
    8.            timeElapsed += Time.deltaTime;
    9.     }
    10.  
    11. //Theeeeen in the input code do this stuff
    12.  
    13.     if(timeElapsed == 1)
    14.     {
    15.      // do the fireing
    16.     }
    17.     if (timeElapsed ==2)
    18.     {
    19.      // do the fireing based on 2 seconds passed
    20.      }
    21. etc etc
    22. }
    23.  
     
  4. justinlloyd

    justinlloyd

    Joined:
    Aug 5, 2010
    Posts:
    1,680
    Thought about it for a couple of minutes and came came up with the following code. There may be lurking bugs, I didn't give it a thorough testing but it should work for what you want.

    The ChargeGUI.cs is only useful for a quick display of the current charge and should be replaced with whatever effects you actually want.

    The ChargeInputHandlers.cs is for taking player input. You will want to change this to whatever your control scheme happens to be.

    Attach the three separate scripts to a GameObject or two and wire up the ChargeUp references in the ChargeUpInputHandler and ChargeGUI scripts.

    ChargeUp.cs
    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class ChargeUp : MonoBehaviour
    5. {
    6.     #region Event Declarations
    7.  
    8.     /// <summary>
    9.     /// Fired when the charge has been reset to zero
    10.     /// </summary>
    11.     public event ChargeResetHandler ChargeReset;
    12.     public delegate void ChargeResetHandler();
    13.  
    14.     /// <summary>
    15.     /// Fired when the charge is released, e.g. the player depresses the fire button
    16.     /// </summary>
    17.     public event ChargeReleasedHandler ChargeReleased;
    18.     public delegate void ChargeReleasedHandler(float charge);
    19.  
    20.     /// <summary>
    21.     /// Fired when the charge potential has reached maximum
    22.     /// </summary>
    23.     public event FullyChargedHandler FullyCharged;
    24.     public delegate void FullyChargedHandler(float charge);
    25.     /// <summary>
    26.     /// Fired when the charge potential has reached sufficient energy to be useful
    27.     /// </summary>
    28.     public event ReadyToReleaseHandler ReadyToRelease;
    29.     public delegate void ReadyToReleaseHandler(float charge);
    30.  
    31.     /// <summary>
    32.     /// Fired when the charging has begun, e.g. the player depresses the charge button
    33.     /// </summary>
    34.     public event ChargeStartedgHandler ChargeStarted;
    35.     public delegate void ChargeStartedgHandler();
    36.  
    37.     /// <summary>
    38.     /// Fired when the charging has stopped, e.g. the player releases the charge button
    39.     /// </summary>
    40.     public event ChargeStoppedHandler ChargeStopped;
    41.     public delegate void ChargeStoppedHandler();
    42.     #endregion
    43.  
    44.     #region Inspector Variables
    45.     /// <summary>
    46.     /// Should we automatically release the charge when it reaches maximum?
    47.     /// </summary>
    48.     [SerializeField]
    49.     protected bool m_autoFireAtMaximum;
    50.     /// <summary>
    51.     /// How quickly the charge will reach maximum potential, can be any positive value less than Maximum Charge Value
    52.     /// </summary>
    53.     [SerializeField]
    54.     protected float m_chargeRatePerSecond;
    55.     /// <summary>
    56.     /// Maximum permitted charge value, can be any positive value
    57.     /// </summary>
    58.     [SerializeField]
    59.     protected float m_maximumChargeValue;
    60.  
    61.     /// <summary>
    62.     /// Percentage to indicate the minimum value of charge required to fire
    63.     /// </summary>
    64.     [SerializeField]
    65.     protected float m_readyToFireAt;
    66.  
    67.     /// <summary>
    68.     /// Should the charge reset when told to stop but hasn't been fired?
    69.     /// </summary>
    70.     [SerializeField]
    71.     protected bool m_resetOnStop;
    72.  
    73.     /// <summary>
    74.     /// We can start the charge value at greater than zero
    75.     /// </summary>
    76.     [SerializeField]
    77.     protected float m_startChargeValue;
    78.  
    79.     #endregion
    80.  
    81.     #region Member Variables
    82.  
    83.     protected readonly string m_invokeReachedFullCharge;
    84.     protected readonly string m_invokeReachedReadyToFire;
    85.  
    86.     /// <summary>
    87.     /// When did we start tracking the charge up?
    88.     /// </summary>
    89.     protected float m_startTime;
    90.     #endregion
    91.  
    92.     public ChargeUp()
    93.     {
    94.         m_invokeReachedReadyToFire = new System.Action(ReachedReadyToFire).Method.Name;
    95.         m_invokeReachedFullCharge = new System.Action(ReachedFullCharge).Method.Name;
    96.     }
    97.  
    98.     #region Properties
    99.     public float CurrentCharge
    100.     {
    101.         get
    102.         {
    103.             if (!IsCharging)
    104.             {
    105.                 return (0.0f);
    106.             }
    107.  
    108.             return (Mathf.Clamp(1.0f / TimeToReachMaximumFromStart * ElapsedChargeTime * MaximumCharge, 0.0f, m_maximumChargeValue));
    109.         }
    110.  
    111.     }
    112.  
    113.     public float ElapsedChargeTime
    114.     {
    115.         get
    116.         {
    117.             if (!IsCharging)
    118.             {
    119.                 return (0.0f);
    120.             }
    121.  
    122.             return (Time.time - m_startTime);
    123.         }
    124.  
    125.     }
    126.  
    127.     public float MaximumCharge
    128.     {
    129.         get
    130.         {
    131.             return (m_maximumChargeValue);
    132.         }
    133.  
    134.         set
    135.         {
    136.             m_maximumChargeValue = value;
    137.         }
    138.  
    139.     }
    140.  
    141.     public float TimeToReachReadyFromStart
    142.     {
    143.         get
    144.         {
    145.             return ((m_maximumChargeValue - m_startChargeValue) * ReadyToFireAt / m_chargeRatePerSecond);
    146.         }
    147.  
    148.     }
    149.  
    150.     public float TimeToReachMaximumFromZero
    151.     {
    152.         get
    153.         {
    154.             return (m_maximumChargeValue / m_chargeRatePerSecond);
    155.         }
    156.  
    157.     }
    158.  
    159.     public float TimeToReachMaximumFromStart
    160.     {
    161.         get
    162.         {
    163.             return ((m_maximumChargeValue - m_startChargeValue) / m_chargeRatePerSecond);
    164.         }
    165.  
    166.     }
    167.  
    168.     public float TimeToReachMaximum
    169.     {
    170.         get
    171.         {
    172.             return ((m_maximumChargeValue - m_startChargeValue) / m_chargeRatePerSecond);
    173.         }
    174.  
    175.     }
    176.  
    177.     public bool IsCharging
    178.     {
    179.         get;
    180.         protected set;
    181.     }
    182.  
    183.     public bool IsFull
    184.     {
    185.         get
    186.         {
    187.             return (CurrentCharge >= m_maximumChargeValue);
    188.         }
    189.  
    190.     }
    191.  
    192.     public bool IsReady
    193.     {
    194.         get
    195.         {
    196.             return (CurrentCharge >= ReadyToFireAt);
    197.         }
    198.  
    199.     }
    200.  
    201.     public float ReadyToFireAt
    202.     {
    203.         get
    204.         {
    205.             return (m_readyToFireAt);
    206.         }
    207.  
    208.         set
    209.         {
    210.             m_readyToFireAt = value;
    211.         }
    212.  
    213.     }
    214.  
    215.     #endregion
    216.  
    217.     #region Unity Event Handlers
    218.     public void Awake()
    219.     {
    220.         System.Diagnostics.Debug.Assert(m_startChargeValue >= 0.0f  m_startChargeValue < m_maximumChargeValue);
    221.         System.Diagnostics.Debug.Assert(m_maximumChargeValue > 0.0f);
    222.         System.Diagnostics.Debug.Assert(m_readyToFireAt > 0.0f  m_readyToFireAt <= m_maximumChargeValue);
    223.         System.Diagnostics.Debug.Assert(m_chargeRatePerSecond > 0.0f  m_chargeRatePerSecond < m_maximumChargeValue);
    224.     }
    225.  
    226.     protected void Reset()
    227.     {
    228.         m_chargeRatePerSecond = 0.1f;
    229.         m_resetOnStop = false;
    230.         m_maximumChargeValue = 5.0f;
    231.         m_startChargeValue = 0.0f;
    232.         m_readyToFireAt = 0.5f;
    233.     }
    234.  
    235.     #endregion
    236.  
    237.     #region General Member Methods
    238.  
    239.     public void ReleaseCharge()
    240.     {
    241.         if (!IsReady)
    242.         {
    243.             return;
    244.         }
    245.  
    246.         FireChargeReleased();
    247.         StopCharging();
    248.     }
    249.  
    250.     public void StartCharging()
    251.     {
    252.         if (IsCharging)
    253.         {
    254.             return;
    255.         }
    256.  
    257.         m_startTime = Time.time;
    258.         Invoke(m_invokeReachedReadyToFire, TimeToReachReadyFromStart);
    259.         Invoke(m_invokeReachedFullCharge, TimeToReachMaximumFromStart);
    260.         IsCharging = true;
    261.         FireChargeStarted();
    262.     }
    263.  
    264.     public void StopCharging()
    265.     {
    266.         if (!IsCharging)
    267.         {
    268.             return;
    269.         }
    270.  
    271.         CancelInvoke();
    272.         IsCharging = false;
    273.         FireChargeStopped();
    274.     }
    275.  
    276.     public void ResetCharge()
    277.     {
    278.         CancelInvoke();
    279.         IsCharging = false;
    280.         FireChargeReset();
    281.     }
    282.     #endregion
    283.  
    284.     #region Event Dispatchers
    285.     protected void FireChargeReleased()
    286.     {
    287.         if (ChargeReleased != null)
    288.         {
    289.             ChargeReleased(CurrentCharge);
    290.         }
    291.  
    292.     }
    293.     protected void FireChargeReset()
    294.     {
    295.         if (ChargeReset != null)
    296.         {
    297.             ChargeReset();
    298.         }
    299.  
    300.     }
    301.  
    302.     protected void FireFullyCharged()
    303.     {
    304.         if (FullyCharged != null)
    305.         {
    306.             FullyCharged(CurrentCharge);
    307.         }
    308.  
    309.     }
    310.  
    311.     protected void FireReadyToRelease()
    312.     {
    313.         if (ReadyToRelease != null)
    314.         {
    315.             ReadyToRelease(CurrentCharge);
    316.         }
    317.  
    318.     }
    319.  
    320.     protected void FireChargeStarted()
    321.     {
    322.         if (ChargeStarted != null)
    323.         {
    324.             ChargeStarted();
    325.         }
    326.  
    327.     }
    328.  
    329.     protected void FireChargeStopped()
    330.     {
    331.         if (ChargeStopped != null)
    332.         {
    333.             ChargeStopped();
    334.         }
    335.  
    336.     }
    337.     #endregion
    338.  
    339.     #region Invoke Handlers
    340.     // responds to "Invoke"
    341.     protected void ReachedFullCharge()
    342.     {
    343.         FireFullyCharged();
    344.         if (m_autoFireAtMaximum)
    345.         {
    346.             ReleaseCharge();
    347.         }
    348.  
    349.     }
    350.  
    351.     // responds to "Invoke"
    352.     protected void ReachedReadyToFire()
    353.     {
    354.         FireReadyToRelease();
    355.     }
    356.     #endregion
    357.  
    358. }
    359.  
    360.  
    361.  
    ChargeUpInputHandler.cs
    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class ChargeUpInputHandler : MonoBehaviour
    5. {
    6.     #region Inspector Variables
    7.     [SerializeField]
    8.     protected ChargeUp m_chargeUp;
    9.     #endregion
    10.  
    11.     #region Unity Event Handlers
    12.  
    13.     protected void Reset()
    14.     {
    15.         // not efficient, but useful if you forget to set your reference in the inspector
    16.         m_chargeUp = GameObject.FindObjectOfType(typeof(ChargeUp)) as ChargeUp;
    17.     }
    18.  
    19.     protected void Update()
    20.     {
    21.         bool chargeEngaged = Input.GetButtonDown("Fire2");
    22.         bool chargeDisengaged = Input.GetButtonUp("Fire2");
    23.         if (chargeEngaged)
    24.         {
    25.             m_chargeUp.StartCharging();
    26.         }
    27.         else if (chargeDisengaged)
    28.         {
    29.             m_chargeUp.StopCharging();
    30.         }
    31.  
    32.         bool fired = Input.GetButtonDown("Fire1");
    33.         if (fired)
    34.         {
    35.             m_chargeUp.ReleaseCharge();
    36.         }
    37.  
    38.     }
    39.     #endregion
    40.  
    41. }
    42.  
    ChargeGUI.cs
    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4.  
    5. public class ChargeGUI : MonoBehaviour
    6. {
    7.     #region Inspector Variables
    8.     [SerializeField]
    9.     protected Color m_chargeFull;
    10.  
    11.     [SerializeField]
    12.     protected Color m_chargeReadyToRelease;
    13.  
    14.     [SerializeField]
    15.     protected ChargeUp m_chargeUp;
    16.  
    17.     [SerializeField]
    18.     protected Color m_chargeNormal;
    19.  
    20.     [SerializeField]
    21.     protected Color m_chargeStarted;
    22.  
    23.     #endregion
    24.  
    25.     protected Color m_colour;
    26.  
    27.     protected void Reset()
    28.     {
    29.         m_chargeNormal = Color.white;
    30.         m_chargeStarted = Color.cyan;
    31.         m_chargeReadyToRelease = Color.yellow;
    32.         m_chargeFull = Color.red;
    33.         // not efficient, but useful if you forget to set your reference in the inspector
    34.         m_chargeUp = GameObject.FindObjectOfType(typeof(ChargeUp)) as ChargeUp;
    35.     }
    36.  
    37.     protected void Start()
    38.     {
    39.         m_colour = m_chargeNormal;
    40.     }
    41.  
    42.     protected void OnChargeReleased(float charge)
    43.     {
    44.         m_colour = m_chargeNormal;
    45.         Debug.Log("Charge released " + charge);
    46.     }
    47.  
    48.     protected void OnFullyCharged(float charge)
    49.     {
    50.         Debug.Log("Fully charged! " + charge);
    51.         m_colour = m_chargeFull;
    52.     }
    53.  
    54.     protected void OnChargeStopped()
    55.     {
    56.         Debug.Log("Charging stopped");
    57.         m_colour = m_chargeNormal;
    58.     }
    59.  
    60.     protected void OnChargeStarted()
    61.     {
    62.         Debug.Log("Charging started");
    63.         m_colour = m_chargeStarted;
    64.     }
    65.  
    66.     protected void OnReadyToRelease(float charge)
    67.     {
    68.         Debug.Log("Ready to fire " + charge);
    69.         m_colour = m_chargeReadyToRelease;
    70.     }
    71.  
    72.  
    73.     #region Unity Event Handlers
    74.  
    75.     protected void OnDisable()
    76.     {
    77.         m_chargeUp.ChargeStarted -= OnChargeStarted;
    78.         m_chargeUp.ChargeStopped -= OnChargeStopped;
    79.         m_chargeUp.FullyCharged -= OnFullyCharged;
    80.         m_chargeUp.ReadyToRelease -= OnReadyToRelease;
    81.         m_chargeUp.ChargeReleased -= OnChargeReleased;
    82.     }
    83.  
    84.     protected void OnEnable()
    85.     {
    86.         m_chargeUp.ChargeStarted += OnChargeStarted;
    87.         m_chargeUp.ChargeStopped += OnChargeStopped;
    88.         m_chargeUp.FullyCharged += OnFullyCharged;
    89.         m_chargeUp.ReadyToRelease += OnReadyToRelease;
    90.         m_chargeUp.ChargeReleased += OnChargeReleased;
    91.     }
    92.  
    93.     protected void OnGUI()
    94.     {
    95.         GUI.color = m_colour;
    96.         GUI.Label(new Rect(25, 25, 200, 50), "Charge: " + m_chargeUp.CurrentCharge.ToString("N2"));
    97.         GUI.Label(new Rect(25, 75, 200, 50), "Elapsed Time: " + m_chargeUp.ElapsedChargeTime.ToString("N2"));
    98.     }
    99.     #endregion
    100.  
    101. }
    102.  
    103.