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

Best way to organize guns for an FPS

Discussion in 'Scripting' started by ConnorBaltich, May 8, 2020.

  1. ConnorBaltich

    ConnorBaltich

    Joined:
    Nov 4, 2016
    Posts:
    10
    So I have a base class for a Gun. I have the basic info that each gun will have contained in this class. However, I want to know the best way to shoot these guns. Since some are going to be automatic and since some will be semi-automatic etc. I don't want to have to do a check every frame to see what type of firing the gun needs to. On my player game object, I have a spot for the current gun which is an instance of the gun class therefore I can put any inheriting class in it. So what would be the most efficient way to call a shooting method for different types of guns?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    That's going to be a single integer compare, or a string compare if you insist. Trust me, just preparing to decide to call each one of your Update() functions each frame takes more grinding than that!!

    Do NOT optimize until a) you have a problem, and b) you attached a profiler to measure the problem.

    As for how to do it, handle it all within scripts on each GameObject, then turn off all the guns you're not using, turn the one on that you are... that's always going to be the cleanest setup.
     
    Last edited: May 8, 2020
    Joe-Censored likes this.
  3. kirbygc00

    kirbygc00

    Joined:
    Apr 4, 2016
    Posts:
    50
    Hey ConnorBaltich,

    This sounds like a great use of the state pattern: https://gameprogrammingpatterns.com/state.html.
    • On the player script send your input to the Gun
    • Each gun has multiple states (idle / firing / reloading )
    • Have each gun implements it's own HandleUpdate which is called from the player's update method
    • If the input contains the fire command on a gun state which should fire, that gun will proxy the call to it's own Fire method
    For example, AK47's firing state would handle the fire button being continuously pressed down by staying in the fire state / firing more bullets... wheras a glock would ignore that input, cycle directly back into idle.

    Cheers =)
     
    ConnorBaltich likes this.
  4. ConnorBaltich

    ConnorBaltich

    Joined:
    Nov 4, 2016
    Posts:
    10
    In case anyone is interested here is what I did. I created an interface called IShooting, next I had the semi auto and auto classes use the interface. the interface has a handleUpdate method which is called from the playerController. I will definitely be implementing the states suggested by Kirby later in development.

    Heres some examples of how I did things

    This is an automatic gun class

    Code (CSharp):
    1. public class AutoGun : Gun, IShooting
    2. {
    3.     public void HandleUpdate()
    4.     {
    5.         if (Input.GetButton("Fire1"))
    6.         {
    7.             Debug.Log("AUTO FIRE");
    8.         }
    9.     }
    10. }
    Heres the interface
    Code (CSharp):
    1. public interface IShooting
    2. {
    3.     void HandleUpdate();
    4. }
    5.  
    Finally here's how it is called from the playerController
    Code (CSharp):
    1. ((IShooting)currentGun).HandleUpdate();
    The currentGun variable is just a slot for the Gun class which semiAuto and Auto extend
    This works well for me and thanks for everyone's help =)


    Also this is my Gun class in case there is any confusion
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using static PlayerController;
    5.  
    6. public class Gun : MonoBehaviour
    7. {
    8.     [Header("Info")]
    9.     public new string name;
    10.     public float reloadTime = .5f;
    11.     public Transform barrelPosition;
    12.  
    13.     [Header("Magazine")]
    14.     public float fireRate = .3f;
    15.     public int clipSize = 30;
    16.  
    17.     [Header("Damage")]
    18.     public float baseDamage = 100;
    19.  
    20.     [HideInInspector]
    21.     public float lastShot = 0;
    22.     [HideInInspector]
    23.     public int leftInClip = 1;
    24.     [HideInInspector]
    25.     public Rigidbody rb;
    26.  
    27.     private void Start()
    28.     {
    29.         rb = GetComponent<Rigidbody>();
    30.     }
    31. }
     
    kirbygc00 likes this.
  5. ConnorBaltich

    ConnorBaltich

    Joined:
    Nov 4, 2016
    Posts:
    10
    I appreciate the response, but the question wasn't so much about optimization, it was more that I knew there was a cleaner way to do it than a bunch of if-else statements. But I will keep your advice on optimization in mind. Much thanks!
     
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Checking this every frame is extremely trivial processing wise.
    I would likely have just done a switch statement and moved on to the next thing in the project. Efficiency in development isn't just about efficiency of your code, but also efficiency in your time spent on the code. The more time you dwell on trivial issues, the less game you are producing, effectively lost opportunity to either make more games or make this game objectively better in the same amount of time. My 2 cents
     
    Kurt-Dekker likes this.
  7. ConnorBaltich

    ConnorBaltich

    Joined:
    Nov 4, 2016
    Posts:
    10
    I know. like I said it wasn't so much about optimization. I just figured there was a better and easier way to be able to quickly create more gun types. I know a few extra if statements are going to have basically no impact on the performance. I just wanted to take the time to see if there was a system out there. But I really do need to work on approaching problems more like you said lol.
     
    Joe-Censored likes this.
  8. newjerseyrunner

    newjerseyrunner

    Joined:
    Jul 20, 2017
    Posts:
    966
    I have a single Boolean member of my weapon interface. It represents whether or not the player is pulling the trigger. All behavior regarding what to do is in the gun itself. No if statements, just polymorphism.
     
    ConnorBaltich and mopthrow like this.
  9. ConnorBaltich

    ConnorBaltich

    Joined:
    Nov 4, 2016
    Posts:
    10
    Thats actually what I have right now. Since the post a lot progress has been made and I have a Shoot() method in the gun class, so in each other class like Auto, Semi-Auto, and Burst, they handle the input and just call the method from Gun because they inherit from it.
     
  10. kirbygc00

    kirbygc00

    Joined:
    Apr 4, 2016
    Posts:
    50
    Glad you made some good progress on this! Let us know if you run into any blockers or want to share some code =)
     
  11. ConnorBaltich

    ConnorBaltich

    Joined:
    Nov 4, 2016
    Posts:
    10
    Thanks! I have a nice system for attachments now too. I just need a good way to render the gun and hands with a separate fov and make it so they don't clip.

    Using the hdrp. I dislike the fps sample's method I really just want a replacement for what the old renderer had.
     
    Last edited: May 25, 2020