So, I was testing my scripts and i wanted my player to jump with character controller and i am having a problem with it.
Problem
```
public CharacterController control;
public float playerSpeed;
public float jumpSpeed;
void Start()
{
playerSpeed = 6.0f;
jumpSpeed = 50;
}
void Update()
{
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
Vector3 move = new Vector3 (h, 0, v);
Vector3 velocity = move * playerSpeed;
if (control.isGrounded && Input.GetKey(KeyCode.Space))
{
velocity.y += jumpSpeed; // velocity.y = jumpSpeed; tried both
}
else
{
velocity += Physics.gravity * Time.deltaTime;
}
control.Move(velocity * Time.deltaTime);
}
}```
Here's my unity screen and code above.
The problem is when i press jump it does jump but it's position goes to 2.068, i.e it jumps to low and when gravity is activated it comes down to slow, it takes around 6 seconds to come to its initial position.
I even tried to add a parent object to it so that it may change, but it does the same to it.
if (control.isGrounded && Input.GetKey(KeyCode.Space))
{
// first just try this
velocity.y += jumpSpeed * Time.deltaTime;
}
else
{
velocity.y -= Physics.gravity * Time.deltaTime;
}
and if it is not working
Vector3 move = new Vector3 (h, 0, 0);
Vector3 jump = new Vector3 (0, 0, v);
Vector3 _velocityMove = move * playerSpeed;
Vector3 _velocityJump = jump* jumpSpeed;
if (control.isGrounded && Input.GetKey(KeyCode.Space))
{
velocity.y += _velocityJump ;//and you can add ' * Time.deltaTime '
}
else
{
velocity += Physics.gravity * Time.deltaTime;
}
control.Move(_velocityMove * Time.deltaTime);
ohk so I tweaked some of my code and instead of declaring velocity.y in the condition of if the player is grounded , i declared outside the condition and change the value of variable in condition.
velocity.y = jumpSpeed;
if (control.isGrounded && Input.GetKey(KeyCode.Space))
{
jumpSpeed = 10;
}
else
{
jumpSpeed += Physics.gravity.y * Time.deltaTime;
}
This seems to do the trick and my player can jump nicely.
Related
wont let me run and jump at the same time, movement works fine but when i sprint jump isnt registered i tried a few things but nothing was successful
the character is a capsule and camera
this is the relevant code:
void UpdateMovement()
{
Vector2 targetDir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
targetDir.Normalize();
currentDir = Vector2.SmoothDamp(currentDir, targetDir, ref currentDirVelocity, moveSmoothTime);
if(controller.isGrounded)
{
if(Input.GetKeyDown(KeyCode.Space))
{
velocityY = 10.0f;
Debug.Log("Jump");
}
else
{
velocityY = 0.0f;
}
}
speed = walkSpeed;
if(Input.GetKey(KeyCode.LeftShift))
{
//Debug.Log("Sprint");
speed = walkSpeed * sprintMultiplier;
}
velocityY += gravity * Time.deltaTime;
Vector3 velocity = transform.forward * currentDir.y * speed + transform.right * currentDir.x * speed + Vector3.up * velocityY;
controller.Move(velocity * Time.deltaTime);
//Debug.Log(speed);
}
thank you in advance for any help
I am writing a script for movement and mouselook, the movement works but the mouse look does not. I start the game, the cursor locks into the game screen and I can move but I can't look around and there are no bugs. can someone help?
Here is my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player_Controller : MonoBehaviour
{
[SerializeField]private float _speed = 7f;
[SerializeField]private float _mouseSensitivity = 50f;
[SerializeField]private float _minCameraview = -70f, _maxCameraview = 80f;
private CharacterController _charController;
private Camera _camera;
private float xRotation = 0f;
// Start is called before the first frame update
void Start()
{
_charController = GetComponent<CharacterController>();
_camera = Camera.main;
if(_charController == null)
Debug.Log("No Character Controller Attached to Player");
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
//Get WASD Input for Player
float vertical = Input.GetAxis("Vertical");
float horizontal = Input.GetAxis("Horizontal");
//move player based on WASD Input
Vector3 movement = Vector3.forward * vertical + Vector3.right * horizontal;
_charController.Move(movement * Time.deltaTime * _speed);
//Get Mouse position Input
float mouseX = Input.GetAxis("Mouse X") * _mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * _mouseSensitivity * Time.deltaTime;
//Rotate the camera based on the Y input of the mouse
xRotation -= mouseY;
//clamp the camera rotation between 80 and -70 degrees
xRotation = Mathf.Clamp(xRotation, _minCameraview, _maxCameraview);
_camera.transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
//Rotate the player based on the X input of the mouse
transform.Rotate(Vector3.up * mouseX * 3);
}
}
The problem is that you are multiplying the mouse input by Time.deltaTime. Time.deltaTime is used when you want to have different devices with different frame rates. This is because when multiplying by Time.deltaTime, you get a constant speed of one unit per second:
float speed = 10f;
float movement = speed * Time.deltaTime;
If you have a frame rate of 10fps (hopefully you don't), you would have each frame in 0.1 second. Each frame is 0.1 second, so when multiplying it by 10 (the speed), you get a value of one. If you speed the frame rate up, you would also get 10 units a second (1 x 10 = 10).
The mouse movement doesn’t need this because mouse movement is not handled by the computer. In other words, when you are moving the mouse, it isn’t changing by the frame rate, so you don’t need ‘Time.deltaTime`.
I also noticed that your movement was based on Vector3. What I mean by this is that you were using global coordinates rather than local (transform). This means if the play rotates, Vector3.forward will be different than the player’s forward. You should use transform.forward instead to use local coordinates.
You should change the script to this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player_Controller : MonoBehaviour
{
[SerializeField]private float _speed = 7f;
[SerializeField]private float _mouseSensitivity = 50f;
[SerializeField]private float _minCameraview = -70f, _maxCameraview = 80f;
private CharacterController _charController;
private Camera _camera;
private float xRotation = 0f;
// Start is called before the first frame update
void Start()
{
_charController = GetComponent<CharacterController>();
_camera = Camera.main;
if(_charController == null)
Debug.Log("No Character Controller Attached to Player");
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
//Get WASD Input for Player
float vertical = Input.GetAxis("Vertical");
float horizontal = Input.GetAxis("Horizontal");
//move player based on WASD Input
Vector3 movement = transform.forward * vertical + transform.right * horizontal; //changed this line.
_charController.Move(movement * Time.deltaTime * _speed);
//Get Mouse position Input
float mouseX = Input.GetAxis("Mouse X") * _mouseSensitivity; //changed this line.
float mouseY = Input.GetAxis("Mouse Y") * _mouseSensitivity; //changed this line.
//Rotate the camera based on the Y input of the mouse
xRotation -= mouseY;
//clamp the camera rotation between 80 and -70 degrees
xRotation = Mathf.Clamp(xRotation, _minCameraview, _maxCameraview);
_camera.transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
//Rotate the player based on the X input of the mouse
transform.Rotate(Vector3.up * mouseX * 3);
}
}
This is a script for both movement and looking
[RequireComponent(typeof(CharacterController))]
public class NewBehaviourScript : MonoBehaviour
{
public float walkingSpeed = 7.5f;
public float runningSpeed = 11.5f;
public float jumpSpeed = 8.0f;
public float gravity = 20.0f;
public Camera playerCamera;
public float lookSpeed = 2.0f;
public float lookXLimit = 45.0f;
CharacterController characterController;
Vector3 moveDirection = Vector3.zero;
float rotationX = 0;
[HideInInspector]
public bool canMove = true;
// Start is called before the first frame update
void Start()
{
characterController = GetComponent<CharacterController>();
// Lock cursor
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
// Update is called once per frame
void Update()
{
// We are grounded, so recalculate move direction based on axes
Vector3 forward = transform.TransformDirection(Vector3.forward);
Vector3 right = transform.TransformDirection(Vector3.right);
// Press Left Shift to run
bool isRunning = Input.GetKey(KeyCode.LeftShift);
float curSpeedX = canMove ? (isRunning ? runningSpeed : walkingSpeed) * Input.GetAxis("Vertical") : 0;
float curSpeedY = canMove ? (isRunning ? runningSpeed : walkingSpeed) * Input.GetAxis("Horizontal") : 0;
float movementDirectionY = moveDirection.y;
moveDirection = (forward * curSpeedX) + (right * curSpeedY);
if (Input.GetButton("Jump") && canMove && characterController.isGrounded)
{
moveDirection.y = jumpSpeed;
}
else
{
moveDirection.y = movementDirectionY;
}
// Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
// when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
// as an acceleration (ms^-2)
if (!characterController.isGrounded)
{
moveDirection.y -= gravity * Time.deltaTime;
}
// Move the controller
characterController.Move(moveDirection * Time.deltaTime);
// Player and Camera rotation
if (canMove)
{
rotationX += -Input.GetAxis("Mouse Y") * lookSpeed;
rotationX = Mathf.Clamp(rotationX, -lookXLimit, lookXLimit);
playerCamera.transform.localRotation = Quaternion.Euler(rotationX, 0, 0);
transform.rotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * lookSpeed, 0);
}
}
}
Basically I want to make bouncing stick and rotate control, with the left-right button.i'm facing an issue that the rotate not good as I expected because it won't follow my button like being affected by something after bouncing,
I'm using 2d physics material with friction = 1 and Bounciness = 0.9797 for perfect bouncing also attached to rigidbody2d.
I don't know, should I attach it on collider?
here my Player control Script:
public Rigidbody2D r2d;
public float vertical;
public float horizontal;
public Joystick joystick;
private void Start() {
r2d = gameObject.GetComponent < Rigidbody2D > ();
joystick = FindObjectOfType < Joystick > ();
}
private void Update() {
Movement();
}
public void Movement() {
r2d.velocity = r2d.velocity.normalized * 7f;
//horizontal = joystick.Horizontal;
//vertical = joystick.Vertical;
//if (horizontal == 0 && vertical == 0)
//{
// Vector3 curRot = transform.localEulerAngles;
// Vector3 homeRot = transform.localEulerAngles;
// transform.localEulerAngles = Vector3.Slerp(curRot, homeRot, Time.deltaTime * 2);
//}
//else
//{
// transform.localEulerAngles = new Vector3(0f, 0f, Mathf.Atan2(horizontal, vertical) * -180 / Mathf.PI);
//}
}
public Vector3 target;
public float rotationSpeed = 10f;
public float offset = 5;
public void turnLeft() {
Vector3 dir = target - transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.Euler(new Vector3(0, 0, angle + offset));
transform.rotation = Quaternion.Slerp(transform.rotation, -rotation, rotationSpeed * Time.deltaTime);
}
public void turnRight() {
Vector3 dir = target - transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.Euler(new Vector3(0, 0, angle + offset));
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, rotationSpeed * Time.deltaTime);
}
Whenever there is a Rigidbody/Rigidbody2D involved you do not want to manipulate anything via the .transform component!
This breaks the physics, collision detection and leads to strange movements basically the transform "fighting" against physics for priority.
What you rather want to do would be e.g. adjusting the Rigidbody2D.angularVelocity
public void turnLeft()
{
// Note that Time.deltaTime only makes sense if this is actually called every frame!
r2d.angularVelocity -= rotationSpeed * Time.deltaTime;
}
public void turnRight()
{
r2d.angularVelocity += rotationSpeed * Time.deltaTime;
}
I have implemented a player movement and jump in my game. I also attached a run and jump animation to animator. However, the jump animation does not perfectly match with the player vertical movement. How can I match them perfectly?
Thanks in advance,
void Control()
{
if (charController.isGrounded)
{
float h = Joystick.GetHorizontalAxis("MyJoystick");
float v = Joystick.GetVerticalAxis("MyJoystick");
moveDirection = new Vector3(h, 0.0f, v);
moveDirection *= (speed * sprint);
anim.SetFloat("WalkSpeed", moveDirection.magnitude);
if (moveDirection.magnitude > 0.5)
{
anim.SetFloat("WalkSpeed", moveDirection.magnitude / speed);
anim.SetFloat("Walk", 1.0f);
transform.forward = moveDirection;
}
else if (moveDirection.magnitude > 0 && moveDirection.magnitude < 0.5)
{
anim.SetFloat("WalkSpeed", moveDirection.magnitude / (speed * 0.5f));
anim.SetFloat("Walk", 0.5f);
transform.forward = moveDirection;
}
else if (moveDirection.magnitude == 0)
{
anim.SetFloat("Walk", 0f);
}
if (Input.GetKeyDown("space"))
{
moveDirection.y = jumpSpeed;
anim.SetTrigger("Jump");
}
}
moveDirection.y -= gravity * Time.deltaTime;
charController.Move(moveDirection * Time.deltaTime);
}
There is an option in the Animator component to do what you want.
Here is a link that describes it in more details.
I am developing endless runner game like subway surfer in Unity.
I want to move my player, smoothly on swipe left or right.
How can do it?
Here is my code:
using UnityEngine;
using System.Collections;
public class SwipeScript3 : MonoBehaviour {
private Touch initialTouch = new Touch();
private float distance = 0;
private bool hasSwiped = false;
//Quaternion targetx = Quaternion.Euler(0, -3f, 0);
//Quaternion targety = Quaternion.Euler(0, 3f, 0);
void FixedUpdate()
{
foreach(Touch t in Input.touches)
{
if (t.phase == TouchPhase.Began)
{
initialTouch = t;
}
else if (t.phase == TouchPhase.Moved && !hasSwiped)
{
float deltaX = initialTouch.position.x - t.position.x;
float deltaY = initialTouch.position.y - t.position.y;
distance = Mathf.Sqrt((deltaX * deltaX) + (deltaY * deltaY));
bool swipedSideways = Mathf.Abs(deltaX) > Mathf.Abs(deltaY);
if (distance > 50f)
{
if (swipedSideways && deltaX > 0) //swiped left
{
//transform.rotation = Quaternion.Slerp (transform.rotation, targetx, Time.deltaTime * 0.8f);
this.transform.Rotate(new Vector3(0, -3f, 0)*Time.deltaTime);
//transform.position = Vector3.Lerp (transform.position,new Vector3(transform.position.x+5f,transform.position.y,transform.position.z),Time.deltaTime*2f );
transform.position = Vector3.Lerp (transform.position, new Vector3 (transform.position.x - 5f, transform.position.y, transform.position.z), Time.deltaTime * 5f);
}
else if (swipedSideways && deltaX <= 0) //swiped right
{
//transform.rotation = Quaternion.Slerp (transform.rotation, targety, Time.deltaTime * 0.8f);
this.transform.Rotate(new Vector3(0, 3f, 0)*Time.deltaTime);
//transform.position = Vector3.Lerp (transform.position, new Vector3 (transform.position.x - 5f, transform.position.y, transform.position.z), Time.deltaTime * f);
transform.position = Vector3.Lerp (transform.position,new Vector3(transform.position.x+5f,transform.position.y,transform.position.z),Time.deltaTime*5f );
}
else if (!swipedSideways && deltaY > 0) //swiped down
{
//this.transform.Rotate(new Vector3(0, 2f, 0));
transform.position = Vector3.Lerp (transform.position,new Vector3(transform.position.x,transform.position.y,transform.position.z-5f),Time.deltaTime*2f );
}
else if (!swipedSideways && deltaY <= 0) //swiped up
{
this.GetComponent<Rigidbody>().velocity = new Vector3(this.GetComponent<Rigidbody>().velocity.x, 0, this.GetComponent<Rigidbody>().velocity.z);
this.GetComponent<Rigidbody>().AddForce(new Vector3(0, 400f, 0));
Debug.Log ("Swiped Up");
}
hasSwiped = true;
}
}
else if (t.phase == TouchPhase.Ended)
{
initialTouch = new Touch();
hasSwiped = false;
}
}
}
}
You could use Vector3.Slerp(Vector3 StartPosition, Vector3 DestinationPosition, float Number)
Number is between 0 and 1 and it indicates where will be the position of your object between StartPosition and DestinationPosition.
Lets say Number = 0.0f;: your object will be at StartPosition.
If Number = 0.5f;: your object will be between StartPosition and DestinationPosition.
You need to increase the Number value from 0 to 1 when swipe action is performed.
The faster you increase the "Number" value, the faster your object will move towards Destination.
You should set you StartPosition once when the swipe action begins, not give your transform.position repeatedly in your Vector3.Slerp() function.
You can find an example here in Unity Docs.
Hope this helps! Cheers!