평평하지 않게
Coddy의 Unity 게임: 벽돌 깨기 코스 레슨. 19개 중 10번째.
벽돌 모서리에 맞고 튕긴 공은 거의 수평으로 움직일 수 있어, 플레이어가 기다리는 동안 경기장을 계속 오갈 수 있습니다. 속도 보정에서 해결하면 됩니다. 방향의 y 성분이 너무 작으면 최솟값으로 설정한 뒤 다시 정규화하세요.
Mathf.Abs는 부호를 제외한 숫자의 크기를 반환하므로, 위로 가는 공과 아래로 가는 공을 모두 한 번의 검사로 처리할 수 있습니다. Mathf.Sign은 음수이면 -1을, 그렇지 않으면 1을 반환하므로, 아래로 가는 공은 계속 아래로 갑니다.
Debug.Log(Mathf.Abs(-0.12f)); // 0.12
Debug.Log(Mathf.Sign(-0.12f)); // -1최솟값이 0.4라면 방향 (0.99, -0.12, 0)의 y는 -0.4가 되고, 정규화하면 약 (0.93, -0.37, 0)이 됩니다. 여전히 오른쪽 아래로 향하지만, 이제 충분히 가파른 각도로 돌아옵니다. 이보다 가파른 방향은 그대로 둡니다.
챌린지
중급공이 경기장을 거의 수평으로 가로지르지 않게 하세요.
Ball에public float minVertical = 0.3f;를 추가하세요.- FixedUpdate에서
Vector3 direction = rb.linearVelocity.normalized;를 가져오세요.Mathf.Abs(direction.y) < minVertical이면direction.y = Mathf.Sign(direction.y) * minVertical;로 설정한 다음 다시 정규화하세요. rb.linearVelocity = direction * speed;로 설정하세요.
‘플레이’를 누르세요. 공이 오랫동안 거의 수평으로 경기장을 가로지르지 않습니다. 그런 다음 ‘확인’을 누르세요.
직접 해보기
using UnityEngine;
using UnityEngine.InputSystem;
public class Ball : MonoBehaviour
{
public Transform paddle;
public float speed = 9f;
Rigidbody rb;
bool launched;
void Awake()
{
rb = GetComponent<Rigidbody>();
PhysicsMaterial bouncy = new PhysicsMaterial("Bouncy");
bouncy.bounciness = 1f;
bouncy.dynamicFriction = 0f;
bouncy.staticFriction = 0f;
bouncy.bounceCombine = PhysicsMaterialCombine.Maximum;
bouncy.frictionCombine = PhysicsMaterialCombine.Minimum;
GetComponent<Collider>().material = bouncy;
}
void Update()
{
if (launched) return;
transform.position = paddle.position + Vector3.up * 0.5f;
if (Keyboard.current.spaceKey.wasPressedThisFrame) Launch(new Vector3(0.3f, 1f, 0f));
}
public void Launch(Vector3 direction)
{
launched = true;
rb.linearVelocity = direction.normalized * speed;
}
public void ResetToPaddle()
{
launched = false;
rb.linearVelocity = Vector3.zero;
}
void FixedUpdate()
{
if (!launched) return;
rb.linearVelocity = rb.linearVelocity.normalized * speed;
}
void OnCollisionEnter(Collision collision)
{
if (!collision.gameObject.CompareTag("Paddle")) return;
float offset = transform.position.x - collision.transform.position.x;
float halfWidth = collision.collider.bounds.size.x / 2f;
float x = Mathf.Clamp(offset / halfWidth, -1f, 1f);
rb.linearVelocity = new Vector3(x, 1f, 0f).normalized * speed;
}
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("DeathZone")) GameManager.Instance.BallLost(this);
}
}
Unity 게임: 벽돌 깨기의 모든 레슨
직접 연습해 보세요: Unity 플레이그라운드