Car Footy

About

Car Footy is a homage to Rocket League. (Note this is not a commercial project, and purely for entertainment purposes).

As an avid Rocket League fan, I set out to create something that could emulate the feel of Rocket League in a more simplistic and portable capacity. I created this to challenge myself in terms of coding ability and as a test case using Proton to create a multiplayer experience.

Whilst I never intend to release this for public use, it has served as a fun little game that me and a few friends play!

I would love to be able to work with Psyonix (Now Epic) on creating a 2D version of Rocket League.

Play now!
Requires 2 players

Code Examples

PlayerSpawner.cs

using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerSpawner : MonoBehaviourPun
{
    [SerializeField] GameObject playerPrefab;
    [SerializeField] GameObject cameraPrefab;
    void Start()
    {
        Vector3 randomSpawn = new Vector3(Random.Range(-10, -5), 0, 0);
        GameObject playerRef = PhotonNetwork.Instantiate(playerPrefab.name, randomSpawn, Quaternion.identity);
        cameraPrefab.GetComponent<CamFollow>().SetTarget(playerRef);
    }
}

CarMovementNet.cs

using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CarMovementNet : MonoBehaviourPun
{
    [Header("Player Variables - Jump")]
    [SerializeField] float jumpHeight;
    [SerializeField] bool firstJump;
    [SerializeField] bool secondJump;
    [Header("Player Variables - Speed")]
    [SerializeField] float carSpeed;
    [SerializeField] float rotationSpeed;
    [SerializeField] float boost;
    [SerializeField] float boostForce;
    [SerializeField] float flipAmount;
    float angle;
    bool facingRight;
    [Header("Player Variables - Colliders")]
    [SerializeField] CircleCollider2D frontWheel;
    [SerializeField] CircleCollider2D rearWheel;
    [SerializeField] GameObject playerNose;
    bool isGrounded;
    [Header("Player Variables - Additional")]
    [SerializeField] GameObject boostGameObject;
    // Components
    Rigidbody2D rb;
    // Inputs
    float xIn;
    float yIn;
    [SerializeField] bool autoFlipEnabled;
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        isGrounded = true;
        facingRight = true;
        firstJump = true;
        secondJump = true;
        autoFlipEnabled = false;
        boost = 100;
    }
    private void Update()
    {
        if(photonView.IsMine)
        {
            xIn = Input.GetAxis("Horizontal");
            yIn = Input.GetAxis("Vertical");
            Vector3 angleCalculation = new Vector3(transform.position.x, transform.position.y + 1, transform.position.z) - transform.position;
            angle = Vector3.Angle(angleCalculation, transform.right);
            if (Input.GetKeyDown(KeyCode.LeftControl) && !autoFlipEnabled)
            {
                Flip();
            } // Manual Flip
            if (facingRight && transform.position.x > playerNose.transform.position.x && !isGrounded && autoFlipEnabled) // Face Direction
            {
                Flip();
            } // Autoflip Left
            if (!facingRight && transform.position.x < playerNose.transform.position.x && !isGrounded && autoFlipEnabled)
            {
                Flip();
            } // Autoflip Right
            if (frontWheel.GetComponent<WheelCollision>().IsColliding && rearWheel.GetComponent<WheelCollision>().IsColliding)
            {
                isGrounded = true;
                StartCoroutine(JumpReset());
            } // Ground Check (Both wheels)
            else
            {
                isGrounded = false;
                firstJump = false;
            } // Flying
            if (Input.GetKeyDown(KeyCode.Space))
            {
                Jump();
            } // Jump
        }        
    }
    void FixedUpdate()
    {
        if(photonView.IsMine)
        {
            if (yIn != 0 && isGrounded) // Drive
            {
                rb.AddForce((transform.right * yIn) * carSpeed, ForceMode2D.Force);
            }
            if (xIn != 0 && !isGrounded) // Rotate
            {
                if (!facingRight)
                {
                    rb.transform.Rotate(Vector3.forward * rotationSpeed * xIn);
                }
                else
                {
                    rb.transform.Rotate(Vector3.forward * -rotationSpeed * xIn);
                }
            }
            if (Input.GetKey(KeyCode.LeftShift)) // Boost
            {
                rb.AddForce(transform.right * boostForce, ForceMode2D.Force);
                boost--;
                boostGameObject.SetActive(true);
            }
            else
            {
                boostGameObject.SetActive(false);
            }
        }  
    }
    IEnumerator Flip(int time, int force)
    {
        yield return new WaitForSeconds(time);
    }
    IEnumerator JumpDelay()
    {
        yield return new WaitForSeconds(5.0f);
        if (!isGrounded)
        {
            secondJump = false;
        }
    }
    IEnumerator JumpReset()
    {
        yield return new WaitForSeconds(.1f);
        if (isGrounded)
        {
            firstJump = true;
            secondJump = true;
        }
    }
    void Jump()
    {
        if (firstJump && secondJump)
        {
            rb.AddForce(transform.up * jumpHeight, ForceMode2D.Force);
            firstJump = false;
        }
        else if (!firstJump && secondJump)
        {
            rb.AddForce(transform.up * jumpHeight, ForceMode2D.Force);
            secondJump = false;
        }
    } // Jump
    void Flip()
    {
        facingRight = !facingRight;
        transform.Rotate(Vector3.right * 180);
    }
    public void UpdateFlipMode(bool b)
    {
        autoFlipEnabled = b;
    }
    public void FacingRight()
    {
        facingRight = true;
    }
}

MainManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MainManager : MonoBehaviour
{
    UIManager _userInterface;
    CamFollow _cameraFollow;
    bool autoFlip;
    bool goal;
    [SerializeField] GameObject[] spawnLocations;
    [SerializeField] GameObject[] players;
    [SerializeField] GameObject ball;
    [SerializeField] GameObject ballSpawn;
    private void Start()
    {
        _userInterface = FindObjectOfType<UIManager>();        
        StartCoroutine(DelayFlipMode());
    }
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            _userInterface.PauseMenu();
            bool temp = _userInterface.ReturnFlipMode();
            if(autoFlip != temp)
            {
                autoFlip = temp;
                players[0].GetComponent<CarMovement>().UpdateFlipMode(autoFlip);
            }
        }
        if(goal)
        {
            StartCoroutine(ResetPitch());
            goal = false;
        }
    }
    IEnumerator DelayFlipMode()
    {
        yield return new WaitForSeconds(.1f);
        autoFlip = _userInterface.ReturnFlipMode();
        if(players.Length > 0)
        {
            players[0].GetComponent<CarMovement>().UpdateFlipMode(autoFlip);
        }
    }
    IEnumerator ResetPitch()
    {
        yield return new WaitForSeconds(0.1f);
        for (int i = 0; i < players.Length; i++)
        {
            players[i].transform.position = spawnLocations[i].transform.position;
            players[i].transform.GetComponent<Rigidbody2D>().velocity = new Vector3(0, 0, 0);
            players[i].transform.rotation = spawnLocations[i].transform.rotation;
            players[i].transform.GetComponent<CarMovement>().FacingRight();
        }
        ball.transform.GetComponent<Rigidbody2D>().velocity = new Vector3(0, 0, 0);
        ball.transform.GetComponent<Rigidbody2D>().angularVelocity = 0;
        ball.transform.rotation = Quaternion.Euler(new Vector3(0, 0, 0));
        ball.transform.position = ballSpawn.transform.position;
    }
    public void GoalScored()
    {
        goal = true;
    }
}

MainMenu.cs

using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class MainMenu : MonoBehaviourPunCallbacks
{
    [SerializeField] private GameObject findOpponentPanel = null;
    [SerializeField] private GameObject waitingStatusPanel = null;
    [SerializeField] private TextMeshProUGUI waitingStatusText = null;
    private bool isConnecting = false;
    private const string GameVersion = "0.1";
    private const int MaxPlayersPerRoom = 2;
    private void Awake() => PhotonNetwork.AutomaticallySyncScene = true;
    public void FindOpponent()
    {
        isConnecting = true;
        findOpponentPanel.SetActive(false);
        waitingStatusPanel.SetActive(true);
        waitingStatusText.text = "Searching...";
        if(PhotonNetwork.IsConnected)
        {
            PhotonNetwork.JoinRandomRoom();
        }
        else
        {
            PhotonNetwork.GameVersion = GameVersion;
            PhotonNetwork.ConnectUsingSettings();
        }
    }
    public override void OnConnectedToMaster()
    {
        Debug.Log("Connected To Master");
        if(isConnecting)
        {
            PhotonNetwork.JoinRandomRoom();
        }
    }
    public override void OnDisconnected(DisconnectCause cause)
    {
        waitingStatusPanel.SetActive(false);
        findOpponentPanel.SetActive(true);
        Debug.Log($"Disconnected due to: {cause}");
    }
    public override void OnJoinRandomFailed(short returnCode, string message)
    {
        Debug.Log("No clients are waiting for an opponent, creating new room...");
        PhotonNetwork.CreateRoom(null, new RoomOptions { MaxPlayers = MaxPlayersPerRoom });
    }
    public override void OnJoinedRoom()
    {
        Debug.Log("Client successfully joined aa room");
        int playerCount = PhotonNetwork.CurrentRoom.PlayerCount;
        if(playerCount != MaxPlayersPerRoom)
        {
            waitingStatusText.text = "Waiting For Opponent";
            Debug.Log("Client is waiting for an opponent");
        }
        else
        {
            waitingStatusText.text = "Opponent Found";
            Debug.Log("Match is ready to begin");
        }
    }
    public override void OnPlayerEnteredRoom(Player newPlayer)
    {
        if(PhotonNetwork.CurrentRoom.PlayerCount == MaxPlayersPerRoom)
        {
            PhotonNetwork.CurrentRoom.IsOpen = false;
            waitingStatusText.text = "Opponent Found";
            Debug.Log("Match is ready to begin");
            PhotonNetwork.LoadLevel("Main_Scene");
        }
    }
}

Invasion of the Southerners

About

Our hero Terry is enjoying life in God’s own county until he makes a shocking discovery. His quaint Yorkshire village has been invaded by... SOUTHERNERS. With his quick wits and smarts, can Terry uncover the identities of all the undercover southerners? Terry is the only hope in saving the villagers from these invaders who may be more sinister than meets the eye.

This game was originally thought up at a Yorkshire themed games jam. Myself, Harun Ali and Faisal Hussain came up with a comedic interpretation of invasion of the body snatchers, but instead we replaced the bodysnatchers with southerners. It in no way means any offense to anyone and is purely just for comedic value. I originally coded the entirety of the game produced for the game jam, but only worked on the combat mechanics for the rebuild.

The playable demo above is of the combat mechanics coded and designed by myself, to play the full first chapter, please visit:
Invasion of the Southerners - Chapter 1

Code Examples

ManagerGame.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ManagerGame : MonoBehaviour
{
    // Array of player objects, defined in editor
    [Header("Player Settings")]
    [SerializeField] GameObject[] playerPrefabs;
    // Referece to emptyy gameObject, where to create players
    [Header("Player Position References")]
    [SerializeField] Transform whereToSpawnPlayer;
    [SerializeField] float playerPositionRandomiseMin;
    [SerializeField] float playerPositionRandomiseMax;
    [Header("Enemy Settings")]
    [SerializeField] GameObject[] enemyPrefabs;
    [Header("Enemy Position References")]
    [SerializeField] Transform whereToSpawnEnemy;
    [SerializeField] float enemyPositionRandomiseMin;
    [SerializeField] float enemyPositionRandomiseMax;
    List<GameObject> players = new List<GameObject>(); // List of players
    List<GameObject> enemies = new List<GameObject>(); // List of players
    List<EntityInfo> attackQueue = new List<EntityInfo>(); // Attack Queue List
    List<AttackScript> attackList = new List<AttackScript>(); // List for storing individual attacks
    float rowNumber = 0;
    float rowOffset = 0;
    float posModifier = 0;
    float imageSize;
    public bool TmEnabled { get; set; }
    bool turnBeingTaken;
    UISystem uiSys;
    AudioManager aMan;
    SceneManagement sMan;
    void Start()
    {
        uiSys = FindObjectOfType<UISystem>();
        aMan = FindObjectOfType<AudioManager>();
        sMan = FindObjectOfType<SceneManagement>();
        // Player Spawning
        for (int i = 0; i < playerPrefabs.Length; i++)
        {
            if(playerPrefabs.Length == 1)
            {
                posModifier = 1;
            }
            if (i > 2)
            {
                rowNumber = 1;
                rowOffset = 2.5f;
            }
            imageSize = playerPrefabs[i].GetComponent<SpriteRenderer>().bounds.size.y;           
            Vector3 positionFix = new Vector3(whereToSpawnPlayer.position.x - rowNumber - Random.Range(playerPositionRandomiseMin, playerPositionRandomiseMax), 
            whereToSpawnPlayer.position.y + (imageSize / 2), (whereToSpawnPlayer.position.z + i) - rowOffset + posModifier);
            players.Add(playerPrefabs[i]);
            Instantiate(players[i], positionFix, Quaternion.identity);
            StartCoroutine(DelayStart(0.1f)); // BG Audio (Delayed Start, as the audio manager needs to be constructed prior to it being kicked off)
        }
        for (int i = 0; i < enemyPrefabs.Length; i++)
        {
            if (enemyPrefabs.Length == 1)
            {
                posModifier = 1;
            }
            if (i > 2)
            {
                rowNumber = 1;
                rowOffset = 2.5f;
            }
            imageSize = enemyPrefabs[i].GetComponent<SpriteRenderer>().bounds.size.y;
            Vector3 positionFix = new Vector3(whereToSpawnEnemy.position.x + rowNumber - Random.Range(playerPositionRandomiseMin, playerPositionRandomiseMax), 
            whereToSpawnEnemy.position.y + (imageSize / 2), (whereToSpawnEnemy.position.z + i) - rowOffset + posModifier);
            enemies.Add(enemyPrefabs[i]);
            Instantiate(enemies[i], positionFix, Quaternion.identity);
        }
        TmEnabled = true;
        turnBeingTaken = false;
    }
    private void Update()
    {
        if(attackQueue.Count > 0 && !turnBeingTaken)
        {
            if(attackQueue[0].GetComponent<EntityInfo>().gameObject.tag == "Enemy")
            {
                turnBeingTaken = true;;
                int randomAttack = Random.Range(0,attackList.Count);
                StartAttack(randomAttack);
            }
            else
            {
                turnBeingTaken = true;
                for (int i = 0; i < attackList.Count; i++)
                {
                    uiSys.CreateAttackButton(attackList[i].attackName, i);
                }
                uiSys.UiState(true);
                uiSys.SetName(attackQueue[0].GetComponent<EntityInfo>().ReturnPlayerName());
            }            
        }        
    }
    public void AddAttackToList(EntityInfo eI)
    {
        WinLossCheck();
        attackQueue.Add(eI);
        foreach (AttackScript atScript in eI.attacks)
        {
            attackList.Add(atScript);
        }        
    }
    public void StartAttack(int attackNumber)
    {
        GameObject[] opponentListTemp;
        List<EntityInfo> enInf = new List<EntityInfo>();
        if (attackQueue[0].gameObject.tag == "Enemy")
        {
            opponentListTemp = GameObject.FindGameObjectsWithTag("Player");
        }
        else
        {
            opponentListTemp = GameObject.FindGameObjectsWithTag("Enemy");
            aMan.PlaySound("Confirm");
        }
        for (int i = 0; i < opponentListTemp.Length; i++)
        {
            enInf.Add(opponentListTemp[i].GetComponent<EntityInfo>());
        }
        switch (attackList[attackNumber].attack)
        {
            case AttackScript.AttackType.Melee:
                attackQueue[0].MeleeMove(enInf[0].originPosition);
                StartCoroutine(AttackWait(attackList[attackNumber].attackTime));          
                break;
            case AttackScript.AttackType.Projectile:
                attackQueue[0].RangedAttack(enInf[0].originPosition);
                StartCoroutine(AttackWait(attackList[attackNumber].attackTime));
                break;
            case AttackScript.AttackType.Friendly:
                attackQueue[0].HealAttack();
                StartCoroutine(AttackWait(attackList[attackNumber].attackTime));
                break;
            default:
                break;
        }
        if (attackList[attackNumber].attack == AttackScript.AttackType.Friendly)
        {
            attackQueue[0].HealDamage(attackList[attackNumber].attackDamage);
        }
        else
        {
            enInf[0].TakeDamage(attackList[attackNumber].attackDamage, attackList[attackNumber].accuracy);
        }
    }
    void ExecuteAttack()
    {     
        attackQueue[0].ResetTurnMeter();
        attackQueue.RemoveAt(0);
        attackList.Clear();        
        turnBeingTaken = false;
        TmEnabled = true;
        WinLossCheck();
    }
    public IEnumerator DelayStart(float f)
    {
        yield return new WaitForSeconds(f);
        aMan.PlaySound("BG_Music");
    }
    public IEnumerator AttackWait(float g)
    {
        uiSys.UiState(false);
        yield return new WaitForSeconds(g);
        ExecuteAttack();
    }
    public void WinLossCheck()
    {
        GameObject CheckTeams = GameObject.FindGameObjectWithTag("Enemy");
        if(CheckTeams == null)
        {            
            uiSys.EndGame("Victory!");
            turnBeingTaken = true;
            sMan.LoadLevel(4);
        }
        CheckTeams = GameObject.FindGameObjectWithTag("Player");
        if (CheckTeams == null)
        {
            uiSys.EndGame("Fail...Restarting");
            turnBeingTaken = true;
            sMan.LoadLevel(3);
        }
    }  
    public void PlaySoundNow(string s)
    {
        aMan.PlaySound(s);
    }
}

AudioManager.cs

using UnityEngine;
[System.Serializable]
public class Sound
{
    public string soundID;
    public AudioClip sound;
    [Range(0f, 1.5f)]
    public float volume = 0.7f;
    [Range(0f, 1.5f)]
    public float pitch = 1f;
    [Range(0f, 0.5f)]
    public float randomVolume = 0.1f;
    public float randomPitch = 0.1f;
    private AudioSource soundSource;
    public void SetSource(AudioSource _source)
    {
        soundSource = _source;
        soundSource.clip = sound;
        soundSource.playOnAwake = false;
    }
    public void Play()
    {
        soundSource.volume = volume * (1 + Random.Range(-randomVolume / 2f, randomVolume / 2f));
        soundSource.pitch = pitch * (1 + Random.Range(-randomPitch / 2f, randomPitch / 2f));
        soundSource.Play();
    }
}
public class AudioManager : MonoBehaviour
{
    public static AudioManager instance;
    [SerializeField]
    Sound[] sounds;
    private void Awake()
    {
        if (instance != null)
        {
            Debug.LogError("More than one AudioManager in the scene");
        }
        else
        {
            instance = this;
        }
    }
    void Start()
    {
        for (int i = 0; i < sounds.Length; i++)
        {
            GameObject _go = new GameObject("Sound_" + i + "_" + sounds[i].soundID);
            _go.transform.SetParent(this.transform);
            sounds[i].SetSource(_go.AddComponent<AudioSource>());
        }
    }
    public void PlaySound(string _name)
    {
        for (int i = 0; i < sounds.Length; i++)
        {
            if (sounds[i].soundID == _name)
            {
                sounds[i].Play();
                return;
            }
        }
        // No sound with _name
        Debug.LogWarning("Audio Manager: Sound not found in list: " + _name);
    }
}

UISystem.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UISystem : MonoBehaviour
{
    [SerializeField] GameObject attackSelection;
    [SerializeField] GameObject buttonPrefab;
    [SerializeField] Text battleMessage;
    ManagerGame manGame;
    private void Start()
    {
        manGame = FindObjectOfType<ManagerGame>();
        battleMessage.text = "";
        attackSelection.SetActive(false);
    }
    public void UiState(bool enabled)
    {
        attackSelection.SetActive(enabled);
        if(!enabled)
        {
            for (int i = 0; i < attackSelection.transform.childCount; i++)
            {
                Destroy(attackSelection.transform.GetChild(i).gameObject);
            }
        }
    }
    public void CreateAttackButton(string playerName, int optionNumber)
    {
        GameObject go = Instantiate(buttonPrefab);
        go.transform.SetParent(attackSelection.transform, false);
        go.name = playerName + "Button";
        go.transform.GetChild(0).GetComponent<Text>().text = playerName;
        go.GetComponent<Button>().onClick.AddListener(() => { manGame.StartAttack(optionNumber); });
    }
    public void EndGame(string e)
    {        
        battleMessage.text = e;
        Time.timeScale = 0;
    }
}

Spaced Up

About

Spaced Up is a top down shooter, with comedic elements, power ups, puzzles and more. This game was originally created by myself, Harun Ali and Faisal Hussain. I originally coded the entirety of the initial demo, but was then unable to contribute to the project due to other commitments. The character and animation controllers are still using the system I designed. This also includes various other additions such as the the minimap, ingame floating UI, Enemy navigation and state handling and more.

The playable demo above is of the 8-way movement / animation controller. Other game mechanics have been removed as I unfortunately cannot discuss this in too much depth due to a NDA.

Code Examples

PlayerControlScript8way.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControlScript8way : MonoBehaviour
{
    // Variables accessible in editor
    [SerializeField]
    GameObject bullet;
    [SerializeField]
    float moveSpeed;
    [SerializeField]
    float fireRate;
    // Private bools
    bool isMoving;
    // Private Floats
    float updateTimer;
    float angleDif;
    float xPos; // x Position of character (stores xpos to update direction)
    float yPos; // y Position of character (stores ypos to update direction)
    // Private references
    Rigidbody2D rb;
    Animator an;
    // Private vectors
    //Vector2 lastMove; // Records the last movement to maintain idle state direction
    Vector2 moveInput; // Records input
    Vector2 moveVelocity; // Stores the moveInput * speed to adjust rigidbody velocity
    //Shoot directionals (Position)
    Vector3 northShotP = new Vector3(0.175f, 0.061f, 0f);
    Vector3 southShotP = new Vector3(-0.135f, -0.284f, 0f);
    Vector3 eastShotP = new Vector3(0.314f,-0.112f,0f);
    Vector3 westShotP = new Vector3(-0.409f, -0.1f, 0f);
    Vector3 neShotP = new Vector3(0.354f, 0.133f, 0f);
    Vector3 nwShotP = new Vector3(-0.252f, 0.13f, 0f);
    Vector3 seShotP = new Vector3(0.094f, -0.254f, 0f);
    Vector3 swShotP = new Vector3(-0.309f, -0.229f, 0f);
    //Shoot directionals (Rotation)
    Quaternion northShotR = new Quaternion(0,0,.7f,.7f);
    Quaternion southShotR = new Quaternion(0,0,-.7f,.7f);
    Quaternion eastShotR = new Quaternion(0,0,0,1f);
    Quaternion westShotR = new Quaternion(0,0,1f,0);
    Quaternion neShotR = new Quaternion(0,0,.4f,.9f);
    Quaternion nwShotR = new Quaternion(0,0,.9f,.4f);
    Quaternion seShotR = new Quaternion(0,0,.4f,-.9f);
    Quaternion swShotR = new Quaternion(0,0,.9f,-.4f);
    // Mouse Position
    Vector3 mPos;
    // Player Position
    Vector3 pPos;
    //Shoot position and rotation
    Vector3 shotPosition;
    Quaternion shotRotation;
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        an = GetComponent<Animator>();
    }
    void Update()
    {
        Movement();
        Aiming();
        Shooting();
        SetAnimatorVariables();
    }
    void FixedUpdate()
    {        
        rb.velocity = moveVelocity;
    }
    void Movement()
    {
        isMoving = false;
        if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)
        {
            isMoving = true;
            //lastMove = new Vector3(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
        }
        // Player Movement
        moveInput = new Vector3(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
        moveVelocity = moveInput * moveSpeed;
    }
    void SetAnimatorVariables()
    {
        an.SetFloat("MoveX", Mathf.Clamp(xPos, -1f, 1f)); // changed from hor input
        an.SetFloat("MoveY", Mathf.Clamp(yPos, -1f, 1f)); // changed from ver input
        an.SetFloat("LastMoveX", Mathf.Clamp(xPos, -1f, 1f)); // changed from lastMove.x
        an.SetFloat("LastMoveY", Mathf.Clamp(yPos, -1f, 1f)); // changed from lastMove.y   
        an.SetBool("IsMoving", isMoving);
    }
    void Aiming()
    {
        mPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        pPos = transform.position;
        Vector2 difference = pPos - mPos;
        float sign = (pPos.y < mPos.y) ? -1.0f : 1.0f;
        angleDif = Vector2.Angle(Vector3.right, difference) * sign;
        // North
        if (angleDif < -67.5 && angleDif > -122.5)
        {
            shotPosition = new Vector3 (northShotP.x + transform.position.x, northShotP.y 
            + transform.position.y, northShotP.z + transform.position.z);
            shotRotation = northShotR;
            xPos = 0f;
            yPos = 1f;
        }
        // South
        if (angleDif > 67.5 && angleDif < 122.5)
        {
            shotPosition = new Vector3(southShotP.x + transform.position.x, southShotP.y 
            + transform.position.y, southShotP.z + transform.position.z);
            shotRotation = southShotR;
            xPos = 0f;
            yPos = -1f;
        }
        // East (Requires two because of how angles are handled)
        if (angleDif < 180 && angleDif > 157.5)
        {
            shotPosition = new Vector3(eastShotP.x + transform.position.x, eastShotP.y 
            + transform.position.y, eastShotP.z + transform.position.z);
            shotRotation = eastShotR;
            xPos = 1f;
            yPos = 0f;
        }
        if (angleDif > -180 && angleDif < -157.5)
        {
            shotPosition = new Vector3(eastShotP.x + transform.position.x, eastShotP.y 
            + transform.position.y, eastShotP.z + transform.position.z);
            shotRotation = eastShotR;
            xPos = 1f;
            yPos = 0f;
        }
        // West (Requires two because of how angles are handled)
        if (angleDif < 22.5 && angleDif > 0)
        {
            shotPosition = new Vector3(westShotP.x + transform.position.x, westShotP.y 
            + transform.position.y, westShotP.z + transform.position.z);
            shotRotation = westShotR;
            xPos = -1f;
            yPos = 0f;
        }
        if (angleDif > -22.5 && angleDif < 0)
        {
            shotPosition = new Vector3(westShotP.x + transform.position.x, westShotP.y 
            + transform.position.y, westShotP.z + transform.position.z);
            shotRotation = westShotR;
            xPos = -1f;
            yPos = 0f;
        }
        // NE -135
        if (angleDif < -112.5 && angleDif > -157.5)
        {
            shotPosition = new Vector3(neShotP.x + transform.position.x, neShotP.y 
            + transform.position.y, neShotP.z + transform.position.z);
            shotRotation = neShotR;
            xPos = 1f;
            yPos = 1f;
        }
        // NW -45
        if (angleDif < -22.5 && angleDif > -67.5)
        {
            shotPosition = new Vector3(nwShotP.x + transform.position.x, nwShotP.y 
            + transform.position.y, nwShotP.z + transform.position.z);
            shotRotation = nwShotR;
            xPos = -1f;
            yPos = 1f;
        }
        // SE 135
        if (angleDif > 112.5 && angleDif < 157.5)
        {
            shotPosition = new Vector3(seShotP.x + transform.position.x, seShotP.y 
            + transform.position.y, seShotP.z + transform.position.z);
            shotRotation = seShotR;
            xPos = 1f;
            yPos = -1f;
        }
        // SW 45
        if (angleDif > 22.5 && angleDif < 67.5)
        {
            shotPosition = new Vector3(swShotP.x + transform.position.x, swShotP.y 
            + transform.position.y, swShotP.z + transform.position.z);
            shotRotation = swShotR;
            xPos = -1f;
            yPos = -1f;
        }        
    }
    void Shooting()
    {
        if (Input.GetButton("Fire1") && Time.time > updateTimer)
        {
            updateTimer = Time.time + fireRate;
            Instantiate(bullet, shotPosition, shotRotation);
        }
    }
}