I have a scene that contains a square sprite in the middle at 0,0,0 position as player and two more square sprites on top and bottom of it with some space between all.
I want the player start to move when I press the up arrow ker or the down arrow key. When the player hits one of those squares on top or the bottom the player must return back to it's first position.
{
Rigidbody2D playerRb;
float axisY = 0f;
bool canMove = true;
public float playerSpeed = 0f;
public float returnSpeed = 0f;
public float speed = 1f;
void Start()
{
playerRb = GetComponent<Rigidbody2D>();
}
//decides to which axis player gonna move to
private void Update()
{
if (Input.anyKey)
{
axisY = Input.GetAxisRaw("Vertical");
}
}
private void FixedUpdate()
{
PlayerMovement(axisY, playerSpeed);
}
//give velocity to player depending on axis
void PlayerMovement(float axis, float speed)
{
switch (axisY)
{
case 1:
if (canMove)
{
canMove = false;
playerRb.velocity = new Vector2(0, axis * speed);
}
break;
case -1:
if (canMove)
{
canMove = false;
playerRb.velocity = new Vector2(0, axis * speed);
}
break;
default:
//do nothing
break;
}
}
//return back after hit
private void OnCollisionEnter2D(Collision2D collision)
{
axisY = 0;
playerRb.velocity = Vector2.zero;
//the code below is my way to get back before i decide to lerp
//playerRb.MovePosition(Vector2.MoveTowards(playerRb.position,Vector2.zero,returnSpeed));
StopAllCoroutines();
StartCoroutine(BackToZero());
}
IEnumerator BackToZero()
{
float t = 0;
while (t < 1)
{
t = Time.deltaTime;
playerRb.MovePosition(Vector2.Lerp(playerRb.position, Vector2.zero, returnSpeed));
yield return null;
}
canMove = true;
}
}
I managed to achieve this with my code but the problem is when the lerp gets closer to 0 it is taking more time to reach there. I have to wait for one second to reach to the position and my canMove bool value gets back to true.
How can I skip this and when my object position is close to 0 point snap it to there?
CodePudding user response:
The problem come from the fact you use playerRb.position
as the start position of your Lerp in your coroutine.
To fix this, I recommend you to buffer the playerRb.position
in a member variable at the OnCollisionEnter()
method right before starting your coroutine and use this buffered position in your Lerp as start position.
This way you should have a nice linear movement at a sweet linear speed without the "damping"
Hope that helped ;)
CodePudding user response:
Here is the solution. When player object's position is too close to the starting position you will detect it then snap it to the position immediately by
playerRb.MovePosition()
.
Then enable player to move right after by setting canMove
bool to true.
private void OnCollisionEnter2D(Collision2D collision)
{
axisY = 0;
playerRb.velocity = Vector2.zero;
Vector2 playerCurrentPosition = playerRb.position;
//playerRb.MovePosition(Vector2.MoveTowards(playerRb.position,Vector2.zero,returnSpeed));
StopAllCoroutines();
StartCoroutine(BackToZero(playerCurrentPosition));
}
IEnumerator BackToZero(Vector2 playerStartPos)
{
float t = 0;
while (t < 1)
{
t = Time.deltaTime;
if (Mathf.Round(Mathf.Abs(playerRb.position.y*2))==0)
{
playerRb.MovePosition(Vector2.zero);
canMove = true;
StopAllCoroutines();
}
else
playerRb.MovePosition(Vector2.Lerp(playerRb.position, Vector2.zero, returnSpeed));
yield return null;
}
canMove = true;
}
}