Writing the character code and connecting the PlayerInput class to it

The last stage of the character is its code class. The code class will receive input from the PlayerInput class we wrote earlier, so the character can be controlled through the input and filter out the type of GameObjects that collided with from the parent of that collider type.

Perform the following steps:

To start with, navigate to the Assets/Scripts folder and right-click on it. Select Create and then C# Script. Name it Character.

Next, we need to give our PlayerInput class a reference to our character. To perform this, navigate to the Assets/Scripts folder and double-click on the PlayerInput.cs file to open it.

At the top of the class, under the SimpleTouch struct, add the following code:

    public Character GameCharacter;

We also need to tie the function that will call GameCharacter when PlayerInput gets a new one. At the bottom of the CalculateTouchInput function, add the following code:

        if (GameCharacter != null)
        {
          if (!GameCharacter.isDead)
          {
            GameCharacter.RecieveInput(touchDistance, touchDirection);
          }
        }

Character attributes

At the top of the Character class, we need to add the bool value that will be used to know whether a character is jumping or not and if a character is dead or alive; we need an int value to know how many coins a character has and if a character should be fading out. The isJumping bool will be used in the code that we will write to know when the character jumps from the SimpleTouch type of PlayerInput. Finally, we will store references to GameCharacterSprite and CharacterRigidBody so that we can use them through the use of this class. Add the following code before the Start function:

    [System.NonSerialized]
    public bool isJumping;

    [System.NonSerialized]
    public bool isDead;

    [System.NonSerialized]
    public int CoinCount;

    [System.NonSerialized]
    public Vector3 RestartLocation;

    private bool isFadeOut;

    SpriteRenderer GameCharacterSprite;

    Rigidbody2D CharacterRigidBody;

    Animator CharacterAnimator;

Tip

[Sytem.NonSerialized] is a way to declare a public variable and have Unity ignore it when it populates the exposed component variables. It means that isJumping won't show up in the component list of variables in the editor. It will also prevent this variable from being serialized. Serialization is the process of converting an object to a stream of bytes so that it can be transmitted into memory.

To explain more, let's understand the following terms:

  • isJumping: This is the bool value to let both the class and the animator know if the character is jumping. True is jumping, whereas false is not jumping.
  • isDead: This is a bool value that does exactly what the isJumping bool does only to check whether the player is dead or not. Again, true is dead, whereas false is not dead.
  • CoinCount: This specifies how many coins the player has collected. Later on, we will store this value so it doesn't reset every time the player restarts the game.
  • RestartLocation: This denotes the Vector3 location that we can use to reset the character to after they have died.
  • IsFadeOut: This is a bool that transitions the character from an opaque state to a translucent state. True is fading to translucent, whereas false is fading to opaque.
  • GameCharacterSprite, CharacterRigidBody, and CharacterAnimator: These are references that we can keep, so we don't have to keep getting them. GameCharacterSprite is the sprite sheet, CharacterRigidBody is Rigidbody 2D for the character, and CharacterAnimator is the animation tree for the character.

To set some of these values, we can use the Start function. Add the following code in the Start function:

  // Use this for initialization
  void Start ()
  {
    RestartLocation = gameObject.transform.position;
    GameCharacterSprite = gameObject.GetComponent<SpriteRenderer>( );
    CharacterRigidBody = gameObject.GetComponent<Rigidbody2D>( );
    CharacterAnimator = gameObject.GetComponent<Animator>( );
  }

This allows you to use all of these references in the other code for this class without having to use the GetComponent function again and again.

PlayerInput

Now, we know that we have to have a couple things for character to be functional. Character needs to take the SimpleInput struct data from PlayerInput so that it knows how to move, and the character needs a function to know when it has collided with another GameObject that has a collider.

Under the Update function in the Character class, add the following functions:

    // Get input data from PlayerInput
    public void RecieveInput(float Distance, Vector2 Direction)
    {
      if (CharacterRigidBody != null && CharacterAnimator != null )
      {
        Direction.x = 0.0f;
        if (Direction.y > 0.0f && !isJumping)
        {
          CharacterRigidBody.AddForce(Direction * Mathf.Clamp(Distance, 0, 200));

          CharacterAnimator.SetBool("Jump", true);
          isJumping = true;
        }
        else if ( Direction.y < 0.0f )
        {
          CharacterRigidBody.AddForce(Direction * Mathf.Clamp(Distance, 0, 250));
        }
      }
    }

    // When the character collides with another GameObject
    void OnCollisionEnter2D(Collision2D Col)
    {
      if (CharacterAnimator != null)
      {
        CharacterAnimator.SetBool("Jump", false);
        isJumping = false;
      }
    }

The RecieveInput function takes the parameters, the distance of the player's swipe, and the direction of the player's swipe. We need the distance in order to know how "hard" the player swiped on the screen, and we need the direction to know whether the player swiped up or down.

When we receive this data from PlayerInput, we then need to get ready to use it. To begin, we need a reference to the Character GameObject's Rigidbody 2D component. To have this, we will use gameObject.GetComponent<Rigidbody2D>( ) and store it in a local variable named characterRigidBody.

We will also need a reference to the animator on character that holds the controller. The controller holds the Jump variable, which we will set when the character jumps.

We then check to make sure that characterRigidBody is something by checking that it is not null; null meaning empty. We also perform the same for characterAnimator.

If we have a reference in characterRigidBody to GameObject's Rigidbody 2D, we start by making sure that the X axis in Swipe is set to 0. This means that the direction will only be up and down, so the player can't jump forward or backward.

We then check whether the Y axis on the Direction parameter is more than 0.0, meaning the player swiped up if the character is not already jumping. If this is true, we will add a force to the Rigidbody2D character.

AddForce takes two arguments: the direction the force needs to be and how much force to apply to Rigidbody 2D. For us, the direction has already been given and altered. The force amount is calculated using Mathf.Clamp( ).

Mathf.Clamp( ) is a way to make sure that the force value is within bounds. If we let the distance decide how much force is added to the character always, the character would go shooting off into space if the player swiped the entire screen of their device. So, we will use the clamp function to check whether the swipe distance is less than 200 and use this value. If the swipe distance is more than 200, clamp it down to 200.

After Rigidbody2D character has a force, we want to update the controller so that it knows to switch to the jumping animation. We do this by setting the Jump bool value to true with the stored reference set earlier in the function and check to make sure that it exists.

As the character needs to know whether it is jumping, we will set isJumping to true here as well. This way if the player tries to swipe while character is already jumping, the condition we have will fail. Also, there will be no force added in the positive Y axis. If we didn't have this check, the player would be able to swipe continuously. Also, the character would continue to jump higher and higher.

If the first condition that checks whether the direction of the swipe is in positive Y and if character is not jumping fails, we check whether the direction of the swipe is in negative Y. The reason we don't check isJumping here is because it doesn't matter if we swipe down if the player is or isn't currently jumping. If Character is already on the ground, it can't go farther down, and if the character is jumping, a force downwards will make it fall to the ground faster, which is intended in design.

The OnCollisionEnter2D function is a Unity function designed to manage what happens when colliders collide.

OnCollisionEnter2D takes a single parameter: the collider that was collided with. For the moment, the only thing we know is that the character can collide with the temporary floor we have on the scene. As a result, we can assume that the only thing to do here is to stop the player from jumping. We start by having the reference back to the character's Animator component and check whether it exists. If it does, we will set the Jump bool value to false; to set that the player is no longer jumping, we will also set the isJumping class variable to false, so if the player was to swipe upwards again, the AddForce function gets a call. Also, the character will jump.

We will compare the type of GameObject with the one that is being collided with so that we can decide what to do with the colliding GameObject as well as what to do with the Character GameObject.

If you play the game now, you should see the character transition from jumping and not jumping; this is based on the player input of swiping upwards to jump and the character stopping the jump by hitting the temporary floor

In addition, we will check to make sure that GameCharacter isn't null (it exists); we also make sure that it is not dead and then we will call GameCharacter.RecieveInput( ), which will send touchDistance and touchDirection to the Character class, which allows you to control the character based on them.

Perform the following steps:

  1. Save this PlayerInput file and navigate back to Unity, which should compile the code now.
  2. After the code is compiled, right-click on Hierarchy and select Create Empty.
  3. Name this new GameObject as Player Input.
  4. With the PlayerInput GameObject chosen, select Add Component from the Inspector window.
  5. Search for PlayerInput and select PlayerInput:
    PlayerInput
  6. Next, select the Character GameObject.
  7. In the Inspector window, select Add Component. Then, search for Character and select Character.
  8. Now, select the PlayerInput GameObject and then left-click on the Character GameObject and drag the object onto the Character field of the PlayerInput component:
    PlayerInput

Tip

If you are like me and have Swipe Time and Swipe Distance set to 0, the settings from the PlayerInput chapter are Swipe Time = 0.08 and SwipeDistance = 25.

This will give the PlayerInput component of the PlayerInput GameObject a reference to the Character GameObject. This also allows you to use PlayerInput to "communicate" with Character or to be more direct, send the SimpleTouch struct data of the current touch input from the user to a function of Character so that Character knows what it should do.

Next double-click on the Character.cs class to open it. Like the PlayerInput class, you will see the generated code from Unity; this includes the Start and Update functions and the two Using declarations as well.

The KillCharacter function

Now, we need to write a function to kill the character. This will be used when the character collides with an obstacle.

Under the OnCollisionEnter2D function, add the following code:

    // Kills the character
    public void KillCharacter()
    {
      if (!isDead)
      {
        if (CharacterRigidBody != null)
        {
          CharacterRigidBody.AddForce(new Vector2(Random.Range(-1, 1), 1) * 512);
          isDead = true;
          isFadeOut = true;
        }
      }
    }

This function is designed to make sure that the character's Rigidbody 2D component exists—by making sure it is not null—add a force to it in a random direction between the negative one and the positive one on the X axis and the positive one on the Y axis. This means that a force will be added, which will throw the character upwards with the force of the random direct multiplied by 512. We can also set the character as dead, so it won't be able to pick up anything.

To avoid having the character go floating off into space, let's use the isFadeOut variable to fade the character if it is true. This way the player will see the character fade to transparent before it escapes the screen.

In the Update function of the character C# class, add the following code:

  // Update is called once per frame
  void Update () 
  {
    if (isFadeOut)
    {
      if (GameCharacterSprite != null)
      {
        float currentAlpha = GameCharacterSprite.color.a;
        currentAlpha -= 0.0085f;

        if (currentAlpha < 0.01f)
        {
          currentAlpha = 0.0f;
        }

        Color newColorAlpha = new Color(1.0f, 1.0f, 1.0f, currentAlpha);
        GameCharacterSprite.color = newColorAlpha;
      }
    }
  }

Let's start by checking whether the isFadeOut bool value is true. If so, we can continue to set the alpha of SpriteRenderer. To set the alpha or fade out the Character sprite, we will need a reference to its SpriteRenderer component. We can have this by using the gameObject.GetComponent function. When we have this, we can make sure it exists by verifying that it is not null. We will then set a float variable to the current value of the SpriteRenderer reference and then subtract a small amount from this.

We will then check currentAlpha of the sprite to check whether it is less than 0.01. If it is, we set currentAlpha to 0. Also, we will create a new Color variable and set the alpha channel to the currentAlpha value.

Finally, we will set the reference to the SpriteRenderer.color value to the updated alpha value.

Then, we will need a function that will reset the character back to running. This will be used later on when we create a reset button in the UI. Write the following function under KillCharacter:

      // Revives the character
      public void ReviveCharacter()
      {
        Color resetColorAlpha = new Color( 1.0f, 1.0f, 1.0f, 1.0f );

        gameObject.transform.position = RestartLocation;
        isDead = false;
        isFadeOut = false;

        if (GameCharacterSprite != null)
        {
          GameCharacterSprite.color = resetColorAlpha;
        }
      }

To revive the character is quite easy. We can create a new world location at the 0X, 0Y, and 0Z location (the center of the world) and set the Character GameObject to that location.

We also need to reset the SpriteRenderer.color.a (alpha) value back to default. To do this, we need to get a reference of SpriteRenderer and make sure that it exists by making sure that it is not null.

If it exists, we set the color value of SpriteRenderer to the resetColorAlpha value, which is 1.0f red, 1.0f green, 1.0f blue, and 1.0f alpha by default.

We will then set isDead to false, meaning that the character is alive, and set isFadeOut to false so that the character does not fade out anymore.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset