3
\$\begingroup\$

I'm currently working on an FPS shooter game and I needed a generic movement controller that supported both keyboard and Xbox One controller input. My main goal in designing this controller was to address two common issues that occurred in previous FPS controllers I've designed, which are:

  • Diagonal movement (strafing) caused the player to move about twice as fast when a keyboard setup was being used.
  • Jumping in a setting with a low ceiling caused the player to 'stick' to said ceiling.

Here's the code:

using UnityEngine;
using System.Collections;
/// <summary>
/// This class is responsible for controlling the players movement.
/// </summary>
[RequireComponent(typeof(CharacterController))]
public class CharacterMovementController : MonoBehaviour
{
 public bool UseController;
 public Vector3 JumpSpeed;
 public Vector3 GravitySpeed;
 public Vector2 MovementSpeed;
 public Vector2 CameraRotationSpeed;
 public Vector2 CameraRotationConstraints;
 public CharacterController CharacterController { get; set; }
 public Vector3 MovementVector { get; set; }
 public float VerticalRotation { get; set; }
 /// <summary>
 /// Rotate the player.
 /// </summary>
 public void Rotate()
 {
 if(this.UseController)
 {
 this.transform.Rotate(new Vector3(0.0f, Input.GetAxis("Xbox Look X"), 0.0f) * this.CameraRotationSpeed.x * Time.deltaTime);
 this.VerticalRotation += Input.GetAxis("Xbox Look Y") * this.CameraRotationSpeed.y * Time.deltaTime;
 this.VerticalRotation = Mathf.Clamp(this.VerticalRotation, this.CameraRotationConstraints.x, this.CameraRotationConstraints.y);
 Camera.main.transform.eulerAngles = new Vector3(
 -this.VerticalRotation,
 Camera.main.transform.eulerAngles.y,
 Camera.main.transform.eulerAngles.z
 );
 }
 else
 {
 this.transform.Rotate(new Vector3(0.0f, Input.GetAxis("Mouse X"), 0.0f) * this.CameraRotationSpeed.x * Time.deltaTime);
 this.VerticalRotation += -Input.GetAxis("Mouse Y") * this.CameraRotationSpeed.y * Time.deltaTime;
 this.VerticalRotation = Mathf.Clamp(this.VerticalRotation, this.CameraRotationConstraints.x, this.CameraRotationConstraints.y);
 Camera.main.transform.eulerAngles = new Vector3(
 -this.VerticalRotation,
 Camera.main.transform.eulerAngles.y,
 Camera.main.transform.eulerAngles.z
 );
 }
 }
 /// <summary>
 /// Move the player.
 /// </summary>
 public void Move()
 {
 if(this.UseController)
 {
 this.MovementVector += Vector3.forward * Input.GetAxis("Xbox Forward / Backward") * this.MovementSpeed.y;
 this.MovementVector += Vector3.right * Input.GetAxis("Xbox Left / Right") * this.MovementSpeed.x;
 this.MovementVector = this.transform.rotation * this.MovementVector;
 }
 else
 {
 bool keyboardMovingForwardBackward = false;
 bool keyboardMovingLeftRight = false;
 if(Input.GetButton("Keyboard Forward"))
 {
 this.MovementVector -= this.transform.forward * this.MovementSpeed.y;
 keyboardMovingForwardBackward = true;
 }
 else if(Input.GetButton("Keyboard Backward"))
 {
 this.MovementVector += this.transform.forward * this.MovementSpeed.y;
 keyboardMovingForwardBackward = true;
 }
 if(Input.GetButton("Keyboard Left"))
 {
 this.MovementVector -= this.transform.right * this.MovementSpeed.x;
 keyboardMovingLeftRight = true;
 }
 else if(Input.GetButton("Keyboard Right"))
 {
 this.MovementVector += this.transform.right * this.MovementSpeed.x;
 keyboardMovingLeftRight = true;
 }
 if(keyboardMovingForwardBackward && keyboardMovingLeftRight)
 {
 this.MovementVector = new Vector3(
 this.MovementVector.x * (1.0f / Mathf.Sqrt(2.0f)),
 this.MovementVector.y,
 this.MovementVector.z * (1.0f / Mathf.Sqrt(2.0f))
 );
 }
 }
 if(!this.CharacterController.isGrounded)
 {
 this.MovementVector += this.GravitySpeed * Time.deltaTime;
 }
 else
 {
 this.MovementVector = new Vector3(this.MovementVector.x, 0.0f, this.MovementVector.z);
 }
 if(Input.GetButton("Xbox A") && this.CharacterController.isGrounded)
 {
 this.MovementVector += this.JumpSpeed;
 }
 RaycastHit upperGroundedRaycastHit;
 if(Physics.Raycast(this.transform.position, this.transform.up, out upperGroundedRaycastHit, (this.CharacterController.height / 2.0f) + 0.1f))
 {
 this.MovementVector = new Vector3(this.MovementVector.x, this.GravitySpeed.y, this.MovementVector.z);
 }
 this.CharacterController.Move(this.MovementVector * Time.deltaTime);
 this.MovementVector = new Vector3(0.0f, this.MovementVector.y, 0.0f);
 }
 /// <summary>
 /// Update is called once per frame.
 /// </summary>
 public void Update()
 {
 this.Rotate();
 this.Move();
 }
 /// <summary>
 /// Start is called once.
 /// </summary>
 public void Start()
 {
 this.CharacterController = this.GetComponent<CharacterController>();
 }
}

Is there anything that can be improved? Are there any potential pitfalls or problems that can occur?

asked May 15, 2017 at 14:45
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Rotate()

In this method the only difference between the if branches are the getting of the X and Y location. It would be enough to place getting these in the branches and therefor you could remove some of the duplicated code but it would be much better just assigning the string's, which are needed, to two variables like so

var xKey = "Mouse X";
var yKey = "Mouse Y";
if(this.UseController)
{
 xKey = "Xbox Look X";
 yKey = "Xbox Look Y";
}
this.transform.Rotate(new Vector3(0.0f, Input.GetAxis(xKey), 0.0f) * this.CameraRotationSpeed.x * Time.deltaTime);
this.VerticalRotation += Input.GetAxis(yKey) * this.CameraRotationSpeed.y * Time.deltaTime;
this.VerticalRotation = Mathf.Clamp(this.VerticalRotation, this.CameraRotationConstraints.x, this.CameraRotationConstraints.y);
Camera.main.transform.eulerAngles = new Vector3(
 -this.VerticalRotation,
 Camera.main.transform.eulerAngles.y,
 Camera.main.transform.eulerAngles.z
 );
answered May 15, 2017 at 15:05
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.