- Home /
3D Movement with Gamepad with Input System?
I've been working on a 3d RPG that would be best controlled using a gamepad. I've been using Unity's input system; however, gamepad controls are pretty new to me and I've hit a wall when in comes to joystick controls. I want to control the character's movement with the left joystick, and I want to control the camera's rotation around the character with the right joystick. I'm trying to figure out how get the script to fit those requirements with the input system. For player movement, it is just a simple walk around a terrain with slight elevation differences. The camera follows and rotates around the player at all angles. If anyone knows any scripts that would help me for any of these, please let me know.
Answer by TheElectroResistance · May 24, 2020 at 11:41 PM
This is what I did:
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;
public float jumpHeight = 3f;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
Vector3 velocity;
bool isGrounded;
// Update is called once per frame
void Update()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 Move = transform.right * x + transform.forward * z;
controller.Move(Move * speed * Time.deltaTime);
if (Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
That was the player movement script, here is the mouse looking around script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class mouseLook : MonoBehaviour
{
public float mouseSensitivity = 100f;
public Transform playerBody;
float xRotation = 0f;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
xRotation -= mouseY;
if (xRotation < -90)
{
xRotation = -90;
}
transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
playerBody.Rotate(Vector3.up * mouseX);
}
}
Note: It doesn't have the mouse lock when you look up and down so you can do front flips. @jhubbard21
Answer by jhubbard0221 · May 24, 2020 at 10:50 PM
To all the people following my question, I figured most of it out. Below, I have my script that got it to work. Because I don't know what everyone is looking for, I put down all of the script I thought could be remotely relevant. This will allow your character to move backward, forward, left, and right at any angle the joystick points in. The character doesn't turn yet (another question I'll be asking soon), and I haven't figured out the camera rotation yet. If there are any other questions about this script, please ask in the replies. I might be able to help or clarify something.
(Sorry if my method of code organization is confusing)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.Scripting.APIUpdating;
public class PlayerController : MonoBehaviour
{
PlayerControls controls;
Vector3 Movement;
void Awake()
//Controller input roles
{
controls = new PlayerControls();
controls.Gameplay.Movement.performed += ctx => Movement = ctx.ReadValue<Vector2>();
controls.Gameplay.Movement.canceled += ctx => Movement = Vector3.zero;
}
//Joystick controls
void Update()
{
//Character Movement
Vector3 m = new Vector3(Movement.x, 0, Movement.y) * Time.deltaTime;
transform.Translate(m, Space.World);
}
void OnEnable()
{
controls.Gameplay.Enable();
}
void OnDisable()
{
controls.Gameplay.Disable();
}
}
Does this script work on terrain and what about the rotations....?
Answer by Rohan_Dharankar · Jan 29, 2021 at 06:04 AM
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.InputSystem;
public class characterMovement : MonoBehaviour { // variable to store character animator component Animator animator;
//variables to store optimized setter/getter parameter IDs
int isWalkingHash;
int isRunningHash;
//Variable to store the instance of the player input
Playerinput input;
//variables to store player input values
Vector2 currentMovement;
bool movementPressed;
bool runPressed;
//Awake is called when the script instance is being loaded
void Awake()
{
input = new Playerinput();
//set the player input values using listeners
input.CharacterControls.Movement.performed += ctx =>
{
currentMovement = ctx.ReadValue<Vector2>();
movementPressed = currentMovement.x != 0 || currentMovement.y != 0;
};
input.CharacterControls.Run.performed += ctx => runPressed = ctx.ReadValueAsButton();
}
// Start is called before the first frame update
void Start()
{
//set animator reference
animator = GetComponent<Animator>();
//set the ID references
isWalkingHash = Animator.StringToHash("isWalking");
isRunningHash = Animator.StringToHash("isRunning");
}
// Update is called once per frame
void Update()
{
handleMovement();
handleRotation();
}
void handleRotation()
{
Vector3 currentPosition = transform.position;
Vector3 newPosition = new Vector3(currentMovement.x, 0, currentMovement.y);
Vector3 positionToLookAt = currentPosition + newPosition;
transform.LookAt(positionToLookAt);
}
void handleMovement()
{
//get parameter values from animator
bool isRunning = animator.GetBool(isRunningHash);
bool isWalking = animator.GetBool(isWalkingHash);
//start walking if movementPressed is true and not already walking
if (movementPressed && !isWalking)
{
animator.SetBool(isWalkingHash, true);
}
//stop walking if movementPressed is false and not already walking
if (!movementPressed && !isWalking)
{
animator.SetBool(isWalkingHash, false);
}
//start running if movementPressed and runPressed is true and not already running
if ((movementPressed && runPressed) && !isRunning)
{
animator.SetBool(isRunningHash, true);
}
//stop running if movementPressed or runPressed is false and already running
if ((!movementPressed || !runPressed) && isRunning)
{
animator.SetBool(isRunningHash, false);
}
}
void OnEnable()
{
//enable the character controls action map
input.CharacterControls.Enable();
}
void OnDisable()
{
//disable the character controls action map
input.CharacterControls.Disable();
}
}
The only problem is that it is passing through terrain surface , the character is not detecting ground