Dank
Dank

Reputation: 11

Would like advice on SOLID principles in my Unity C# script

I am working to understand SOLID, and want to know how my Unity C# script could be better formatted to align with the principles. I will provide the script and then an explanation:

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

public class PlayerMovement : MonoBehaviour
{

    public CharacterController controller;

    public float speed = 12f;
    public float gravity = -9.81f;
    Vector3 velocity;

    public Transform groundCheck;
    public float groundDistance = 0.4f;
    public LayerMask groundMask;
    private bool isGrounded;

    void Update()
    {
        GroundCheck();
        Movement();
        Gravity();
    }

    private void GroundCheck()
    {
        isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);

        if(isGrounded && velocity.y < 0)
        {
            velocity.y = -2f;
        }
    }

    private void Movement()
    {
        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");

        Vector3 move = transform.right * x + transform.forward * z;

        controller.Move(move * speed * Time.deltaTime);
    }

    private void Gravity()
    {
        velocity.y += gravity * Time.deltaTime;
        controller.Move(velocity * Time.deltaTime);
    }
}

This is a script that handles movement of a character, but additionally performs ground checks and gravity of the player. I have seen interfaces used when adding new functionality, and new classes as well in the same script, but I thought for the purposes of this code it would be best to separate each functionality into a function and have them all call from update of the PlayerMovement class. I decided to use one class because I was wary of running three classes with three Update methods in this one script for performance reasons. Is there a better way I should approach the organization of this script from a SOLID point of view? My thought process was that if I wanted to extend these functionalities I would be able to do so in each function, and if I needed new functionality I could create more functions.

Upvotes: 0

Views: 594

Answers (1)

Lovro Bubanic
Lovro Bubanic

Reputation: 11

you can have one separate class that has the GroundCheck(), Movement(), Gravity() methods, and then you can access that class from the PlayerMovement class. if you make your methods static you will be able to access them. And that way you will have your public and private fields in PlayerMovement class and Update() method. So you call the methods in Update() and add the needed arguments in the brackets.

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

public class PlayerMovement : MonoBehaviour
{

    public CharacterController controller;

    public float speed = 12f;
    public float gravity = -9.81f;
    Vector3 velocity;

    public Transform groundCheck;
    public float groundDistance = 0.4f;
    public LayerMask groundMask;
    private bool isGrounded;
    
    Movement movement;

    void Start()
    {
        movement = FindObjectOfType<Movement>();
    }
    void Update()
    {
        movement.GroundCheck(isGrounded, groundCheck, groundDistance, groundMask, velocity);
        movement.Movement(this.gameObject, controller, speed);
        movement.Gravity(velocity, gravity, controller);
    }   
}


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

public class Movement : MonoBehaviour
{
    static public void GroundCheck(bool isGrounded, Transform groundCheck, float groundDistance, LayerMask groundMask, Vector3 velocity)
    {
        isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);

        if(isGrounded && velocity.y < 0)
        {
            velocity.y = -2f;
        }
    }

    static public void Movement(GameObject playerMovement, CharacterController controller, float speed)
    {
        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");

        Vector3 move = playerMovement.transform.right * x + playerMovement.transform.forward * z;

        controller.Move(move * speed * Time.deltaTime);
    }

    static public void Gravity(Vector3 velocity, float gravity, CharacterController controller)
    {
        velocity.y += gravity * Time.deltaTime;
        controller.Move(velocity * Time.deltaTime);
    }
}

Upvotes: 1

Related Questions