friends, new dev asking, I looked through a lot of sites and tried a lot of different scripts separate scripts from player movement and other scripts to no avail and came up with this as a conglomeration of what I've seen but it also doesn't work, at all. I couldn't find anything in subreddits or this. I know my normal movement code is probably ugly but it works. I hope you can help thank you!
TO clarify this is making the player sprint while holding down the shift key thank you for those who reminded me to elaborate.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(UnityEngine.AI.NavMeshAgent))]
public class PlayerMovement : MonoBehaviour
{
UnityEngine.AI.NavMeshAgent agent;
private Rigidbody rb;
public float movementSpeed = 5.0f;
public float clockwise = 1000.0f;
public float counterClockwise = -5.0f;
public float Speed = 5.0f;
public Vector3 jump;
public float jumpForce =1.0f;
public float shiftSpeed = 10.0f;
public bool isGrounded;
void Start()
{
rb = GetComponent<Rigidbody>();
jump = new Vector3(0.0f, 1.0f, 0.0f);
agent = GetComponent<UnityEngine.AI.NavMeshAgent>();
}
void OnCollisionStay()
{
isGrounded = true;
}
void Update()
{
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
transform.position += transform.forward \* Time.deltaTime \* movementSpeed;
}
else if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.LeftShift))
{
transform.position += transform.forward \* Time.deltaTime \* shiftSpeed;
}
else if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
{
transform.position -= transform.forward \* Time.deltaTime \* movementSpeed;
}
else if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow) && Input.GetKey(KeyCode.LeftShift))
{
transform.position += transform.forward \* Time.deltaTime \* shiftSpeed;
}
else if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
GetComponent<Rigidbody>().position += Vector3.left \* Time.deltaTime \* movementSpeed;
}
else if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow) && Input.GetKey(KeyCode.LeftShift))
{
transform.position += transform.forward \* Time.deltaTime \* shiftSpeed;
}
else if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
GetComponent<Rigidbody>().position += Vector3.right \* Time.deltaTime \* movementSpeed;
}
else if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow) && Input.GetKey(KeyCode.LeftShift))
{
transform.position += transform.forward \* Time.deltaTime \* shiftSpeed;
}
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.AddForce(jump \* jumpForce, ForceMode.Impulse);
isGrounded = false;
}
}
}
I assume what you are asking is "How to make my player move faster when I hold down the shift key?"
I would suggest having two constants for walking speed and running speed. Then another variable that changes based on if the shift key is held:
private const float walkSpeed = 5.0f;
private const float runSpeed = 10.0f;
private float moveSpeed = walkSpeed; // Our current movement speed
//...
void Update() {
//...
if (Input.GetKey(KeyCode.LeftShift) {
// Set current speed to run if shift is down
moveSpeed = runSpeed;
}
else {
// Otherwise set current speed to walking speed
moveSpeed = walkSpeed;
}
}
Related
I was following a tutorial but I'm having trouble with the CheckCollisionOverlap() function. It's meant to check for a collision over the player's head when the player is crouching, but for some reason he won't stand back up (or stop walking in place).
If I comment out PhysicsUpdate() and CheckCollisionOverlap(), he will crouch, walk crouch, and stand up from crouch, so I know the problem has to exist within that logic.
In the tutorial comments section, someone mentioned that they changed the value of the layermask. I named a layermask Player and assigned it to layer 8 but that still didn't do anything.
Tutorial Link https://www.youtube.com/watch?v=QVxvwRAYeHU
using UnityEngine;
public class CrouchingState : State
{
float playerSpeed;
bool belowCeiling;
bool crouchHeld;
bool grounded;
float gravityValue;
Vector3 currentVelocity;
public CrouchingState(Character _character, StateMachine _stateMachine):base(_character, _stateMachine)
{
character = _character;
stateMachine = _stateMachine;
}
public override void Enter()
{
base.Enter();
character.animator.SetTrigger("crouch");
belowCeiling = false;
crouchHeld = false;
gravityVelocity.y = 0;
playerSpeed = character.crouchSpeed;
character.controller.height = character.crouchColliderHeight;
character.controller.center = new Vector3(0f, character.crouchColliderHeight / 2f, 0f);
grounded = character.controller.isGrounded;
gravityValue = character.gravityValue;
}
public override void Exit()
{
base.Exit();
character.controller.height = character.normalColliderHeight;
character.controller.center = new Vector3(0f, character.normalColliderHeight / 2f, 0f);
gravityVelocity.y = 0f;
character.playerVelocity = new Vector3(input.x, 0, input.y);
character.animator.SetTrigger("move");
}
public override void HandleInput()
{
base.HandleInput();
if (crouchAction.triggered && !belowCeiling)
{
crouchHeld = true;
}
input = moveAction.ReadValue<Vector2>();
velocity = new Vector3(input.x, 0, input.y);
velocity = velocity.x * character.cameraTransform.right.normalized + velocity.z * character.cameraTransform.forward.normalized;
velocity.y = 0f;
}
public override void LogicUpdate()
{
base.LogicUpdate();
character.animator.SetFloat("speed", input.magnitude, character.speedDampTime, Time.deltaTime);
if (crouchHeld)
{
stateMachine.ChangeState(character.standing);
}
}
public override void PhysicsUpdate()
{
base.PhysicsUpdate();
belowCeiling = CheckCollisionOverlap(character.transform.position + Vector3.up * character.normalColliderHeight);
gravityVelocity.y += gravityValue * Time.deltaTime;
grounded = character.controller.isGrounded;
if (grounded && gravityVelocity.y < 0)
{
gravityVelocity.y = 0f;
}
currentVelocity = Vector3.Lerp(currentVelocity, velocity, character.velocityDampTime);
character.controller.Move(currentVelocity * Time.deltaTime * playerSpeed + gravityVelocity * Time.deltaTime);
if (velocity.magnitude > 0)
{
character.transform.rotation = Quaternion.Slerp(character.transform.rotation, Quaternion.LookRotation(velocity), character.rotationDampTime);
}
}
public bool CheckCollisionOverlap(Vector3 targetPositon)
{
int layerMask = 1 << 8;
layerMask = ~layerMask;
RaycastHit hit;
Vector3 direction = targetPositon - character.transform.position;
if (Physics.Raycast(character.transform.position, direction, out hit, character.normalColliderHeight, layerMask))
{
Debug.DrawRay(character.transform.position, direction * hit.distance, Color.yellow);
return true;
}
else
{
Debug.DrawRay(character.transform.position, direction * character.normalColliderHeight, Color.white);
return false;
}
}
}
I had to change all the layers of the children in the player gameobject as well. Not really sure why that worked, but its responding.
so I am trying to make a shooting machine that shoots bullet and bullet gets back from the same way it went through when hitting the wall without speeding up and without changing angle (just the opposite way)
i added force and tried many ways but nothing works , please help
here is my code (the last one) even though i normalized the force but i still feel like its speeding up
public Rigidbody2D rb;
private float bulletForce = 20f;
private bool collided;
Vector2 dir;
private void Awake()
{
instance = this;
rb = gameObject.GetComponent<Rigidbody2D>();
dir = transform.up;
}
void Update()
{
rb.AddForce(dir.normalized * bulletForce * Time.deltaTime, ForceMode2D.Impulse);
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("Edge"))
{
dir = Vector2.Reflect(rb.position, other.contacts[0].normal);
rb.velocity = dir.normalized * bulletForce;
transform.up = dir.normalized;
}
}
this is wanted results explanation
this is current results explanation
If you just want to exactly invert the direction than
rb.velocity = -rb.velocity;
transform.up = rb.velocity;
and of course it is speeding up since you constantly add force in
void Update()
{
rb.AddForce(dir.normalized * bulletForce * Time.deltaTime, ForceMode2D.Impulse);
}
why don't you just disable any friction for this bullet and set an initial velocity once?
public class CollideReflector : MonoBehaviour
{
[SerializeField] Rigidbody2D rb;
[SerializeField] Vector2 direction;
[SerializeField] float bulletForce = 20f;
[SerializeField]float smooth;
private bool collided;
// STARTER
private void Awake()
{
instance = this;
rb = gameObject.GetComponent<Rigidbody2D>();
direction = transform.up;
}
void Update()
{
rb.AddForce(direction.normalized * bulletForce * Time.deltaTime, ForceMode2D.Impulse);
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("Edge"))
{
var x = Quaternion.Euler(transform.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z);
Quaternion target = -x;
transform.rotation = Quaternion.Slerp(transform.rotation, x, Time.deltaTime * smooth);
rb.AddForce(-direction.normalized * bulletForce * Time.deltaTime, ForceMode2D.Impulse);
}
}
}
My Project is a First Person Jump&Run, I want my Player to Sprint by pressing Horizonzal or Vertical combined with Shift.
I already made a new Input, called Sprint, with negative Button "left shift"
My Player does normal move, but he doesn't Sprint.
Thanks a lot.
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
public float speed = 12f;
public float sprint;
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);
// Noch nicht fertig -> Noch ausstehend
if (Input.GetButtonDown("Horizontal") && Input.GetButtonDown("Sprint") || Input.GetButtonDown("Vertical") && Input.GetButtonDown("Sprint"))
{
controller.Move(move * (speed + sprint) * Time.deltaTime);
}
}
There are most likely problems with how the Input is being handled.
My assumption is that GetButtonDown only returns true for the single frame when you press shift down. Use GetKey instead:
Input.GetKey(KeyCode.LeftShift)
If that doesn't work, try those 2 instead:
Input.GetKeyDown("left shift")
Input.GetKeyDown(KeyCode.LeftShift)
But there might be the same problem with those 2 as with "GetButtonDown".
Also, I think it'd help people understand your code better if you use english comments instead of german. I'm able to read it but most probably don't. Don't worry though, that also happened to me!
I want to press the key once
My cube moves to the right and rotates 90 degrees
The rotation is well done
But it does not move well
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour
{
public float speed;
public float time;
public GameObject contactPoint;
private Rigidbody rig;
private void Start()
{
rig = GetComponent<Rigidbody>();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.D))
{
StartCoroutine(RotatePlayer(Vector3.forward * 90, Vector3.right, time));
}
if (Input.GetKeyDown(KeyCode.A))
{
StartCoroutine(RotatePlayer(Vector3.back * 90, Vector3.left, time));
}
}
private IEnumerator RotatePlayer(Vector3 byAngle, Vector3 dir, float inTime)
{
Quaternion fromAngle = contactPoint.transform.rotation;
Quaternion toAngle = Quaternion.Euler(transform.eulerAngles - byAngle);
for (float t = 0; t < 1; t += Time.deltaTime / inTime)
{
rig.MovePosition(transform.position + (dir * speed * Time.deltaTime));
rig.MoveRotation(Quaternion.Slerp(fromAngle, toAngle, t));
yield return null;
}
}
}
Your main issue is: You should do Physics related things like movement of a Rigidbody only in FixedUpdate.
For Coroutines Unity provides WaitForFixedUpdate which does exactly what the name says, making sure the code after it is executed in a FixedUpdate physics call.
private IEnumerator RotatePlayer(Vector3 byAngle, Vector3 dir, float inTime)
{
yield return new WaitForFixedUpdate();
// here I would also use "rig" instead of "transform"
Quaternion fromAngle = contactPoint.transform.rotation;
Quaternion toAngle = Quaternion.Euler(rig.eulerAngles - byAngle);
for (float t = 0; t < 1; t += Time.deltaTime / inTime)
{
yield return new WaitForFixedUpdate();
// here I would also use "rig" instead of "transform"
rig.MovePosition(rig.position + (dir * speed * Time.deltaTime));
rig.MoveRotation(Quaternion.Slerp(fromAngle, toAngle, t));
}
}
beyond that it is a bit unclear what exactly you define as not move well. You also should somehow make sure that only one routine is running at a time. Either by terminating already running routines like
private void Update()
{
if (Input.GetKeyDown(KeyCode.D))
{
StopAllCoroutines();
StartCoroutine(RotatePlayer(Vector3.forward * 90, Vector3.right, time));
}
if (Input.GetKeyDown(KeyCode.A))
{
StopAllCoroutines();
StartCoroutine(RotatePlayer(Vector3.back * 90, Vector3.left, time));
}
}
or preventing new routines from starting until the current one is finished using a flag like
private bool alreadyRotating;
private IEnumerator RotatePlayer(Vector3 byAngle, Vector3 dir, float inTime)
{
if(alreadyRotating) yield break;
alreadyRotating = true;
......
alreadyRotating = false;
}
I can write somehow this code for optimization?
If not use coroutines, when I click on space the next jump has more force and so on.
If use rb.MovePosition, the character will move as if 15 fps. I know, change Time in settings. But I want to know if exist another method...
private void Update() {
if(Input.GetKeyDown(KeyCode.Space)) {
StopAllCoroutines();
StartCoroutine(Jump());
}
}
private IEnumerator Jump() {
if(rb.bodyType != RigidbodyType2D.Dynamic) {
rb.bodyType = RigidbodyType2D.Dynamic;
}
rb.constraints = RigidbodyConstraints2D.FreezePositionY;
_pos = transform.position;
for (float t = 0; t < 1; t += Time.deltaTime * 4f)
{
transform.position = Vector3.Lerp(transform.position, new Vector3(transform.position.x, _pos.y + .35f, transform.position.z), t);
yield return null;
}
rb.constraints = RigidbodyConstraints2D.None;
}
Rigidbodies exist so you don't need to directly adjust an object's transform. Since you have a Rigidbody2d you can just set the velocity directly:
public float jumpSpeed = 5f; // Whatever feels right
private void FixedUpdate() {
if(Input.GetKeyDown(KeyCode.Space)) {
rb.velocity = Vector2.up * jumpSpeed;
}
}
(Edited to use velocity instead of AddForce)