Character run faster with 2 buttons pressed at same time - c#

Im trying to make controller script for my character. Everything works ok, but when i press 2 movement buttons at same time my character moves faster.
If i press D it moves slower than if i press D+S or D+W. How i can fix that? I want my character to move with same speed.
Code:
AnimationsCharacter animations;
CharacterController controller;
Transform camera;
Vector3 camForward;
Vector3 camRight;
Vector3 motion;
float horizontal;
float vertical;
float sprint;
float inputMagnitude;
float speed;
float defaultSpeed = 5;
float sprintSpeed = 10;
void Start()
{
controller = GetComponent<CharacterController>();
animations = GetComponent<AnimationsCharacter>();
camera = Camera.main.transform;
}
void FixedUpdate()
{
GetMoveInput();
}
public void GetMoveInput()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
sprint = Input.GetAxis("Sprint");
if (horizontal != 0 || vertical != 0)
{
if(sprint != 0)
{
speed = sprintSpeed;
}
else
{
speed = defaultSpeed;
}
CalculateCamera();
Move();
}
}
public void CalculateCamera()
{
camForward = camera.forward;
camRight = camera.right;
camForward.y = 0;
camRight.y = 0;
camForward = camForward.normalized;
camRight = camRight.normalized;
}
public void Move()
{
motion = (camForward * vertical + camRight * horizontal);
inputMagnitude = new Vector2(horizontal, vertical).sqrMagnitude;
controller.Move(motion * speed * Time.deltaTime);
animations.AnimMovement(inputMagnitude);
transform.rotation = Quaternion.LookRotation(motion);
}
I tried different things, like /2 if 2 buttons pressed. Seems like i do something wrong.

You should Normalize the motion in the case that it has a sqrMagnitude > 1 (= magnitude > 1 but cheaper access) so it has always magnitude <= 1.
motion = (camForward * vertical + camRight * horizontal);
if(motion.sqrMagnitude > 1)
{
motion.Normalize();
}

Related

How to make sliding mechanic gain speed when on a slope

I am a new unity developer that is trying to make a 3d game. So far I have managed to develop a pretty cool first-person character controller. It uses a character controller and it has sliding and jumping mechanics.
And the question is:
How can I make my player lose sliding speed when sliding up a slope and gain sliding speed when sliding down a slope?
Here is my code so far and please keep in mind that my code is messy and that I am a still beginner. If you need any further information please don't hesitate to ask. Thanks for your time! Also, any suggestions are more than welcome!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovementScript : MonoBehaviour
{
//Character controller refrence
private CharacterController controller;
//Camera refrence
[SerializeField] Camera fpsCam;
//IsGrounded variables
private float groundDistance = 1.5f;
public bool isGrounded;
//SomethingAbove variables
private float cellingDistance = 1.5f;
public bool somethingAbove;
//Variables
//Speed that is modified
private float speed = 12f;
//Default speed
private float baseSpeed = 12f;
//Slide speed that is modified
private float slideSpeed = 15f;
//Default slide speed
private float slideSpeedStorage = 15f;
//Crouch speed
private float crouchSpeed = 3f;
//Jump height
private float jumpHeight = 2f;
private bool isJumping = false;
//Gravity
private float gravity = -14.715f;
//Air resistance
private float xAirResistance = 0.5f;
private float zAirResistance = 0.35f;
//Air multipiler
private float airMultiplierJump = 1.1f;
//Fov
private float fovWhenSliding = 100f;
private float defaultFov;
//Crouch variables
float originalHeight;
float reducedHeight = 0.5f;
//Player input
float x;
float z;
bool jump;
bool control;
//Directions
Vector3 velocity;
private Vector3 move = new Vector3();
private Vector3 slideDirection = new Vector3();
private Vector3 jumpDirection = new Vector3();
private void Awake()
{
controller = GetComponent<CharacterController>();
}
private void Start()
{
//Getting the original height
originalHeight = controller.height;
//Getting the default fov
defaultFov = fpsCam.fieldOfView;
}
private void Update()
{
MyInput();
Calculations();
PlayerMovement();
}
private void MyInput()
{
//Getting WASD input
x = Input.GetAxis("Horizontal");
z = Input.GetAxis("Vertical");
//Space bar input
jump = Input.GetButtonDown("Jump");
//Left control input
control = Input.GetKey(KeyCode.LeftControl);
}
private void Calculations()
{
//Checking if player is grounded
Debug.DrawRay(transform.position, Vector3.down * groundDistance, Color.red);
isGrounded = Physics.Raycast(transform.position, Vector3.down, groundDistance);
//Checking if player can get up
Debug.DrawRay(transform.position, Vector3.up * cellingDistance, Color.black);
somethingAbove = Physics.Raycast(transform.position, Vector3.up, cellingDistance);
/*//Getting the player has enough speed and getting jump direction
if (isGrounded && jump && z > 0)
{
//If pressing W the jump direction is forward
jumpDirection = transform.forward;
}*/
//Movement in air
if (isGrounded)
{
//On ground movement
move = transform.right * x + transform.forward * z;
}
else
{
//If pressing W
if (z > 0)
{
//Jump direction multiplied by airMultiplierJump
move = transform.forward * z * airMultiplierJump + transform.right * x * xAirResistance;
}
else
{
//Jump direction = Vector3.zero;
move = transform.forward * z * zAirResistance + transform.right * x * xAirResistance;
}
}
//Checking if the player has enough speed for sliding and getting direction
if (Input.GetKeyDown(KeyCode.LeftControl) && isGrounded)
{
if (z == 1 || x == 1 || x == -1)
{
//If pressing W || A || D slide direction is the direction u are moving towards
slideDirection = transform.forward * z + transform.right * x;
}
else
{
//If pressing S the slide direction is zero
slideDirection = Vector3.zero;
}
}
//Adding extra force so the player stays on ground
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
//Calculating gravity
velocity.y += gravity * Time.deltaTime;
//Normalizing the move vector so the diagonal and normal movement are the same speed
if (move.sqrMagnitude > 1)
{
move.Normalize();
}
//Extra force on slope downwards so the player stays on it
if((x != 0 || z != 0) && OnSlope())
{
controller.Move(Vector3.down * controller.height / 2 * 2f);
}
}
private void PlayerMovement()
{
Jump();
Slide();
//Moving the player with WASD
controller.Move(move * speed * Time.deltaTime);
//Applying gravity
controller.Move(velocity * Time.deltaTime);
}
private void Slide()
{
//Checking for left control input and if the player is grounded
if(control && isGrounded && !OnSlope())
{
StartSlide();
}
//Checking if the player can uncrouch
else if(!somethingAbove && isGrounded)
{
StopSlide();
}
else if (!control)
{
controller.height = originalHeight;
speed = baseSpeed;
}
else if(control && !isGrounded)
{
controller.height = originalHeight;
speed = baseSpeed;
}
else
{
controller.height = reducedHeight;
speed = crouchSpeed;
}
}
//Starting to slide
private void StartSlide()
{
if (z != 1 || x != -1 || x != 1)
{
speed = crouchSpeed;
}
else
{
speed = 0f;
}
controller.height = reducedHeight;
controller.Move(slideDirection * Time.deltaTime * slideSpeed);
slideSpeed -= 10f * Time.deltaTime;
if (slideSpeed <= 0)
{
slideSpeed = 0f;
speed = crouchSpeed;
}
}
//Stopping the slide
private void StopSlide()
{
controller.height = originalHeight;
speed = baseSpeed;
//Slide speed recovery
slideSpeed = Mathf.Lerp(slideSpeed, slideSpeedStorage, Time.deltaTime * 2);
}
//Jumping mechanic
private void Jump()
{
if (jump && isGrounded)
{
isJumping = true;
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
}
private bool OnSlope()
{
if (isJumping)
{
return false;
}
RaycastHit hit;
if(Physics.Raycast(transform.position, Vector3.down, out hit, controller.height / 2 * 5f))
if(hit.normal != Vector3.up)
{
return true;
}
return false;
}
//Stopping the slide if hitting object
private void OnControllerColliderHit(ControllerColliderHit hit)
{
if(hit.transform.tag == "SlideStop")
{
slideSpeed = 0f;
speed = crouchSpeed;
}
}
}```
private bool OnSlope()
{
if (isJumping)
{
return false;
}
RaycastHit hit;
if(Physics.Raycast(transform.position, Vector3.down, out hit, controller.height / 2 * 5f))
if(hit.normal != Vector3.up)
{
return true;
}
return false;
}
One issue is comparing Vector3s which is bad practice, since they are arrays of floats. Even if the plane is completely planar, it might still return true due to what's known as 'floating point errors'. A better practice is to use:
Vector3.distance(hit.normal, Vector3.up) > .1f // or some other small value;

Rotate 2D Sprite with Virtual Joystick

I am trying to rotate a GameObject along z-axis using Joystick, but its rotating y-axis. I might missed some math calculation. Any Help??
Reference Image
void FixedUpdate()
{
// get input from joystick
// get input from joystick
rightJoystickInput = rightJoystick.GetInputDirection();
float xMovementRightJoystick = rightJoystickInput.x; // The horizontal movement from joystick 02
float zMovementRightJoystick = rightJoystickInput.y; // The vertical movement from joystick 02
// if there is only input from the right joystick
if (rightJoystickInput != Vector3.zero)
{
// calculate the player's direction based on angle
float tempAngle = Mathf.Atan2(zMovementRightJoystick, xMovementRightJoystick);
xMovementRightJoystick *= Mathf.Abs(Mathf.Cos(tempAngle));
zMovementRightJoystick *= Mathf.Abs(Mathf.Sin(tempAngle));
// rotate the player to face the direction of input
Vector3 temp = transform.position;
temp.x += xMovementRightJoystick;
temp.z += zMovementRightJoystick;
Vector3 lookDirection = temp - transform.position;
if (lookDirection != Vector3.zero)
{
rotationTarget.localRotation = Quaternion.Slerp(rotationTarget.localRotation, Quaternion.LookRotation(lookDirection) * Quaternion.Euler(0, 45f, 0), rotationSpeed * Time.deltaTime);
}
}
}
You don't need most of the code in your question and this is really simple.
1.Find the angle with Mathf.Atan2 then multiple it with Mathf.Rad2Deg.
2.Use Quaternion.Euler(new Vector3(0, 0, angle)) to get the rotation then apply it to the Object.
This should be one in the Update function not FixedUpdate because FixedUpdate is used to move Rigidbody Objects.
public Transform rotationTarget;
public bool flipRot = true;
void Update()
{
rightJoystickInput = rightJoystick.GetInputDirection();
float horizontal = rightJoystickInput.x;
float vertical = rightJoystickInput.y;
float angle = Mathf.Atan2(horizontal, vertical) * Mathf.Rad2Deg;
angle = flipRot ? -angle : angle;
rotationTarget.rotation = Quaternion.Euler(new Vector3(0, 0, angle));
}
If using Rigidbody2D then use Rigidbody2D.MoveRotation in the FixedUpdate function. The rest of the code stays the-same.
public Rigidbody2D rg2d;
public bool flipRot = true;
void FixedUpdate()
{
rightJoystickInput = rightJoystick.GetInputDirection();
float horizontal = rightJoystickInput.x;
float vertical = rightJoystickInput.y;
float angle = Mathf.Atan2(horizontal, vertical) * Mathf.Rad2Deg;
angle = flipRot ? -angle : angle;
rg2d.MoveRotation(angle);
}
EDIT:
But only the problem is when i leave joystick its rotation is setting
to 0 instantly which looks too odd. How can i fix it?
You have to detect when you release the joystick in OnPointerUp then slowly lerp the joystick thump back to the Zero position. You also have to lerp the current target object angle to zero or to its default value and this should be done in a coroutine function. When OnPointerDown is called, stop the current coroutine function. Prevent the code in FixedUpdate from running when finger is released so that it won't interfere with the coroutine function.
For the sake of completeness, below is the combination of a Joystick code and the Rigidbody answer above:
public class VirtualJoystickController : MonoBehaviour,
IDragHandler, IPointerUpHandler, IPointerDownHandler
{
private Image bgImg;
private Image joystickImg;
public float mas_distance = 7f;
void Start()
{
bgImg = GameObject.Find("JoystickBGImage").GetComponent<Image>(); // the joysticks background
joystickImg = GameObject.Find("Joystickthumb").GetComponent<Image>(); // the joystick object to use
}
private Vector3 _inputDirection = Vector3.zero;
//the movementDirection
public Vector3 joystickInputDirection
{
set
{
//Change only if value is different from old one
if (_inputDirection != value)
{
_inputDirection = value;
Debug.Log("Dir: " + _inputDirection);
}
}
get
{
return _inputDirection;
}
}
public void OnDrag(PointerEventData eventData)
{
dragJoyStick(eventData);
}
void dragJoyStick(PointerEventData eventData)
{
Vector3 tempDir = Vector3.zero;
Vector2 pos = Vector2.zero;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle
(bgImg.rectTransform,
eventData.position,
eventData.pressEventCamera,
out pos))
{
pos.x = (pos.x / bgImg.rectTransform.sizeDelta.x);
pos.y = (pos.y / bgImg.rectTransform.sizeDelta.y);
float x = (bgImg.rectTransform.pivot.x == 1) ? pos.x * 2 + 1 : pos.x * 2 - 1;
float y = (bgImg.rectTransform.pivot.y == 1) ? pos.y * 2 + 1 : pos.y * 2 - 1;
tempDir = new Vector3(x, y, 0);
if (tempDir.magnitude > 1)
{
tempDir = tempDir.normalized;
}
joystickImg.rectTransform.anchoredPosition = new Vector3(
tempDir.x * (bgImg.rectTransform.sizeDelta.x / mas_distance),
tempDir.y * (bgImg.rectTransform.sizeDelta.y / mas_distance));
joystickInputDirection = tempDir;
}
}
public void OnPointerDown(PointerEventData eventData)
{
released = false;
//Stop current coroutine
if (retCoroutine != null)
StopCoroutine(retCoroutine);
if (eventData.pointerCurrentRaycast.gameObject == bgImg.gameObject ||
eventData.pointerCurrentRaycast.gameObject == joystickImg.gameObject)
{
OnDrag(eventData);
}
}
public void OnPointerUp(PointerEventData eventData)
{
released = true;
//Stop current coroutine then start a new one
if (retCoroutine != null)
StopCoroutine(retCoroutine);
retCoroutine = StartCoroutine(SlowReturn(returnTime));
}
IEnumerator SlowReturn(float duration)
{
RectTransform thumbstickTransform = joystickImg.rectTransform;
Vector3 toPosition = Vector3.zero;
float counter = 0;
//Get the current position of the object to be moved
Vector2 currentThumb = thumbstickTransform.anchoredPosition;
while (counter < duration)
{
counter += Time.deltaTime;
//Slowly returns thumbstick
Vector2 tempThumbStickVal = Vector2.Lerp(currentThumb, toPosition, counter / duration);
joystickInputDirection = tempThumbStickVal;
thumbstickTransform.anchoredPosition = tempThumbStickVal;
//Slowly returns the target Object to original pos
float tempTargetObjAngle = Mathf.Lerp(angle, originalAngle, counter / duration);
rg2d.MoveRotation(tempTargetObjAngle);
yield return null;
}
}
public float returnTime = 1.0f;
public Rigidbody2D rg2d;
public bool flipRot = true;
const float originalAngle = 0;
bool released = true;
float angle;
Coroutine retCoroutine;
void FixedUpdate()
{
if (released)
return;
float horizontal = joystickInputDirection.x;
float vertical = joystickInputDirection.y;
angle = Mathf.Atan2(horizontal, vertical) * Mathf.Rad2Deg;
angle = flipRot ? -angle : angle;
rg2d.MoveRotation(angle);
}
}
your function calculates a point where you want to look at:
Vector3 temp = transform.position;
temp.x += xMovementRightJoystick;
temp.z += zMovementRightJoystick;
Vector3 lookDirection = temp - transform.position;
this point is on the XZ plane, that is why the car rotates on Y axis
if you want to rotate on Z axis, calculate a point on XY plane like this:
Vector3 temp = transform.position;
temp.x += xMovementRightJoystick;
temp.y += zMovementRightJoystick;
Vector3 lookDirection = temp - transform.position;
PS: i don't know why you multiply with Quaternion.Euler(0, 45f, 0) - that is a constant angle on Y axis, it just means that each lookDirection will be rotated for 45 degrees - i would have to see your scene to know why you need this...

Can't create elevator using waypoints in Unity3d

I have a script for waypoints, which I find here. It works fine for objects, which move on the horizontal axes. But it don't move objects up and down. Can't understand, why.
Elevator are just decoration and it will randomly move from one floor to another.
public Transform[] waypoint; // The amount of Waypoint you want
float patrolSpeed = 3.0f; // The walking speed between Waypoints
float dampingLook = 6.0f; // How slowly to turn
public float pauseDuration; // How long to pause at a Waypoint
float curTime;
int currentWaypoint;
CharacterController character;
void Start()
{
character = GetComponent<CharacterController>();
}
void Update()
{
if (currentWaypoint < waypoint.Length)
Patrol();
else
currentWaypoint = 0;
}
void Patrol()
{
Vector3 target = waypoint[currentWaypoint].position;
target.y = transform.position.y; // Keep waypoint at character's height
Vector3 moveDirection = target - transform.position;
if(moveDirection.magnitude < 0.5)
{
if (curTime == 0)
curTime = Time.time; // Pause over the Waypoint
if ((Time.time - curTime) >= pauseDuration)
{
currentWaypoint = Random.Range(0, waypoint.Length);
curTime = 0;
}
}
else
{
var rotation = Quaternion.LookRotation(target - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * dampingLook);
character.Move(moveDirection.normalized * patrolSpeed * Time.deltaTime);
}
}
Edit1:
Here is the video how it works.
Try this, without a rigidbody:
using UnityEngine;
using System.Collections;
public class Elevator : MonoBehaviour {
public Transform[] waypoint; // The amount of Waypoint you want
float patrolSpeed = 3.0f; // The walking speed between Waypoints
float dampingLook = 6.0f; // How slowly to turn
public float pauseDuration; // How long to pause at a Waypoint
float curTime;
int currentWaypoint;
void Update()
{
if (currentWaypoint < waypoint.Length)
Patrol();
else
currentWaypoint = 0;
}
void Patrol()
{
Vector3 target = waypoint[currentWaypoint].position;
Vector3 moveDirection = target - transform.position;
if(moveDirection.magnitude < 0.5)
{
if (curTime == 0)
curTime = Time.time; // Pause over the Waypoint
if ((Time.time - curTime) >= pauseDuration)
{
currentWaypoint = Random.Range(0, waypoint.Length);
curTime = 0;
}
}
else
{
transform.Translate(moveDirection.normalized * patrolSpeed * Time.deltaTime);
}
}
}
Edit: Correct the script by removing two rotation lines.

Two Raycast causes a lag

I need your help.
I make a Hover-car movement script.
Distance to ground and the Hover movement is calculated by Raycast,
I make another Raycast, because there was a problem - hover flew too high if you hold the button pressed.
But now with two Raycast it cause a lag - Hover moves in jerks.
Interpolate does not help.
How can I make smooth movement without jerking?
Please, help.
public class hoverController_v7 : MonoBehaviour
Rigidbody carBody;
float deadZone = 0.1f;
public float hoverForce = 9.0f;
public float hoverHeight = 2.0f;
public GameObject[] hoverPoints;
public float forwardAcceleration = 100.0f;
public float backwardAcceleration = 25.0f;
public float currThrust = 0.0f;
public float turnStrength = 10.0f;
public float currTurn = 0.0f;
public GameObject leftAirBrake;
public GameObject rightAirBrake;
int layerMask;
void Start()
{
carBody = GetComponent<Rigidbody>();
layerMask = 1 << LayerMask.NameToLayer("Characters");
layerMask = ~layerMask;
}
void OnDrawGizmos()
{
// сила hoverForce
RaycastHit hit;
for(int i = 0; i < hoverPoints.Length; i++)
{
var hoverPoint = hoverPoints[i];
if(Physics.Raycast(hoverPoint.transform.position,
-Vector3.up, out hit,
hoverHeight,
layerMask))
{
Gizmos.color = Color.yellow;
//Color if correctly alligned
Gizmos.DrawLine(hoverPoint.transform.position, hit.point);
Gizmos.DrawSphere(hit.point, 0.5f);
}
else
{
Gizmos.color = Color.red;
//Color if incorrectly alligned
Gizmos.DrawLine (hoverPoint.transform.position, hoverPoint.transform.position - Vector3.up * hoverHeight);
}
}
}
void Update()
{
// main thrust
currThrust = 0.0f;
float aclAxis = Input.GetAxis("Vertical");
if(aclAxis > deadZone)
{
currThrust = aclAxis * forwardAcceleration;
}
else if(aclAxis < -deadZone)
{
currThrust = aclAxis * backwardAcceleration;
}
// Turning
currTurn = 0.0f;
float turnAxis = Input.GetAxis("Mouse X") * 2;
if(Mathf.Abs(turnAxis) > deadZone)
currTurn = turnAxis;
}
void FixedUpdate()
{
// hover force
RaycastHit hit;
for(int i = 0; i < hoverPoints.Length; i++)
{
var hoverPoint = hoverPoints[i];
if(Physics.Raycast(hoverPoint.transform.position,
-Vector3.up, out hit,
hoverHeight, layerMask))
carBody.AddForceAtPosition(Vector3.up * hoverForce * (1.0f -(hit.distance / hoverHeight)),
hoverPoint.transform.position);
else
{
if(transform.position.y > hoverPoint.transform.position.y)
carBody.AddForceAtPosition(hoverPoint.transform.up * hoverForce, hoverPoint.transform.position);
else
//add force to car
carBody.AddForceAtPosition(hoverPoint.transform.up * -hoverForce, hoverPoint.transform.position);
}
}
// forward
RaycastHit hit2;
if(Physics.Raycast(transform.position, -transform.up, out hit2))
{
if(hit2.distance < 2)
{
if(Mathf.Abs(currThrust) > 0)
{
carBody.AddForce(transform.forward * currThrust);
}
}
}
// turn
if(currTurn > 0)
{
carBody.AddRelativeTorque(Vector3.up * currTurn * turnStrength);
}
else if(currTurn < 0)
{
carBody.AddRelativeTorque(Vector3.up * currTurn * turnStrength);
}
}
}
You need to rethink your game's logic. Raycasts are computationally expensive. You are firing two on the FixedUpdate(). Then you have have a for loop inside that update, which is generally a bad idea.
If you really need to know the distance to the ground fire a raycast on the Update() instead.

How do I jump a fix distance in Unity 3d?

I have a Controller which moves my object diagonally. The left arrow should move the player forward and to the left 45 degrees, and the right arrow the same to the right. I would like to move the player relatively to its current position. Right now it moves relatively to the point(0,0,0).
My code:
public class JollyJumper : MonoBehaviour {
protected CharacterController control;
public float fTime = 1.5f; // Hop time
public float fRange = 5.0f; // Max dist from origin
public float fHopHeight = 2.0f; // Height of hop
private Vector3 v3Dest;
private Vector3 v3Last;
private float fTimer = 0.0f;
private bool moving = false;
private int number= 0;
private Vector2 direction;
public virtual void Start () {
control = GetComponent<CharacterController>();
if(!control){
Debug.LogError("No Character Controller");
enabled=false;
}
}
void Update () {
if (fTimer >= fTime&& moving) {
var playerObject = GameObject.Find("Player");
v3Last = playerObject.transform.position;
Debug.Log(v3Last);
v3Dest = direction *fRange;
//v3Dest = newVector* fRange + v3Last;
v3Dest.z = v3Dest.y;
v3Dest.y = 0.0f;
fTimer = 0.0f;
moving = false;
}
if(Input.GetKeyDown(KeyCode.LeftArrow)){
moving = true;
direction = new Vector2(1.0f, 1.0f);
number++;
}
if(Input.GetKeyDown(KeyCode.RightArrow)){
moving = true;
direction = new Vector2(-1.0f, 1.0f);
number++;
}
if(moving){
Vector3 v3T = Vector3.Lerp (v3Last, v3Dest, fTimer / fTime);
v3T.y = Mathf.Sin (fTimer/fTime * Mathf.PI) * fHopHeight;
control.transform.position = v3T;
fTimer += Time.deltaTime;
}
}
}
How can resolve this? Any ideas? Thanks a lot!
The short answer is: you hard-coded two locations you want to jump to: points (1, 1) and (-1, 1). You should create new Vector each time you start jumping. Replace each
direction = new Vector2(1.0f, 1.0f);
with this line:
v3Dest = transform.position + new Vector3(1.0f, 0, 1) * fRange;
and it should work.
While I'm on it, there are some other things I want to point:
There is a lot of floating point error after each jump. Notice that in your code v3T will never be equal to v3Dest (you never actually reach your destination), because you switch the moving flag earlier. You should explicitly set your position to v3Dest when the jump is over.
You are checking jump timers etc. every frame. A more elegent solution is to start a coroutine.
You use a sinusoid as your jump curve, which looks ok, but using a parabola would be conceptually more correct.
Right now it is possible to start next jump mid-air (I'm not sure whether it is intended or not)
Here is some code you may use that avoids those problems:
using System.Collections;
using UnityEngine;
public class Jumper : MonoBehaviour
{
#region Set in editor;
public float jumpDuration = 0.5f;
public float jumpDistance = 3;
#endregion Set in editor;
private bool jumping = false;
private float jumpStartVelocityY;
private void Start()
{
// For a given distance and jump duration
// there is only one possible movement curve.
// We are executing Y axis movement separately,
// so we need to know a starting velocity.
jumpStartVelocityY = -jumpDuration * Physics.gravity.y / 2;
}
private void Update()
{
if (jumping)
{
return;
}
else if (Input.GetKeyDown(KeyCode.LeftArrow))
{
// Warning: this will actually move jumpDistance forward
// and jumpDistance to the side.
// If you want to move jumpDistance diagonally, use:
// Vector3 forwardAndLeft = (transform.forward - transform.right).normalized * jumpDistance;
Vector3 forwardAndLeft = (transform.forward - transform.right) * jumpDistance;
StartCoroutine(Jump(forwardAndLeft));
}
else if (Input.GetKeyDown(KeyCode.RightArrow))
{
Vector3 forwardAndRight = (transform.forward + transform.right) * jumpDistance;
StartCoroutine(Jump(forwardAndRight));
}
}
private IEnumerator Jump(Vector3 direction)
{
jumping = true;
Vector3 startPoint = transform.position;
Vector3 targetPoint = startPoint + direction;
float time = 0;
float jumpProgress = 0;
float velocityY = jumpStartVelocityY;
float height = startPoint.y;
while (jumping)
{
jumpProgress = time / jumpDuration;
if (jumpProgress > 1)
{
jumping = false;
jumpProgress = 1;
}
Vector3 currentPos = Vector3.Lerp(startPoint, targetPoint, jumpProgress);
currentPos.y = height;
transform.position = currentPos;
//Wait until next frame.
yield return null;
height += velocityY * Time.deltaTime;
velocityY += Time.deltaTime * Physics.gravity.y;
time += Time.deltaTime;
}
transform.position = targetPoint;
yield break;
}
}

Categories