Can anyone help me implement a mobile joystick into a third person character controller script?

So I have already made a mobile joystick, but I don’t know how to implement it into this third person character controller script, it’s very unreadable to me. This script is taken from the Unity asset store, it’s called 3rd Person Controller + Fly Mode.

Any help will be greatly appreciated, this is the only thing stopping me from making the game I want to make.

There are 2 movement scripts:

Script 1:

using UnityEngine;
   using System.Collections;

// MoveBehaviour inherits from GenericBehaviour. This class corresponds to basic walk and run behaviour, it is the default behaviour.
public class MoveBehaviour : GenericBehaviour
{
   public float walkSpeed = 0.15f;                 // Default walk speed.
   public float runSpeed = 1.0f;                   // Default run speed.
   public float sprintSpeed = 2.0f;                // Default sprint speed.
   public float speedDampTime = 0.1f;              // Default damp time to change the animations based on current speed.
   public float jumpHeight = 1.0f;                 // Default jump height.


   private float speed;                            // Moving speed.
   private int jumpBool;                           // Animator variable related to jumping.
   private int groundedBool;                       // Animator variable related to whether or not the player is on ground.
   private bool run;                               // Boolean to determine whether or not the player activated the run mode.
   private bool jump;                              // Boolean to determine whether or not the player started a jump.

   // Start is always called after any Awake functions.
   void Start()
   {
       // Set up the references.
       jumpBool = Animator.StringToHash("Jump");
       groundedBool = Animator.StringToHash("Grounded");
       anim.SetBool (groundedBool, true);

       // Subscribe and register this behaviour as the default behaviour.
       behaviourManager.SubscribeBehaviour (this);
       behaviourManager.RegisterDefaultBehaviour (this.behaviourCode);
   }

   // Update is used to set features regardless the active behaviour.
   void Update ()
   {
       // Activate run by input.
       run = Input.GetButton ("Run");
       if(Input.GetButtonDown ("Jump"))
           jump = true;
   }

   // LocalFixedUpdate overrides the virtual function of the base class.
   public override void LocalFixedUpdate()
   {
       // Call the basic movement manager.
       MovementManagement (behaviourManager.GetH, behaviourManager.GetV, run);

       // Call the jump manager.
       JumpManagement();
   }

   // Execute the idle and walk/run jump movements.
   void JumpManagement()
   {
       // Already jumped, landing.
       if (anim.GetBool(jumpBool) && rbody.velocity.y < 0)
       {
           // Set jump boolean on the Animator controller.
           jump = false;
           anim.SetBool (jumpBool, false);
       }
       // Start jump.
       if (jump && !anim.GetBool(jumpBool) && IsGrounded())
       {
           // Set jump boolean on the Animator controller.
           anim.SetBool(jumpBool, true);
           if(speed > 0)
           {
               // Set jump vertical impulse when moving.
               rbody.AddForce (Vector3.up * jumpHeight * rbody.mass * 10, ForceMode.Impulse);
           }
       }
   }

   // Deal with the basic player movement
   void MovementManagement(float horizontal, float vertical, bool running)
   {
       // On ground, obey gravity.
       if (anim.GetBool(groundedBool))
           rbody.useGravity = true;

       // Call function that deals with player orientation.
       Rotating(horizontal, vertical);

       // Set proper speed.
       if(behaviourManager.IsMoving())
       {
           if(behaviourManager.isSprinting())
           {
               speed = sprintSpeed;
           }
           else if (running)
           {
               speed = runSpeed;
           }
           else
           {
               speed = walkSpeed;
           }
       }
       else
       {
           speed = 0f;
       }
       anim.SetFloat(speedFloat, speed, speedDampTime, Time.deltaTime);
   }

   // Rotate the player to match correct orientation, according to camera and key pressed.
   Vector3 Rotating(float horizontal, float vertical)
   {
       // Get camera forward direction, without vertical component.
       Vector3 forward = behaviourManager.playerCamera.TransformDirection(Vector3.forward);

       // Player is moving on ground, Y component of camera facing is not relevant.
       forward.y = 0.0f;
       forward = forward.normalized;

       // Calculate target direction based on camera forward and direction key.
       Vector3 right = new Vector3(forward.z, 0, -forward.x);
       Vector3 targetDirection;
       float finalTurnSmoothing;
       targetDirection = forward * vertical + right * horizontal;
       finalTurnSmoothing = behaviourManager.turnSmoothing;

       // Lerp current direction to calculated target direction.
       if((behaviourManager.IsMoving() && targetDirection != Vector3.zero))
       {
           Quaternion targetRotation = Quaternion.LookRotation (targetDirection);

           Quaternion newRotation = Quaternion.Slerp(rbody.rotation, targetRotation, finalTurnSmoothing * Time.deltaTime);
           rbody.MoveRotation (newRotation);
           behaviourManager.SetLastDirection(targetDirection);
       }
       // If idle, Ignore current camera facing and consider last moving direction.
       if(!(Mathf.Abs(horizontal) > 0.9 || Mathf.Abs(vertical) > 0.9))
       {
           behaviourManager.Repositioning();
       }

       return targetDirection;
   }
}

Script 2:

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

// This class contains all basic setup and common functions used by all other player behaviours, and also manages wich behaviour is active.
public class BasicBehaviour : MonoBehaviour
{
   public Transform playerCamera;                 // Reference to the camera that focus the player.
   public float turnSmoothing = 3.0f;             // Speed of turn when moving to match camera facing.
   public float sprintFOV = 100f;                 // the FOV to use on the camera when player is sprinting.
   public VirtualJoystick moveJoystick;

   private float h;                                // Horizontal Axis.
   private float v;                                // Vertical Axis.
   private int currentBehaviour;                   // Reference to the current player behaviour.
   private int defaultBehaviour;                   // The default behaviour of the player when any other is not active.
   private Vector3 lastDirection;                 // Last direction the player was moving.
   private Animator anim;                         // Reference to the Animator component.
   private ThirdPersonOrbitCam camScript;         // Reference to the third person camera script.
   private bool sprint;                           // Boolean to determine whether or not the player activated the sprint mode.
   private int hFloat;                            // Animator variable related to Horizontal Axis.
   private int vFloat;                            // Animator variable related to Vertical Axis.
   private List<GenericBehaviour> behaviours;     // The list containing all the enabled player behaviours.
   private Rigidbody rbody;                       // Reference to the player's rigidbody.

   // Current horizontal and vertical axes.
   public float GetH { get { return h; } }
   public float GetV { get { return v; } }

   void Awake ()
   {
       // Set up the references.
       behaviours = new List<GenericBehaviour> ();
       anim = GetComponent<Animator> ();
       hFloat = Animator.StringToHash("H");
       vFloat = Animator.StringToHash("V");
       camScript = playerCamera.GetComponent<ThirdPersonOrbitCam> ();
       rbody = GetComponent<Rigidbody> ();
   }

   void Update()
   {
       // Store the input axes.
       h = Input.GetAxis("Horizontal");
       v = Input.GetAxis("Vertical");

       // Set the input axes on the Animator Controller.
       anim.SetFloat(hFloat, h);
       anim.SetFloat(vFloat, v);

       // Toggle sprint by input.
       sprint = Input.GetButton ("Sprint");

       // Set the correct camera FOV.
       if(isSprinting())
       {
           camScript.SetFOV(sprintFOV);
       }
       else
       {
           camScript.ResetFOV();
       }
   }

   void FixedUpdate()
   {
       // Ensure the camera will be back to original setup when no behaivour is active.
//      camScript.ResetTargetOffsets ();
//      camScript.ResetMaxVerticalAngle ();

       // Call the active behaviour.
       bool isAnyBehaviourActive = false;
       foreach (var behaviour in behaviours)
       {
           if (behaviour.isActiveAndEnabled && currentBehaviour == behaviour.GetBehaviourCode())
           {
               isAnyBehaviourActive = true;
               behaviour.LocalFixedUpdate ();
           }
       }

       // Ensure the player is standed on floor if no behaivour is active.
       if (!isAnyBehaviourActive)
       {
           rbody.useGravity = true;
           Repositioning ();
       }
   }

   // Puts a new behaviour on the monitored behaviours list.
   public void SubscribeBehaviour(GenericBehaviour behaviour)
   {
       behaviours.Add (behaviour);
   }

   // Set the default player behaviour.
   public void RegisterDefaultBehaviour(int behaviourCode)
   {
       defaultBehaviour = behaviourCode;
       currentBehaviour = behaviourCode;
   }

   // Attempt to set a player behaviour as the active one.
   public void RegisterBehaviour(int behaviourCode)
   {
       if (currentBehaviour == defaultBehaviour)
       {
           currentBehaviour = behaviourCode;
       }
   }

   // Attempt to deactivate a player behaviour and return to the default one.
   public void UnregisterBehaviour(int behaviourCode)
   {
       if (currentBehaviour == behaviourCode)
       {
           currentBehaviour = defaultBehaviour;
       }
   }

   // Check if the active behaviour is the passed one.
   public bool IsCurrentBehaviour(int behaviourCode)
   {
       return this.currentBehaviour == behaviourCode;
   }

   // Check if player is sprinting.
   public virtual bool isSprinting()
   {
       return sprint && IsMoving() && CanSprint();
   }

   // Check if player can sprint (all behaviours must allow).
   public bool CanSprint()
   {
       foreach (var behaviour in behaviours)
       {
           if (!behaviour.AllowSprint ())
               return false;
       }
       return true;
   }

   // Check if the player is moving on the horizontal plane.
   public bool IsHorizontalMoving()
   {
       return Mathf.Abs(h) > 0.1;
   }

   // Check if the player is moving.
   public bool IsMoving()
   {
       return Mathf.Abs(h) > 0.1 || Mathf.Abs(v) > 0.1;
   }

   // Set the last player direction of facing.
   public void SetLastDirection(Vector3 direction)
   {
       lastDirection = direction;

       if (moveJoystick.InputDirection != Vector3.zero)
       {
           direction = moveJoystick.InputDirection;
       }
   }

   // Put the player on a standing up position based on last direction faced.
   public void Repositioning()
   {
       if(lastDirection != Vector3.zero)
       {
           lastDirection.y = 0;
           Quaternion targetRotation = Quaternion.LookRotation (lastDirection);
           Quaternion newRotation = Quaternion.Slerp(rbody.rotation, targetRotation, turnSmoothing * Time.deltaTime);
           rbody.MoveRotation (newRotation);
       }
   }
}

// This is the base class for all player behaviours, any custom behaviour must inherit from this.
public abstract class GenericBehaviour : MonoBehaviour
{
   protected Rigidbody rbody;                     // Reference to the player's rigidbody.
   protected Animator anim;                       // Reference to the Animator component.
   protected int speedFloat;                      // Speed parameter on the Animator.
   protected BasicBehaviour behaviourManager;     // Reference to the basic behaviour manager.
   protected ThirdPersonOrbitCam camScript;       // Reference to the third person camera script.
   protected int behaviourCode;                   // The code that identifies a behaviour.
   protected bool canSprint;                      // Boolean to store if the behaviour allows the player to sprint.
   protected float distToGround;                   // Actual distance to ground.

   void Awake()
   {
       // Set up the references.
       anim = GetComponent<Animator> ();
       rbody = GetComponent<Rigidbody> ();
       behaviourManager = GetComponent<BasicBehaviour> ();
       camScript = behaviourManager.playerCamera.GetComponent<ThirdPersonOrbitCam> ();
       speedFloat = Animator.StringToHash("Speed");
       canSprint = true;

       // Set the behaviour code based on the inheriting class.
       behaviourCode = this.GetType().GetHashCode();
       distToGround = GetComponent<Collider>().bounds.extents.y;
   }

   // Protected, virtual functions can be overridden by inheriting classes.
   // Here the custom active behaviour will control the player actions.
   public abstract void LocalFixedUpdate ();

   // Get the behaviour code.
   public int GetBehaviourCode()
   {
       return behaviourCode;
   }

   // Check if the behaviour allows sprinting.
   public bool AllowSprint()
   {
       return canSprint;
   }

   // Function to tell whether or not the player is on ground.
   public bool IsGrounded() {
       return Physics.Raycast(transform.position, Vector3.down, distToGround + 0.1f);
   }
}

My joystick script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;

public class VirtualJoystick : MonoBehaviour, IPointerUpHandler, IPointerDownHandler, IDragHandler
{
   private Image bgImage;
   private Image joystickImage;

   public Vector3 InputDirection { set; get; }

   private void Start()
   {
       bgImage = GetComponent<Image>();
       joystickImage = transform.GetChild(0).GetComponent<Image>();
       InputDirection = Vector3.zero;
   }

   public virtual void OnDrag(PointerEventData ped)
   {
       Vector2 pos = Vector2.zero;
       if (RectTransformUtility.ScreenPointToLocalPointInRectangle
           (bgImage.rectTransform,
           ped.position,
           ped.pressEventCamera,
           out pos))
       {
           pos.x = (pos.x / bgImage.rectTransform.sizeDelta.x);
           pos.y = (pos.y / bgImage.rectTransform.sizeDelta.y);

           float x = (bgImage.rectTransform.pivot.x == 1) ? pos.x * 2 + 1 : pos.x * 2 - 1;
           float y = (bgImage.rectTransform.pivot.y == 1) ? pos.y * 2 + 1 : pos.y * 2 - 1;

           InputDirection = new Vector3(x, 0, y);
           InputDirection = (InputDirection.magnitude > 1) ? InputDirection.normalized : InputDirection;

           joystickImage.rectTransform.anchoredPosition =
               new Vector3(InputDirection.x * (bgImage.rectTransform.sizeDelta.x / 3),
               InputDirection.z * (bgImage.rectTransform.sizeDelta.y / 3));
       }
   }

   public virtual void OnPointerUp(PointerEventData ped)
   {
       OnDrag(ped);
   }

   public virtual void OnPointerDown(PointerEventData ped)
   {
       InputDirection = Vector3.zero;
       joystickImage.rectTransform.anchoredPosition = Vector3.zero;

   }
}

BasicBehaviour lines 45 and 46. These access the unity input class and get the movement axis. You’ll want to replace them with the appropriate values from the virtual joystick.

edit: by appropriate I mean the input vector would need to be split into the two directions and the value normalised to -1…1 range so that the rest of the script is getting what it expects.

1 Like

Thank you very much! Sorry for this noob question but how would I go about doing that?

well the split would be the x and z values from the vector, and it looks like VirtualJoystick line 38 already does the normalising so you should be ok just splitting it i think.

1 Like

How?