Im trying to learn coding and watch youtube tutorials learn to code and I came across this code that I put in my prototype game, Im just asking what should I add to make my character do a double jump?
Code:
public class fpsmovement : MonoBehaviour
{
private float yaw = 0.0f, pitch = 0.0f;
private Rigidbody rb;
[SerializeField] float movementspeed = 5.0f, sensitivity = 2.0f;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
rb = gameObject.GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.Space) && Physics.Raycast(rb.transform.position, Vector3.down, 1 + 0.001f))
rb.velocity = new Vector3(rb.velocity.x, 5.0f, rb.velocity.z);
Look();
}
void FixedUpdate()
{
Movement();
}
void Look()
{
pitch -= Input.GetAxisRaw("Mouse Y") * sensitivity;
pitch = Mathf.Clamp(pitch, -90.0f, 90.0f);
yaw += Input.GetAxisRaw("Mouse X") * sensitivity;
Camera.main.transform.localRotation = Quaternion.Euler(pitch, yaw, 0);
}
void Movement()
{
Vector2 axis = new Vector2(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal")).normalized * movementspeed;
Vector3 forward = new Vector3(-Camera.main.transform.right.z, 0.0f, Camera.main.transform.right.x);
Vector3 wishDirector = (forward * axis.x + Camera.main.transform.right * axis.y + Vector3.up * rb.velocity.y);
rb.velocity = wishDirector;
}
}
First of all you need to check if your player is grounded to be allowed to jump. You problably have a player which can jump again forever like a rocket right now. Then you need to create a boolean variable to check if the player can double jump. Set the variable to true when you jump and set the variable to false when you do the 2nd jump. Also, to allow jump, you should check if the player is grounded OR if can doublejump. There is a lot of tutorials on youtube about this topic, I hope you find the code needed easily.
You can try two methods, "Jump" and "Jump1", the first "Jump" method first uses if to judge whether it is on the ground, if it is allowed to jump on the ground, the "Jump1" method judges if it is not on the ground. On this basis, the code logic for judging the jump state is implemented, and finally the button is reset.
Related
I'm currently developing an FPS shooter in Unity 3D. I'm fairly new to Unity and I've been having a bit of trouble with my player movement script. Individually everything seems to work, I can rotate and move the player freely, however when I try doing the two simultaneously my player seems to lock and won't rotate.
Sometimes jumping or moving to higher ground on the terrain seems to fix the issue, however I ran a few checks with gravity disabled, no colliders, and with the player well above ground, so the problem seems to be with the script. I've also done a bit of debugging and the Rotate() code does run, just the rotation amount doesn't seem to change.
Here is the player movement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class PlayerMov : MonoBehaviour
{
[SerializeField]
private Camera cam;
[SerializeField]
private float speed = 5f;
[SerializeField]
private float looksensitivity = 4f;
[Header("Camera View Lock:")]
[SerializeField] //min and max amount for looking up and down (degrees)
private float lowlock = 70f;
[SerializeField]
private float highlock = 85f;
private Rigidbody rb;
private float currentrotx; //used later for calculating relative rotation
public Vector3 velocity;
public Vector3 rotation; // rotates the player from side to side
public float camrotation; // rotates the camera up and down
public float jmpspe = 2000f;
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
CalcMovement();
CalcRotation();
Rotate();
}
void FixedUpdate()
{
Move();
}
private void CalcRotation()
{
float yrot = Input.GetAxisRaw("Mouse X"); //around x axis
rotation = new Vector3(0f, yrot, 0f) * looksensitivity;
float xrot = Input.GetAxisRaw("Mouse Y"); //around y axis
camrotation = xrot * looksensitivity;
}
private void CalcMovement()
{
float xmov = Input.GetAxisRaw("Horizontal");
float zmov = Input.GetAxisRaw("Vertical");
Vector3 movhor = transform.right * xmov;
Vector3 movver = transform.forward * zmov;
velocity = (movhor + movver).normalized * speed;
}
void Move()
{
//move
if (velocity != Vector3.zero)
{
rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);
}
//jump
if (Input.GetKeyDown(KeyCode.Space))
{
//add double jump limit later!
rb.AddForce(0, jmpspe * Time.deltaTime, 0, ForceMode.Impulse);
}
}
void Rotate()
{
//looking side to side
rb.MoveRotation(rb.rotation * Quaternion.Euler(rotation));
// camera looking up and down
currentrotx -= camrotation;
currentrotx = Mathf.Clamp(currentrotx, -lowlock, highlock);
cam.transform.localEulerAngles = new Vector3(currentrotx, 0, 0);
}
}
Here are the relevant components attached to my player:
(The player has a couple more components attached but I ran tests without them and the problem still occurs)
Like I said I'm a bit of a unity novice, so i'm sure I missed something small but I just can't seem to place my finger on it, I've been stuck on this for a while so any help is much appreciated.
SOLVED:
It seems the problem I had was because I was running the scene from my laptop and not a desktop which I assume is what the Unity input was built for.
I have made a script with movement, that finally works as i want it to, except one thing... I want it to be a first person game, but the way the movement works now, is on the global axis, which means that W is always torwards one specific direction, no matter what direction my camera is turning... How do i fix this? i want the movement to stay how it is, but with the W key to always be forward depending on the way the camera or player is looking.
Please let me know how my script would look edited, or atleast what part i have to change.
I would also like to add that i would love to be able to do a wall jump, but i am not sure how to add that behavior.
Here is my movement script:
public class MovementScript : MonoBehaviour {
public float speed;
public float jumpforce;
public float gravity = 25;
private Vector3 moveVector;
private Vector3 lastMove;
private float verticalVelocity;
private CharacterController controller;
// Use this for initialization
void Start () {
controller = GetComponent<CharacterController> ();
//Låser og gemmer musen
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update () {
//Låser musen op
if (Input.GetKeyDown ("escape"))
Cursor.lockState = CursorLockMode.None;
moveVector = Vector3.zero;
moveVector.x = Input.GetAxis("Horizontal");
moveVector.z = Input.GetAxis("Vertical");
if (controller.isGrounded) {
verticalVelocity = -1;
if (Input.GetButton("Jump")) {
verticalVelocity = jumpforce;
}
} else {
verticalVelocity -= gravity * Time.deltaTime;
moveVector = lastMove;
}
moveVector.y = 0;
moveVector.Normalize ();
moveVector *= speed;
moveVector.y = verticalVelocity;
controller.Move (moveVector * Time.deltaTime);
lastMove = moveVector;
}
}
You need to go from local to world space:
for example when you want to move on the x-axis regarding the player's orientation, the local vector is (1, 0, 0), which you get from your input axis, but the CharacterController need a world based direction (see the doc of the Move function)
A more complex move function taking absolute movement deltas.
To get this, use Transform.TransformDirection like this
worldMove = transform.TransformDirection(moveVector);
controller.Move (worldMove * Time.deltaTime);
EDIT regarding your issue with the controller moving a bit after releasing the input:
That's because GetAxis gives you a smoothed value. Replace GetAxis by GetAxisRaw and it should work
Modify the final moving code to
controller.Move(moveVector.z * transform.forward * Time.deltaTime);
controller.Move(moveVector.x * transform.right * Time.deltaTime);
controller.Move(moveVector.y * transform.up * Time.deltaTime);
Alternatively, suppose your character is only rotated about the Y axis, you can look into rotating your moveVector by your character's Y rotation so moveVector's forward points parallel to your chracter's forward.
I found a good explaination of rotating a vector here: https://answers.unity.com/questions/46770/rotate-a-vector3-direction.html
Rotating a vector:
moveVector = Quaternion.Euler(0, transform.eulerAngles.y, 0) * moveVector;
I have a little problem with my player control script (C#) in the unity enigne. I worked out the following script with the basic movement of the player. The problem is that the player can enter the jump statement (the debug log printed it out)
Debug Log
but it will not work. The character is still on the ground.
The jump function will be enabled when the player is on the ground (grounded) and did not a double jump.
So my question is are there any "code mistakes" or maybe some configuration problems which I do not see?
Thank you for your help in advance!
using UnityEngine;
using System.Collections;
public class PlayerControl : MonoBehaviour
{
// public variables
public float speed = 3f;
public float jumpHeight = 5f;
// private variables
Vector3 movement;
Animator anim;
Rigidbody2D playerRigidbody;
// variables for the ground check
public Transform groundCheck;
public float groundCheckRadius;
public LayerMask whatIsGround;
private bool grounded;
private bool doubleJump;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
// Proves if the player is on the ground and activate the double jump function
if (grounded)
{
doubleJump = false;
}
// First line of proving the jump
if (Input.GetMouseButtonDown(0) && grounded)
{
Debug.Log("Jump if entered");
Jump();
}
if (Input.GetMouseButtonDown(0) && !doubleJump && !grounded)
{
Debug.Log("double Jump");
Jump();
doubleJump = true;
}
// Flipping the Player when he runs back
if (Input.GetAxis("Horizontal") < 0)
{
playerRigidbody.transform.localScale = new Vector2(-1.7f, 1.7f);
}
else
{
playerRigidbody.transform.localScale = new Vector2(1.7f, 1.7f);
}
}
void Awake()
{
// References setting up
playerRigidbody = this.GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
}
void FixedUpdate()
{
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
// simple Movement without a speed control
Move(horizontal, vertical);
Animating(horizontal, vertical);
// Section for ground detection
grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
// Set the parameter for the jump animation false or true
anim.SetBool("Grounded", grounded);
}
void Move(float horizontal, float vertical)
{
movement.Set(horizontal, 0f, vertical);
movement = movement.normalized * speed * Time.deltaTime;
playerRigidbody.MovePosition(transform.position + movement);
}
void Jump()
{
playerRigidbody.AddForce(Vector3.up * jumpHeight);
// playerRigidbody.AddForce(new Vector2(0f, jumpHeight), ForceMode2D.Impulse);
Debug.Log("Jump function");
}
void Animating(float h, float v)
{
bool walking = h != 0f || v != 0f;
anim.SetBool("IsWalking", walking);
}
}
Just guessing here, but maybe Vector3.up does not work for 2D physics? I'm not really into 2D, but you could try
playerRigidbody.AddForce(transform.up * jumpHeight);
instead.
Also, have you tried different values for jumpHeight? 5 might be way to small depending on the mass you set for your rigidbody.
And make sure you haven't restricted any axes in the inspector.
// Note: If you want the object to move in a reliable predictable way but still allow physics interactions, use MovePosition (set the object to kinematic if you want it to be unaffected by physics but still be able to affect other things, and uncheck kinematic if you want both objects to be able to be acted on by physics.
If you want to move your object but let physics handle the finer details, add a force.
playerRigidbody.rigidbody2D.AddForce(Vector3.up * 10 * Time.deltaTime);
use Vector.up, Vector.down, vector.right, Vectore.left along with time.deltaTime to have smooth movement along the frame.
I'm trying to develop a 3D endless runner game in unity 5. The problem I'm facing is jump. How can I apply a jump to an endless runner? I've been searching and surfing through the internet with no luck. I did find some codes but when I try to apply them, they didn't work. Also How do I adjust the character controller to go up with the animation? A help would be really appreciated.
This is the playerMotor.cs code.
private Vector3 moveVector;
private float verticalVelocity = 0.0f;
private float gravity = 12.0f;
private float jumpPower = 15.0f;
private bool jump;
private float animationDuration = 3.0f;
private float startTime;
private Animator anim;
private CharacterController controller;
void Start()
{
controller = GetComponent<CharacterController>();
anim = GetComponent<Animator>();
startTime = Time.time;
}
void Update()
{
if (Time.time - startTime < animationDuration)
{
controller.Move(Vector3.forward * speed * Time.deltaTime);
return;
}
moveVector = Vector3.zero;
if (controller.isGrounded)
{
verticalVelocity = -0.5f;
if (Input.GetButton("Jump"))
{
verticalVelocity = jumpPower;
anim.SetBool("Jump", true);
}
//anim.SetBool("Jump", false);
}
else
{
verticalVelocity -= gravity * Time.deltaTime;
}
// X - Left and Right
moveVector.x = Input.GetAxisRaw("Horizontal") * speed;
anim.SetFloat("Turn", moveVector.x);
if (Input.GetMouseButton(0))
{
//Are we holding touch on the right side?
if (Input.mousePosition.x > Screen.width / 2)
{
moveVector.x = speed;
}
else
{
moveVector.x = -speed;
}
}
//// Y - Up and Down
//if (Input.GetButtonDown("Jump"))
//{
// moveVector.y = verticalVelocity;
//}
// Z - Forward and Backward
moveVector.z = speed;
controller.Move(moveVector * Time.deltaTime);
}
The codes I used to implement is shown below.
function PlayerController(){
var controller : CharacterController = GetComponent(CharacterController);
moveDirection = Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (controller.isGrounded) {
vSpeed = -1;
if (Input.GetButtonDown ("Jump")) {
vSpeed = jumpSpeed;
}
}
vSpeed -= gravity * Time.deltaTime;
moveDirection.y = vSpeed;
controller.Move(moveDirection * Time.deltaTime);
}
I have applied jump for normal RPG characters but this one is harder than I thought.
From your comment it seems your actual problem is "controller.isGrounded" never ticks in, right?
I described the first issue in comment (anim.SetBool("Jump", false);) related to animation.This second problem comes from your PlayerController code.
You "reset" your jump with setting vSpeed = -1;, right after the frame you just jumped. So techincally, the engine doesn't even have time to react on the jump as the character the next frame gets pulled back hard to the ground (by the "anti-jump" :) you implemented).
What I recommend is, take the sample code from CharacterController.Move, just like you did before you applied your changes, but this time don't alter it!
Just copy-paste the snippet into your app and test. After you made it work "as is", again, without any changes in the code, add the customizations you want, one by one and test every time if the change introduced a defect (bug).I'd also recommend you to start using Debug.Log() while you are coding so you can filter out issues like what you have now, as you'll see what happens in the code "on the fly", when you play-test (.Log variable values with comments, if "branches" when they tick in, calculated values, calls to important functions -like .Move()- etc).
I hope this helps! Cheers!
I finally found the answer to my question. Thanks Mark for the advice you gave me, it helped me a lot.
So here's what I did to make the jump and the jump animation happen. Also note that I'm posting what which is correct not the whole code since I didn't find any other errors in the rest of the script.
moveVector = Vector3.zero;
if (controller.isGrounded) //Check whether are we ground
{
verticalVelocity = -0.5f; //Just to make sure that we are ground
if (Input.GetButton("Jump"))
{
verticalVelocity = 10f; //Basically this is the Jump power to Player
anim.SetBool("Jump", true); //Jump animation to true
}
}
else
{
verticalVelocity -= gravity * speed * Time.deltaTime; //Apply gravity
anim.SetBool("Jump", false); //Set jump animation to false to stop looping continuously
}
//... the rest
This is my own code. Thanks for helping Mark. Cheers to you too.
i have a character controller which jumps but while jumping i want to change the x position of the character so basically he can turn while jumping, this is my attempt so far
//start of character controller
CharacterController controller = GetComponent<CharacterController>();
if (controller.isGrounded) {
//get the player vector movement vector
movePlayer = new Vector3(Input.acceleration.x,0,1);
//float h = Input.acceleration.x;
//translate the players movement
transform.Translate(movePlayer * moveSpeed * Time.deltaTime);
//the run animation
animation.CrossFade("run");
//restrict the movement of x-axis for player
Vector3 pos = transform.position;
pos.x = Mathf.Clamp(pos.x, -3.0f, 3.0f);
transform.position = pos;
if (Input.GetButton("Jump")){
//my ptoblem is here, the x axis on the vector3 is not happening
movePlayer =transform.TransformDirection(new Vector3(Input.acceleration.x,jumpSpeed,forwardJumpSpeed));
}
}
// attach the gravity and move controller
movePlayer.y -= gravity * Time.deltaTime;
controller.Move(movePlayer * Time.deltaTime);
current code:
void Update() {
CharacterController controller = GetComponent<CharacterController>();
//get the player vector movement vector
movePlayer = new Vector3(Input.GetAxis("Horizontal"),0,1);
//float h = Input.acceleration.x;
//translate the players movement
transform.Translate(movePlayer * moveSpeed * Time.deltaTime);
//the run animation
animation.CrossFade("run");
//restrict the movement of x-axis for player
Vector3 pos = transform.position;
pos.x = Mathf.Clamp(pos.x, -3.0f, 3.0f);
transform.position = pos;
if (controller.isGrounded) {
if (Input.GetButton("Jump")){
movePlayer =transform.TransformDirection(new Vector3(Input.acceleration.x,jumpSpeed,forwardJumpSpeed));
}
}
movePlayer.y -= gravity * Time.deltaTime;
controller.Move(movePlayer * Time.deltaTime);
this is my current code, the jump if statement is inside the if(controller.isGrounded) the character still moves but when i press spacebar it deosnt jump anymore.
When the player jumps its no longer grounded so any code under the if(controller.isGrounded) is not called. Put your movement code outside it but keep the jumping code inside it and it'll work fine.
// movement code goes here
// Keep the jumping code inside this if-statement
if (controller.isGrounded) {
if (Input.GetButton("Jump")){
movePlayer =transform.TransformDirection(new Vector3(Input.acceleration.x,jumpSpeed,forwardJumpSpeed));
}