How to store mouse move position value in array? - c#

Here I am trying to Store mouse position value in array so that my ball will move according to that array value.
Is there any better way to do this as I am stuck at the end of the project. Your help will be appreciated.
using UnityEngine;
using System.Collections;
[RequireComponent (typeof(Ball))]
public class BallDragLaunch : MonoBehaviour {
//MyScript
//public float powePerPixel;
public float maxPower;
public float sensitivity;
//private Vector3 touvhPos;
private bool isRolling;
private float rotation = 10f;
//
private Rigidbody rg;
private Vector3 dragStart, dragFlick, dragEnd;
private float startTime, endTime, flickTime;
private Ball ball;
public Rigidbody ballRigid;
public float [] mousePositionX, mousePositionY;
// Use this for initialization
void Start () {
ball = GetComponent<Ball> ();
//MyScript
isRolling = false;
//ballRigid = this.ball;
}
public void MoveStart (float speed) {
if (Input.GetAxis ("Mouse X") > 0) {
if (! ball.inPlay) {
dragStart = Input.mousePosition;
//transform.position = new Vector3(Mathf.Clamp(ball.transform.position.x + speed, ball.transform.position.x - speed, 0), -42.0f, 42.0f);
float xPos = Mathf.Clamp (ball.transform.position.x + speed, -42.0f, 42.0f);
float yPos = ball.transform.position.y;
float zPos = ball.transform.position.z;
ball.transform.position = new Vector3 (xPos, yPos, zPos);
Debug.LogError("Right");
}
}
if (Input.GetAxis ("Mouse X") < 0) {
if (! ball.inPlay) {
dragStart = Input.mousePosition;
//transform.position = new Vector3(Mathf.Clamp(ball.transform.position.x + speed, ball.transform.position.x - speed, 0), -42.0f, 42.0f);
float xPos = Mathf.Clamp (ball.transform.position.x - speed, -42.0f, 42.0f);
float yPos = ball.transform.position.y;
float zPos = ball.transform.position.z;
ball.transform.position = new Vector3 (xPos, yPos, zPos);
Debug.LogError("Left");
}
}
}
public void DragStart () {
if (! ball.inPlay) {
// Capture time & position of drag start
dragStart = Input.mousePosition;
startTime = Time.time;
Debug.LogError("Drag Start");
}
}
public void DragEnd () {
if (Input.GetAxis ("Mouse X") < 0.2f) {
if (! ball.inPlay) {
// Launch the ball
dragEnd = Input.mousePosition;
endTime = Time.time;
float dragDuration = endTime - startTime;
float launchSpeedX = (dragEnd.x - dragStart.x) / dragDuration;
float launchSpeedZ = (dragEnd.y - dragStart.y) / dragDuration;
transform.Rotate (0, rotation, 0);
Vector3 launchVelocity = new Vector3 (launchSpeedX * sensitivity, 0, launchSpeedZ);
ball.Launch (launchVelocity);
Debug.Log ("Drag End Ball Launch");
Debug.LogError("Left Ball Movemet ");
}
}
if (Input.GetAxis ("Mouse X") > 0.2f) {
if (! ball.inPlay) {
// Launch the ball
dragEnd = Input.mousePosition;
endTime = Time.time;
float dragDuration = endTime - startTime;
float launchSpeedX = (dragEnd.x - dragStart.x) / dragDuration;
float launchSpeedZ = (dragEnd.y - dragStart.y) / dragDuration;
transform.Rotate (0, rotation, 0);
Vector3 launchVelocity = new Vector3 (launchSpeedX * sensitivity, 0, launchSpeedZ);
ball.Launch (launchVelocity);
Debug.Log ("Drag End Ball Launch");
Debug.LogError("Right Ball Movemet ");
}
}
if (Input.GetAxis ("Mouse X") >= 0 ) {
if (! ball.inPlay) {
// Launch the ball
dragEnd = Input.mousePosition;
endTime = Time.time;
float dragDuration = endTime - startTime;
float launchSpeedX = (dragEnd.x - dragStart.x) / dragDuration;
float launchSpeedZ = (dragEnd.y - dragStart.y) / dragDuration;
transform.Rotate (0, rotation, 0);
Vector3 launchVelocity = new Vector3 (launchSpeedX * sensitivity, 0, launchSpeedZ);
ball.Launch (launchVelocity);
//Debug.Log ("Drag End Ball Launch");
Debug.LogError("Mid Ball Right Move");
}
}
}
}

in response to Lajos Arpad answer
I have to say use lists instead of arrays. They are so much better to work with, and you dont need to know how many variables will go into the list before hand.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[RequireComponent (typeof(Ball))]
public class BallDragLaunch : MonoBehaviour {
//MyScript
public List<Vector3> mousPositions;
in your code you can treat the list exactly the same way you would treat an array. To add mouse positions to the list simply write
mousePosition.Add(Input.mousePosition);

Your ball is moving in three dimensions and you use Vector3 for them. On the other hand, you have two arrays of float[] called mousePositionX and mousePositionY, respectively. You could use a Vector3[] for that purpose. This is how you declare it:
public Vector3[] mousePositions;
If you know its size, which, for instance is n, then this is how you initialize it:
mousePositions = new Vector3[n];
and if you want to set its i'th value, then this is how you can do it:
mousePositions[i] = ball.transform.position;
Problems you need to solve:
- you need to know the size of the array before you initialize it
- you need to keep track of the first index where you have not put a valid position yet
I believe you will not know the size of the array in advance and you also do not want to always keep track of indexes. So I would use a Queue if I were you. Don't worry, it is not difficult. Try to work with the array solution first to have some success and when you see it works, create a backup of your code and try experimenting with a Queue<Vector3>. Believe me, it is worth it.

Related

How to jump to a point using CharacterController?

I have a script to jump, but it jumps depending on the value of the JumpFactor constant. I would like the jump to happen using the JumpToPositionX (float target) method. I think I need to somehow calculate the JumpFactor depending on the value of the target in the JumpToPositionX method. I found an article on Wikipedia, but I don't even know where to start. I have not found examples of how to do this with the CharacterController.
public class ExampleClass : MonoBehaviour
{
const float Speed = 6f;
const float JumpFactor = 14f;
const float Gravity = 20f;
private Vector3 moveDirection = Vector3.zero;
CharacterController controller;
void Start()
{
controller = GetComponent<CharacterController>();
}
void Update()
{
if (controller.isGrounded)
{
moveDirection = new Vector3(1f, 0f, 0f); // Move X Direction
moveDirection *= Speed;
if (Input.GetButton("Jump"))
moveDirection.y = JumpFactor;
}
moveDirection.y -= Gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
// Method for jump, calling from other script.
void JumpToPositionX(float target)
{
}
}
Theory
I assume you want to use the ballistic physic.
Let's see what formula we can use
Where :
V : Velocity
a : Acceleration
P : Position
t : time since start
0 : Initial
is known it's (0f,-9.81f) or (0f, Gravity) in your case.
is known too, it's your initial position before the jump.
is the end target position.
Resolution
You have to find the end time and the initial Velocity . So here's the position equation:
We can simplify the process by looking only for the x axis because there's no acceleration.
is simplified to :
Let's isolate the from the x position formula :
Now you have the total time of the jump .
You just need to find the initial y velocity by using the y position formula :
Isolate the Vyo :
So now you have all informations for computing the jump : Initial and end position, Total time, Initial velocity and acceleration.
Implementation
Here's an example of the MonoBehaviour you can create :
public class JumpBehaviour : MonoBehaviour
{
public CharacterController CharacterController;
public Transform TargetPosition;
private bool jumpStarted = false;
private float totalTime = 0f;
private float t = 0f;
private Vector2 V0;
private Vector2 initialPosition;
private bool jumpKeyDown;
private const float xSpeed = 6f;
private const float gravity = -9.81f;
void Update()
{
jumpKeyDown = Input.GetKeyDown(KeyCode.Space);
}
void FixedUpdate()
{
if (jumpStarted)
{
UpdateJumpPosition(Time.fixedDeltaTime);
}
else if (jumpKeyDown )
{
StartJump();
}
}
private void UpdateJumpPosition(float deltaTime)
{
t += deltaTime;
if(t > totalTime)
{
//End of jump
transform.position = TargetPosition.position;
jumpStarted = false;
return;
}
Vector2 newPosition = new Vector2(0f, gravity) * t * t + V0 * t + initialPosition;
CharacterController.Move(newPosition);
}
private void StartJump()
{
jumpStarted = true;
initialPosition = transform.position;
// Absolute because xSpeed could be positive or negative. We dont want negative time
float delta = TargetPosition.position.x - transform.position.x;
totalTime = Mathf.Abs(delta / xSpeed);
t = 0f;
float yInitialSpeed = (TargetPosition.position.y - transform.position.y - gravity * totalTime * totalTime) / totalTime;
// Using Sign to set the direction of horizontal movement
V0 = new Vector2(xSpeed * Mathf.Sign(delta), yInitialSpeed);
}
}
And this is the result
Conclusion
This is just an quick example to figure out how to compute the initial value of the jump and movement in 2D.
As derHugo said on comment you should not use transform.position direct attribution with Physic.
For 3D it's the same idea but you should compute the speed x,z from target direction and speed magnitude.
Vector3 delta = TargetPosition - transform.position;
delta.y = 0f;
float direction = delta.normalized;
Vector3 initialSpeed = direction * movementSpeed;

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...

Seperate Camera and Player Movement in Unity

I'm currently trying to script a camera that has the player in focus and can move around unlinked to the players own movement.
You can control the camera with the right xBox controller.
The camera should move normally on the X axis in an orbit around the player, but if you move the camera to look up or down (let's say 20° up) it should be on 0° to focus the player again if u let off the joystick and interpolate between those two angles.
In my script the camera is able to look up and down (but the degree isn't locked yet so you could move it on the Y axis 360°+) but it resets to 0°. Additionally the x axis doesn't behave as I want it to since it is able to rotate around the player but only 180° and then it stops and if u let the controller go it also sets it's values back (which I don't want for the x axis).
The camera is a child object of an empty game object. The script is attached to the empty game object.
I'm trying to figure this out since ~3 days and I'd be really grateful for any small advice.
Thanks in advance & here's my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollowPlayer : MonoBehaviour
{
public GameObject target;
public GameObject cameraRig;
public float rotateSpeedX = 90.0f;
public float rotateSpeedY = 5f;
float cameraAngle;
float startCameraAngle;
Vector3 offset;
Vector3 currentOffset;
public float minRotationY;
public float maxRotationY;
bool isCameraMoving;
void Start()
{
offset = transform.position - target.transform.position;
cameraAngle = transform.localEulerAngles.z;
startCameraAngle = cameraAngle;
currentOffset = offset;
}
void Update()
{
transform.position = target.transform.position + currentOffset; // Folgt dem Spieler
float hor = Input.GetAxis("RightJoystickX") * rotateSpeedX; // Input rechter Joystick
float ver = Input.GetAxis("RightJoystickY") * rotateSpeedY;
if (!Mathf.Approximately (hor, 0)) {
transform.RotateAround (target.transform.position, Vector3.up, hor);
currentOffset = transform.position - target.transform.position;
}
if (!Mathf.Approximately (ver, 0)) {
cameraAngle += 110f * Time.deltaTime;
transform.RotateAround (target.transform.position, Vector3.up, hor);
currentOffset = transform.position - target.transform.position;
print(ver);
}
else if (ver <= 0.8f) {
//cameraAngle = Mathf.Lerp(cameraAngle, startCameraAngle, 1f - 0.1f * Time.deltaTime);
cameraAngle = startCameraAngle;
}
transform.localEulerAngles = new Vector3(0, hor, cameraAngle);
}
}
If sb else googled this and found my question this worked for me:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollowPlayer : MonoBehaviour
{
public GameObject target;
public GameObject cameraRig;
public float rotateSpeedX = 9.0f;
public float rotateSpeedY = 5f;
float cameraAngle;
float startCameraAngle;
Vector3 offset;
Vector3 currentOffset;
bool isCameraMoving;
void Start()
{
offset = transform.position - target.transform.position;
cameraAngle = transform.localEulerAngles.z;
startCameraAngle = cameraAngle;
currentOffset = offset;
}
void Update()
{
transform.position = target.transform.position + currentOffset; // Folgt dem Spieler
float hor = Input.GetAxisRaw("RightJoystickX") * rotateSpeedX; // Input rechter Joystick GetAxis wenn Bewegung ausschwingen soll
float ver = Input.GetAxisRaw("RightJoystickY") * rotateSpeedY; // GetAxis wenn Bewegung ausschwingen soll
if (!Mathf.Approximately (hor, 0)) {
transform.RotateAround (target.transform.position, Vector3.up, hor);
currentOffset = transform.position - target.transform.position;
}
if (ver != 0) {
//cameraAngle += 110f * Time.deltaTime;
if (ver > 0)
{
cameraAngle += 110f * Time.deltaTime;
if (cameraAngle >= 420f)
{
cameraAngle = 420f;
}
}
if (ver < 0)
{
cameraAngle -= 110f * Time.deltaTime;
if (cameraAngle <= 290f)
{
cameraAngle = 290f;
}
}
transform.RotateAround (target.transform.position, Vector3.up, hor);
currentOffset = transform.position - target.transform.position;
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y, cameraAngle);
}
else
{
cameraAngle = Mathf.Lerp(startCameraAngle, cameraAngle, 1f - 0.9f * Time.deltaTime);
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y, cameraAngle);
}

Rotating avatar at certain x coordinate Unity

I have a problem with turning my avatar at a certain position on the map. The character moves back and forth, but he doesn't want to rotate at coordinates i entered. What am i doing wrong?
this is my code:
sing System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AvatarPingPong : MonoBehaviour {
// Use this for initialization
public float speed;
public float startXCord, endXCord;
float endTrunx, startTurnx;
public GameObject obj;
Vector3 EndPoint, StartPoint;
void Start () {
EndPoint = transform.position;
endXCord = EndPoint.x;
endTrunx = EndPoint.x - 2f;
StartPoint = transform.position;
StartPoint.x = startXCord;
startTurnx = StartPoint.x + 2f;
}
// Update is called once per frame
void Update () {
transform.position = new Vector3(PingPong (Time.time * speed, startXCord, endXCord ), transform.position.y, transform.position.z);
if (transform.position.x == startTurnx ) {
Debug.Log("start Check");
obj.transform.Rotate(0f, 180f, 0f);
}
if (transform.position.x == endTrunx ) {
obj.transform.Rotate(0f, 180f, 0f);
Debug.Log("einde check");
}
}
//function to change the default starting value of (0, 0, 0) to any value
float PingPong(float t, float minLength, float maxLength) {
return Mathf.PingPong(t, maxLength-minLength) + minLength;
}
}
I believe the problem is that you're trying to flip your avatar once he reaches a particular x-coordinate, but he may never reach that EXACT coordinate. if (transform.position.x == startTurnx) will only return true if the two values are EXACTLY the same, and your avatar isn't actually moving smoothly across the screen. He's actually jumping minute amounts every frame, so he may never land on exactly that point.
Instead, my recommendation would be to compare his new position against his old position to see which direction he's traveling in and flip him when he changes direction. Some code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AvatarPingPong : MonoBehaviour {
// Use this for initialization
public float speed;
public float startXCord, endXCord;
float endTrunx, startTurnx;
public GameObject obj;
Vector3 EndPoint, StartPoint;
//I'm going to assume you start it moving left. You may have to change this
bool goingLeft = false;
void Start () {
EndPoint = transform.position;
endXCord = EndPoint.x;
endTrunx = EndPoint.x - 2f;
StartPoint = transform.position;
StartPoint.x = startXCord;
startTurnx = StartPoint.x + 2f;
}
// Update is called once per frame
void Update () {
float prevX = transform.position.x;
float newX = PingPong (Time.time * speed, startXCord, endXCord );
transform.position = new Vector3(newX, transform.position.y, transform.position.z);
if (newX > prevX) {
//avatar is moving to the right, check to see if that's the direction it was going last Update
if (goingLeft) {
Debug.Log("Flipping Right");
obj.transform.Rotate(0f, 180f, 0f);
goingLeft = false;
}
}else if (newX < prevX){
//avatar is moving to the left, check to see it that's the direction it was going last Update
if (!goingLeft) {
Debug.Log("Flipping Left");
obj.transform.Rotate(0f, 180f, 0f);
goingLeft = true;
}
}
}
//function to change the default starting value of (0, 0, 0) to any value
float PingPong(float t, float minLength, float maxLength) {
return Mathf.PingPong(t, maxLength-minLength) + minLength;
}
}

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