Beginner question so please don't hate. I've made this 3d character controller script (I know it's terrible but I'm trying to begin with something I 100% understand before moving to more complex things). In this script, I made bools of wPressed, aPressed, sPressed, and dPressed in the update function. I then made the FixedUpdate function and added this section of code:
if (wPressed == true)
{
player.velocity = transform.forward * movementSpeed;
}
if (sPressed == true)
{
player.velocity = -transform.forward * movementSpeed;
}
if (wPressed == false && sPressed == false)
{
player.velocity = transform.forward * 0;
}
if (wPressed == true && sPressed == true)
{
player.velocity = transform.forward * 0;
}
Its probably bad... But it worked fine for now... However when I tried adding the a and d movement,
if (aPressed == true)
{
player.velocity = -transform.right * movementSpeed;
}
if (dPressed == true)
{
player.velocity = transform.right * movementSpeed;
}
if (aPressed == false && dPressed == false)
{
player.velocity = transform.right * 0;
}
if (aPressed == true && dPressed == true)
{
player.velocity = transform.right * 0;
}
It also worked, but it now broke the w and s movement script. Why is that?
Here is the entire code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
bool dPressed;
bool aPressed;
bool wPressed;
bool sPressed;
Rigidbody player;
private int movementSpeed;
// Start is called before the first frame update
void Start()
{
player = GetComponent<Rigidbody>();
movementSpeed = 5;
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.W))
{
wPressed = true;
}
if (Input.GetKeyUp(KeyCode.W))
{
wPressed = false;
}
if (Input.GetKey(KeyCode.S))
{
sPressed = true;
}
if (Input.GetKeyUp(KeyCode.S))
{
sPressed = false;
}
if (Input.GetKey(KeyCode.A))
{
aPressed = true;
}
if (Input.GetKeyUp(KeyCode.A))
{
aPressed = false;
}
if (Input.GetKey(KeyCode.D))
{
dPressed = true;
}
if (Input.GetKeyUp(KeyCode.D))
{
dPressed = false;
}
}
private void FixedUpdate()
{
if (wPressed == true)
{
player.velocity = transform.forward * movementSpeed;
}
if (sPressed == true)
{
player.velocity = -transform.forward * movementSpeed;
}
if (wPressed == false && sPressed == false)
{
player.velocity = transform.forward * 0;
}
if (wPressed == true && sPressed == true)
{
player.velocity = transform.forward * 0;
}
if (aPressed == true)
{
player.velocity = -transform.right * movementSpeed;
}
if (dPressed == true)
{
player.velocity = transform.right * movementSpeed;
}
if (aPressed == false && dPressed == false)
{
player.velocity = transform.right * 0;
}
if (aPressed == true && dPressed == true)
{
player.velocity = transform.right * 0;
}
}
}
Your issue is that whenever you have new input, you are fully overwriting your current velocity. For example, at every conditional statement, you have a
player.velocity = transform.direction * movementSpeed
Instead, you would want to isolate the velocity that each direction would change. I recommend looking into GetAxis
, which is a similar approach but reduces the number of input checks.
float mH = Input.GetAxis ("Horizontal");
float mV = Input.GetAxis ("Vertical");
player.velocity = new Vector3 (mH * movementSpeed, rb.velocity.y, mV * movementSpeed);
You are always overwriting the entire velocity eg
player.velocity = transform.right * 0;
so even if w
(or anything else) is pressed you set the entire velocity = 0,0,0. Forgetting all previously handled keys.
Rather do eg
private void Update()
{
var movement = Vector2.zero;
if (Input.GetKey(KeyCode.W))
{
movement.y += 1;
}
if(Input.GetKey(KeyCode.S))
{
movement.y -= 1;
}
if(Input.GetKey(KeyCode.A))
{
movement.x -= 1;
}
if(Input.GetKey(KeyCode.D))
{
movement.x += 1;
}
movement = Vector2.ClampMagnitude(movement, 1f);
player.velocity = transform.forward * movement.y + transform.right * movement.x;
}
Note that by default Unity also provides this via GetAxis
var movement = new Vector2 (Input.GetAxis ("Horizontal"), Input.GetAxis ("Vertical"));
movement = Vector2.ClampMagnitude(movement, 1f);
player.velocity = transform.forward * movement.y + transform.right * movement.x;
First of all, this section
if (aPressed == false && dPressed == false)
{
player.velocity = transform.right * 0;
}
will execute always when (A == false && D == false) even if W/S are pressed too. Easy solution is just move this double-check section to the top.
More complex solution is create Vector3 for velocity and then make single player.velocity = newVec based on the input.
Vector3 dir = Vector3.zero;
var forward = transform.forward;
var right = transform.right;
if(aPressed)
dir -= right;
if(dPressed)
dir += right;
if(sPressed)
dir -= forward;
if(wPressed)
dir += forward;
//Same as Vector3.ClampMagnitude(vec, 1f) but a bit faster
dir = dir.normalized;
player.velocity = dir;
There is also Input.GetAxis solution, but be careful with it, because it can cause minor performance loss when called frequently (for instance 100-1000 times a frame)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.