기타/일상

제비뽑기, 방추첨 어플 만들기 #2 (다듬기, 시각적인 기능구현)

DOlpa_ 2026. 1. 6. 05:29
728x90

이번엔 지난 글에 이어 시각적인 기능구현을 하나 추가하고 이쁘게 다듬어보겠다

 

 

저번과 달리 이번에는 로또 공  추첨하는 효과를 주고 싶어 방식을 바꾸기로 했다

 

13개의 공을 만들었다

 

using UnityEngine;

public class BallController : MonoBehaviour
{
    [Header("Movement Settings")]
    [SerializeField] private float initialForce = 5f;  // 초기 힘
    [SerializeField] private float minForce = 1f;     // 최소 힘
    [SerializeField] private float deceleration = 0.1f; // 감속 정도
    [SerializeField] private float minVelocity = 0.1f; // 정지로 판단할 최소 속도
    
    private Rigidbody2D rb;
    private Vector2 currentDirection;
    private float currentForce;
    private bool isMoving = true;

    void Start()
    {
        // Rigidbody2D 컴포넌트 가져오기 또는 추가
        rb = GetComponent<Rigidbody2D>();
        if (rb == null)
        {
            rb = gameObject.AddComponent<Rigidbody2D>();
        }
        
        // 물리 재질 설정 (탄성, 마찰 등)
        rb.sharedMaterial = new PhysicsMaterial2D()
        {
            bounciness = 0.8f,  // 탄성 계수 (0~1)
            friction = 0.2f     // 마찰 계수
        };
        
        // 중력 비활성화 (2D 게임에서 중력이 필요없다면)
        rb.gravityScale = 0f;
        
        // 공이 회전하지 않도록 설정
        rb.freezeRotation = true;
        
        // 초기 힘 설정
        ApplyRandomForce();
    }

    void FixedUpdate()
    {
        if (!isMoving) return;
        
        // 현재 속도 감소
        currentForce = Mathf.Max(currentForce - deceleration * Time.fixedDeltaTime, 0f);
        
        // 힘 적용
        rb.velocity = currentDirection * currentForce;
        
        // 일정 속도 이하로 떨어지면 정지
        if (rb.velocity.magnitude < minVelocity)
        {
            rb.velocity = Vector2.zero;
            isMoving = false;
        }
    }
    
    void OnCollisionEnter2D(Collision2D collision)
    {
        if (!isMoving) return;
        
        // 충돌 시 반사 방향 계산 (정규화된 반사 벡터)
        Vector2 normal = collision.contacts[0].normal;
        currentDirection = Vector2.Reflect(currentDirection, normal).normalized;
        
        // 약간의 무작위성 추가 (0.9 ~ 1.1 사이의 랜덤값)
        float randomFactor = Random.Range(0.9f, 1.1f);
        currentDirection *= randomFactor;
        currentDirection.Normalize();
    }
    
    private void ApplyRandomForce()
    {
        // 랜덤한 방향 벡터 생성
        float angle = Random.Range(0f, 360f) * Mathf.Deg2Rad;
        currentDirection = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)).normalized;
        
        // 랜덤한 힘 설정 (최소 힘 이상)
        currentForce = Random.Range(minForce, initialForce);
        
        // 초기 힘 적용
        rb.velocity = currentDirection * currentForce;
        isMoving = true;
    }
    
    // 외부에서 공을 다시 움직이게 할 때 사용할 수 있는 메서드
    public void ResetBall()
    {
        ApplyRandomForce();
    }
}

 

그리고 아주 간단하게 공이 생성되자마자 랜덤한 방향으로 움직이고

서서히 느려지는 시스템이다

 

동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.

 

 

이제부터는 정지된 이미지가 아니라 공이 실시간으로 생성되어 랜덤하게 이동한다

이게 훨 나은것 같다

 

이제 대략 기능구현도 다 끝났으니 시각적으로 이쁘게 다듬어보도록 하자

 

----------------------------------------

 

 

 

 

이대로 색만 바꾸기에는 아쉬우니 한가지 기능을 더 추가해주었다

 

 

동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.

 

짠! 위에서 제비뽑기에 쓰이던 공들을 가져와 재사용해주었다

 

 

 

 

그 외에도 너무 칙칙한 느낌만 안들도록 바꿔주었다

어차피 기능이 중요한건데 너무 공들이진 않았다. 그럼 진짜 밤샐까봐....

 

 

공의 움직임도 Update 말고 DOTween을 사용하여 최적화해주었다

 

프레임도 60프레임 고정시키고, 제비뽑기! 버튼 누를때마다 효과음도 추가해주었다

유니티 설정도 전부 최적화 설정 마쳤고 

 

 

바로 테스트 출시까지 해버리기!

 

이제 자야겠다

 

 

 

동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.

 

최종 완성본

728x90
반응형