I've been trying to figure out how to get this specific movement system working, and I got it working (yay!), but the bad news is that it is SUPER unoptimized. I have lots of copypaste and honestly I'm kind of embarrassed to post this, but here it is. Please let me know what I'm doing wrong if you see any obvious mistakes (you will). I'm still pretty new to programming so I want to catch any bad habits before I let them develop.
For reference, the code posted below is for my player character. It is referencing a float called camDirection from another script which is currently attached to the camera, it goes from -3 to +3 in increments of 1.
The basic idea here is that I wanted the player's input for movement to switch directions on the keyboard when the player presses one of two buttons to move the camera 90 degrees around the player, one for clockwise rotation and another for counterclockwise rotation. When the camera is facing north, we have standard WASD controls(up is W, left is A, down is S and right is D), which I assigned to an action map called PlayerN.
Now, if the camera is facing east, the actionmap gets changed to PlayerW where up is D, left is W, right is S and down is A. If that sounds weird to you, rotate your keyboard 90 degrees counter-clockwise and look at your WASD keys and you might see where I'm coming from. I have no idea how optimal this is, but this was just what made sense to me at the time so I went with it, I couldn't get unity's ApplyBindingOverride to work or anything similar to that, but I'm certain I was using them incorrectly. Along with PlayerS and PlayerE I have 4 action maps altogether, one for each direction.
Anyways, here it is. I'm gonna break down some of this mess below the post:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.InputSystem;
public class Player : MonoBehaviour
{
public InputMaster controls;
private float playerSpeed = 4f;
Vector2 moveN;
Vector2 moveE;
Vector2 moveS;
Vector2 moveW;
Vector2 moveW2;
Vector2 moveS2;
Vector2 moveE2;
public CameraRotate refScript;
void Awake()
{
controls = new InputMaster();
controls.PlayerN.Movement.performed += ctx => moveN = ctx.ReadValue<Vector2>();
controls.PlayerN.Movement.canceled += ctx => moveN = Vector2.zero;
controls.PlayerE.Movement.performed += ctx => moveE = ctx.ReadValue<Vector2>();
controls.PlayerE.Movement.canceled += ctx => moveE = Vector2.zero;
controls.PlayerE.Movement.performed += ctx => moveE2 = ctx.ReadValue<Vector2>();
controls.PlayerE.Movement.canceled += ctx => moveE2 = Vector2.zero;
controls.PlayerS.Movement.performed += ctx => moveS = ctx.ReadValue<Vector2>();
controls.PlayerS.Movement.canceled += ctx => moveS = Vector2.zero;
controls.PlayerS.Movement.performed += ctx => moveS2 = ctx.ReadValue<Vector2>();
controls.PlayerS.Movement.canceled += ctx => moveS2 = Vector2.zero;
controls.PlayerW.Movement.performed += ctx => moveW = ctx.ReadValue<Vector2>();
controls.PlayerW.Movement.canceled += ctx => moveW = Vector2.zero;
controls.PlayerW.Movement.performed += ctx => moveW2 = ctx.ReadValue<Vector2>();
controls.PlayerW.Movement.canceled += ctx => moveW2 = Vector2.zero;
}
void Update()
{
Vector2 inputVectorN = controls.PlayerN.Movement.ReadValue<Vector2>();
Vector2 inputVectorE = controls.PlayerE.Movement.ReadValue<Vector2>();
Vector2 inputVectorS = controls.PlayerS.Movement.ReadValue<Vector2>();
Vector2 inputVectorW = controls.PlayerW.Movement.ReadValue<Vector2>();
Vector2 inputVectorE2 = controls.PlayerE.Movement.ReadValue<Vector2>();
Vector2 inputVectorS2 = controls.PlayerS.Movement.ReadValue<Vector2>();
Vector2 inputVectorW2 = controls.PlayerW.Movement.ReadValue<Vector2>();
switch (refScript.camDirection)
{
case -3:
Debug.Log("Facing East");
inputVectorE = new Vector2(moveE.x, moveE.y) * Time.deltaTime * playerSpeed;
Vector3 finalVectorE = new Vector3();
finalVectorE.x = inputVectorE.x;
finalVectorE.z = inputVectorE.y;
transform.Translate(finalVectorE, Space.World);
break;
case -2:
Debug.Log("Facing South");
inputVectorS = new Vector2(moveS.x, moveS.y) * Time.deltaTime * playerSpeed;
Vector3 finalVectorS = new Vector3();
finalVectorS.x = inputVectorS.x;
finalVectorS.z = inputVectorS.y;
transform.Translate(finalVectorS, Space.World);
break;
case -1:
Debug.Log("Facing West");
inputVectorW = new Vector2(moveW.x, moveW.y) * Time.deltaTime * playerSpeed;
Vector3 finalVectorW = new Vector3();
finalVectorW.x = inputVectorW.x;
finalVectorW.z = inputVectorW.y;
transform.Translate(finalVectorW, Space.World);
break;
case 0:
Debug.Log("Facing North");
inputVectorN = new Vector2(moveN.x, moveN.y) * Time.deltaTime * playerSpeed;
Vector3 finalVectorN = new Vector3();
finalVectorN.x = inputVectorN.x;
finalVectorN.z = inputVectorN.y;
transform.Translate(finalVectorN, Space.World);
break;
case 1:
Debug.Log("Facing East");
inputVectorE2 = new Vector2(moveE2.x, moveE2.y) * Time.deltaTime * playerSpeed;
Vector3 finalVectorE2 = new Vector3();
finalVectorE2.x = inputVectorE2.x;
finalVectorE2.z = inputVectorE2.y;
transform.Translate(finalVectorE2, Space.World);
break;
case 2:
Debug.Log("Facing South");
inputVectorS2 = new Vector2(moveS2.x, moveS2.y) * Time.deltaTime * playerSpeed;
Vector3 finalVectorS2 = new Vector3();
finalVectorS2.x = inputVectorS2.x;
finalVectorS2.z = inputVectorS2.y;
transform.Translate(finalVectorS2, Space.World);
break;
case 3:
Debug.Log("Facing West");
inputVectorW2 = new Vector2(moveW2.x, moveW2.y) * Time.deltaTime * playerSpeed;
Vector3 finalVectorW2 = new Vector3();
finalVectorW2.x = inputVectorW2.x;
finalVectorW2.z = inputVectorW2.y;
transform.Translate(finalVectorW2, Space.World);
break;
}
}
private void OnEnable()
{
controls.Enable();
}
private void OnDisable()
{
controls.Disable();
}
}
I think the Switch might be the worst offender here, I couldn't figure out how to condense my code for movement so I just copypasted it a bunch of times for each case. However, once I did this 4 times (for cases -3, -2 -1, and 0) it started giving me errors, and that's because it was conflicting with the code I did in an earlier case.
For instance, when case is -3 OR 1, the player will be facing east, which means I should run the same code. HOWEVER it started giving me errors, and that's when I noticed that I couldn't have identical variable names in a Switch statement (it was my first time using one). So I quickly made variables named moveE2 inputVectorE2 and finalVectorE2 and I did this for every direction except for north since it only shows up once on the switch statement.
One of the big reasons I'm making this post is because I don't necessarily want this to be the final movement system for my character, and I don't know how to easily create something more modular for this code, or for when I do something similar to this in the future. Currently if I want to change the movement at all I have to go into the cases and change it 7 times. Not very efficient.
Anyways thanks for reading, I'd really appreciate any pointers or tips you might have to slim down this code and make it easier to work with in the future.
thisTransforminside every MonoBehavior class. Use this reference instead oftransform. This will avoid reflection calls for every access. Initialize thethisTransform = transforminsideAwake()orStart()methods. The same goes for any similar commonly used properties like rigidBody, collider or any component you want to use inUpdate()orFixedUpdate()- Kumar CN,E,S,W,E2,S2,W2combine themoveXYZfields into a dictionary where you can use the enum to index into it. Do the same withinputVectorXYZlocals. Then you can make a method that does the thing for each case statement depending on the key - Ruzihm