I have a player, which can turn into a ball (Metroid-clone)
I have a tile map, inside a grid (Layer is ground).
I also have an empty game object named boundaries (That represent the boundaries of the camera) and obviously the layer for this is “No collision”
I went to my project setting and turn off all the interaction with that layer
void Update() {
#region Check if the player is grounded
_isGrounded = Physics2D.OverlapCircle(_groundPoint.position, 0.3f, _whatIsGround);
#endregion
#region Handle dashing and Movement
if (Input.GetKeyDown(KeyCode.Z) && _canDash && _playrSprites[0].activeSelf) {
StartCoroutine(DashCoroutine(0.5f));
} else {
float horizontalInput = Input.GetAxisRaw("Horizontal");
_rb2D.velocity = new Vector2(horizontalInput * _moveSpeed, _rb2D.velocity.y);
SetLocalScale();
}
#endregion
#region Handle jumping
if (Input.GetKeyDown(KeyCode.X) && (_isGrounded || _canDoubleJump)) {
if (_isGrounded) {
_canDoubleJump = true;
} else {
_canDoubleJump = false;
_animator.SetTrigger("isDoubleJumping");
}
_rb2D.velocity = new Vector2(_rb2D.velocity.x, _jumpForce);
} else if (Input.GetKeyUp(KeyCode.X) && _rb2D.velocity.y > 0) {
_rb2D.velocity = new Vector2(_rb2D.velocity.x, _jumpForce * 0.5f);
}
#endregion
#region Handle shooting
if (Input.GetKeyDown(KeyCode.C) && !_isBall) {
Instantiate(_bullets, _shotPoint.position, Quaternion.identity).ChangeDirr(transform.localScale.x);
_animator.SetTrigger("fireShot");
}
#endregion
#region Ball mode
if (Input.GetKeyDown(KeyCode.X)) {
if (!_isBall) {
StartCoroutine(TurnOnBallCoroutine(1.5f));
}
}
if (Input.GetKeyUp(KeyCode.X)) {
RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.up, raycastDistance);
Debug.DrawRay(transform.position, Vector2.up * raycastDistance, rayColor);
Debug.Log(hit.collider.name);
if (hit.collider == null) { // Raycast did not hit anything, allow turning off ball mode
Debug.Log("turning off ball mode");
TurnOffBall();
}
}
#endregion
// Update the animator variables
_animator.SetFloat("isRunning", Mathf.Abs(_rb2D.velocity.x));
_animator.SetBool("isGrounded", _isGrounded);
}
IEnumerator DashCoroutine(float dashDuration) {
float timer = 0f;
while (timer < dashDuration) {
_canDash = false;
_isDashing = true;
_rb2D.velocity = new Vector2(_dashSpeed * transform.localScale.x, _rb2D.velocity.y);
timer += Time.deltaTime;
ShowAfterImage();
yield return null;
}
_canDash = true;
_isDashing = false;
}
IEnumerator TurnOnBallCoroutine(float time) {
_isBall = true;
yield return new WaitForSeconds(time);
Debug.Log("ball");
TurnOnBall();
}
private void SetLocalScale() {
if (Input.GetAxisRaw("Horizontal") > 0) {
transform.localScale = new Vector3(1, 1, 1);
} else if (Input.GetAxisRaw("Horizontal") < 0) {
transform.localScale = new Vector3(-1, 1, 1);
}
}
private void ShowAfterImage() {
if (Time.time >= _nextAfterImageSpawnTime) {
SpriteRenderer _spriteRenderer = Instantiate(_afterImageSpriteRender,
transform.position,
transform.rotation);
_spriteRenderer.sprite = _mySpriteRenderer.sprite;
_spriteRenderer.transform.localScale = transform.localScale;
_spriteRenderer.color = _afterImageColor;
Destroy(_spriteRenderer.gameObject, _afterImageLifeTime);
_nextAfterImageSpawnTime = Time.time + _afterImageSpacing;
}
}
private void TurnOnBall() {
Debug.Log("Turned Ball");
_isBall = true;
_playrSprites[1].SetActive(true);
_playrSprites[0].SetActive(false);
}
private void TurnOffBall() {
Debug.Log("Turn off ball");
_isBall = false;
_playrSprites[1].SetActive(false);
_playrSprites[0].SetActive(true);
}
So, I have my ball, to be a child of my player, and by default is not active, and if I hold the X key, I run a coroutine, that turns my ball on, and I added a raycast, to see if I have something above me, if this is the case I don’t turn of the ball
But I have some problems with this
- if I jump, when I hit the floor, I change into a ball
- I can’t turn back’
If I print what the rayast hit, it was the “Camera boundaries” and of course I is not null
’
[1]: /storage/temp/205319-screenshot-2023-03-05-055207.png
[2]: /storage/temp/205320-screenshot-2023-03-05-055219.png


