streamlining code tutorial

Streamlining Code For Unity MMO: Free Tutorial #7 Multiplayer Game

Unity 3D MMO Tutorial Series

Welcome to the streamlining code tutorial #7 for the Unity MMO series. This tutorial will streamline the code to make it more readable and manageable. There are a lot of easier ways to design the code to optimize for efficiency. It is NOT necessary to do this tutorial! This is just informational because we will put the original code back in tutorial #9. If you have not finished tutorial #6, click here. If you are looking to start this series, go here.

What Does it Mean to Streamline Code?

Optimized code runs more smoothly, is easier to understand, and follows a more logical structure. You accomplish this by removing unnecessary or useless parts and organizing the remaining code to make it more straightforward to read and use. Streamlining a program’s code can improve performance by making it easier to read and understand, less prone to bugs, and more amenable to revisions. We may achieve this using coding standards and practices like design patterns and refactoring.

What In Ternary?

Today’s word is “ternary.” The word “ternary” comes from the Latin word “ternarius,” which means “made up of three parts.” We use it as a shorthand for a simple if-else statement and can also use it as a shorthand to assign a value to a variable based on a condition. A ternary operator is a shorthand way to write an if-else statement with three operands. Learn more about the Ternary Operator.

In other words, the ternary operator is a shorthand way to write a simple if-else statement that gives a value to a variable based on a condition. The “? :” symbols represent the ternary operator.

Remove the contents of the “Locomotion” method and add this first line of code inside:

public void Locomotion()
{
    float speed = walkSpeed * (run ? runSpeed : 1);
}

This code will assign a value to the variable “speed” based on the value of the “run” variable. The ternary operator ? : is used to check the value of the “run” variable.

The syntax of the ternary operator is like this :

(condition) ? (value if true) : (value if false)

In this case, we check the condition of “run,” a boolean variable (either true or false).

  • If “run” is true, then the value of “speed” will be equal to “walkSpeed” multiplied by “runSpeed.”
  • If “run” is false, then the value of “speed” will be equal to “walkSpeed” multiplied by 1, which is equivalent to just “walkSpeed.”

Therefore, this line of code is equivalent to the following if-else block.

if(run)
{
   speed = walkSpeed * runSpeed;
}
else
{
    speed = walkSpeed;
}

It’s shorter and more readable. We will use the final value of “speed” to determine the character’s movement velocity.

Streamlining the Animation Code

We have to put our animation code back in, but we will also streamline that. Under the code we just added, type this in:

animator.SetFloat("Player Locomotion", (movementInputs.x == 0 && movementInputs.y == 0) ? 0 : (run ? 1 : 0.5f));

This code line sets the value of the “Player Locomotion” parameter in an animator component. The animator.SetFloat method takes two arguments, the first is the name of the float parameter you want to set, and the second is the value you want to set it to.

Here, the first argument is “Player Locomotion,” which is the name of the float parameter that you want to set. The second argument is a ternary operator that assigns a value to the “Player Locomotion” parameter based on the values of “movementInputs.x” and “movementInputs.y” and “run” variables.

In this case, the condition being checked (movementInputs.x == 0 && movementInputs.y == 0) checks if both movementInputs.x and movementInputs.y is equal to 0.

  • When the condition is true, indicating that the player is not moving, the code sets the value of the “Player Locomotion” parameter to 0.
  • If the condition is false, it means the player is moving, and then it checks the value of the “run” variable,
    • When “run” is true, the code sets the value of the “Player Locomotion” parameter to 1.
    • When “run” is false, the code sets the value of the “Player Locomotion” parameter to 0.5f.

In short, this line of code sets the value of the “Player Locomotion” parameter in an animator component based on whether or not the player is moving, and if they are moving, whether they are running or walking.

Streamlining the Input Code

The “GetInput” method receives the most benefit from streamlining. We will condense the long code block to just three lines. Add these lines of code in place of your “GetInput()” method:

 public void GetInputs()
    {
        movementInputs.y = (Input.GetKey(baseControls.forward) ? 1 : (Input.GetKey(baseControls.backward) ? -1 : 0));
        movementInputs.x = (Input.GetKey(baseControls.strafeRight) ? 1 : (Input.GetKey(baseControls.strafeLeft) ? -1 : 0));
        rotation = (Input.GetKey(baseControls.rotateRight) ? 1 : (Input.GetKey(baseControls.rotateLeft) ? -1 : 0));
    }

The first line of code is using the ternary operator to assign a value to the “movementInputs.y” variable based on the state of the “baseControls.forward” and “baseControls.backward” keys. Furthermore, the concept of the streamlined code is the same as the “Locomotion()” code previously rewritten in this tutorial.

What It Means

Here, the condition being checked is Input.GetKey(baseControls.forward).

  • When the condition is true, indicating that the “baseControls.forward” key is pressed, the code sets the value of “movementInputs.y” to 1.
  • If the condition is false, it means the “baseControls.forward” key is not pressed, then it checks the state of the “baseControls.backward” key by the second ternary operator. Input.GetKey(baseControls.backward) ? -1 : 0.
    • If the “baseControls.backward” key is pressed, the value of “movementInputs.y” will be set to -1.
    • If the “baseControls.backward” key is not pressed, the value of “movementInputs.y” will be set to 0.

As before, this line of code uses a ternary operator to check the state of the “baseControls.forward” and “baseControls.backward” keys and assigns the appropriate value to “movementInputs.y” based on the state of these.

The other two lines of code handle strafing left and right and character rotation similarly.

About Ridgidbody

Another thing about the “PlayerControls” method is to remove the “Ridgidbody rb;” and the “rb = GetComponent<Ridgidbody>();.” We don’t need those as we have created our own gravity. Also, delete the Ridgidbody component from the player character.

The last thing to do is move this if statement:

 if (mouseMovementControls.leftAndRightMouseButtons)
 {
     movementInputs.y = 1;
 }

Place the if statement right below the line “float speed = walkSpeed * (run ? runSpeed : 1);” in the “Locomotion()” method.

Placing it at the method’s top processes the forward movement input ahead of any other calculations or movements. This promptly updates the character’s movement with new input, leading to a more responsive and smooth motion.

In other words, the animation won’t work using mouse movements because of the linear structure of the code.

On to the Mouse Hunt!

We can streamline “MouseMovementControls.cs” a bit as well. There are a few redundant lines that do not need to be there.

We can streamline this code in a few ways:

  • You can remove the Awake() function since it is empty and not doing anything.
  • The player “GameObject” variable is not being used. It can be removed.
  • The isLeftMouseButtonHeld and isRightMouseButtonHeld variables can be combined into a single variable indicating whether either button is held.
  • The “leftAndRightMouseButtons” variable can be removed, as it is redundant and not being used.
  • Instead of checking if the left and right mouse buttons are held, you can use the Input.GetMouseButtonDown() function, which will only return true when the button is first pressed rather than every frame it is held.
  • Remove the characterAngle declaration. It’s no longer needed.

Here is the new “GetMouseControls()” code block:

void GetMouseControls()
    {
        isLeftMouseButtonHeld = Input.GetMouseButton(0);
        isRightMouseButtonHeld = Input.GetMouseButton(1);
        if (isRightMouseButtonHeld)
        {
            character.localRotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * mouseRotateSpeed * Time.deltaTime, 0);
        }
        leftAndRightMouseButtons = isLeftMouseButtonHeld && isRightMouseButtonHeld;
    }

This function uses the Input.GetMouseButton(0) and Input.GetMouseButton(1) To check if the left and right mouse buttons are held, respectively. However, when the user holds down the right mouse button, the system applies the rotation to the character by multiplying its current rotation with a Quaternion representing the additional rotation. This enables a smooth character rotation in response to the user’s input. The rotation is calculated using the Input.GetAxis("Mouse X") to get the mouse x movement and multiply it by the mouseRotateSpeed and Time.deltaTime.

The “leftAndRightMouseButtons” variable is set based on whether both the left and right mouse buttons are held or not, this line “leftAndRightMouseButtons = isLeftMouseButtonHeld && isRightMouseButtonHeld;” does this job without the need for an if statement

It eliminates the need for the characterAngle variable and the isLeftMouseButtonHeld assignment inside the if statement, which is not necessary because the value is already assigned to the isLeftMouseButtonHeld variable.

The Full Monty

Here is the complete code for the “MouseMovementControls.cs” class:

using UnityEngine;
public class MouseMovementControls : MonoBehaviour
{
    public bool isLeftMouseButtonHeld = false;
    public bool isRightMouseButtonHeld = false;
    public bool leftAndRightMouseButtons = false;
    public float mouseRotation;
    public float mouseRotateSpeed = 5000f;
    public Transform character;
    void Update()
    {
        GetMouseControls();
    }
    void GetMouseControls()
    {
        isLeftMouseButtonHeld = Input.GetMouseButton(0);
        isRightMouseButtonHeld = Input.GetMouseButton(1);
        if (isRightMouseButtonHeld)
        {
            character.localRotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * mouseRotateSpeed * Time.deltaTime, 0);
        }
        leftAndRightMouseButtons = isLeftMouseButtonHeld && isRightMouseButtonHeld;
    }
}

We’ve condensed quite a lot of code down to a few short code blocks. I hope you enjoyed this streamlining code tutorial. The next tutorial will create the camera follow system from scratch! This will be a fun tutorial, so get ready!

Until next time, May The Force Be With You, Always. – Dragon

Check out these cool Low Poly Assets on the Unity Asset Store!

Tagged

Leave a Reply

Your email address will not be published. Required fields are marked *