티스토리 뷰

즉 화면을 좌우로 스크롤하면 오브젝트가 그에 따라서 회전하게 하는 것을 구현하려고 합니다.

대충 어떻게든 되게 하는 것은 쉽지만 이것을 좀 맛있게 하게 하는 데에 시행착오를 겪어서 글을 적어봅니다.

 

즉 이 움짤처럼 하고 싶은 거임.

단순히 드래그에 따라서 움직이게 하는 것이라면 스크롤이라는 편안한 컴포넌트가 있지만 회전은 결국 다시 만들어야 하더군요. 저는 패널에 이벤트시스템 인터페이스를 붙여서 구현하는 중입니다.

 

일단 패널을 만드려면 Image 컴포넌트가 필요하기 때문에 Image가 존재하는 패널에 붙여서 써주세요.

 

존재해야하는 기능 리스트

  • Threshold : 충분히 움직이지 않으면 드래그를 시작하지 않는다. 작은 터치로도 움직이게 하는 것 방지.
  • 드래그를 움직이면서 끝내면 그 속도에 탄력적으로 반응 한다. 드래그가 끝난 후의 움직임! 단, 다시 터치하면 멈춰야한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

[RequireComponent(typeof(UnityEngine.UI.Image))]
public class TestRotation : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler, IPointerDownHandler, IPointerUpHandler
{

    [SerializeField]
    Transform worldTrans;

    Vector2 touchPositionInFirst;

    [SerializeField] float maximumVelocity = 50;
    [SerializeField] float rotationSpeed = 7;
    [SerializeField] float touchSensitivity = 0.3f;
    [SerializeField] float movingThreshold = 10;
    [SerializeField] float decelerationVelocity = 3;
    [SerializeField] float stopVelocity = 0.5f;
    [SerializeField] float stopSensitivity = 0.2f;
    [SerializeField] float noMovingCheckTime = 0.2f;
    [SerializeField] float stopSignalWatingTime = 0.1f;
    [SerializeField] float returningSpeed = 1;

    private float _velocity;
    private float _fNowRotationZ;
    private bool _bIsMoved;
    private bool _bIsTouchPressed;


    public void OnBeginDrag(PointerEventData eventData)
    {
        _bIsMoved = false;
        touchPositionInFirst = eventData.position;
    }
    public void OnDrag(PointerEventData eventData)
    {
        float movingValue = eventData.delta.x;
        if (!_bIsMoved && _velocity == 0) 
        {
            if (Mathf.Abs(touchPositionInFirst.x - eventData.position.x) > movingThreshold)
            {
                _bIsMoved = true;
            }
            else
            {
                return;
            }
        }

        SetVelocity(-(movingValue * touchSensitivity));
        RotateWorld();
    }
    public void OnEndDrag(PointerEventData eventData)
    {
        this.SetVelocity(-(eventData.delta.x * touchSensitivity));
    }
    
    private void SetVelocity(float xValue)
    {
        this._velocity = Mathf.Clamp(xValue, -maximumVelocity, maximumVelocity);
    }
    private void RotateWorld()
    {
        _fNowRotationZ += _velocity * rotationSpeed * Time.deltaTime;
        worldTrans.localRotation = Quaternion.Euler(0, 0, _fNowRotationZ);
    }

    void Update()
    {
        UpdateRotation();
    }
    private void UpdateRotation()
    {
        if (!_bIsTouchPressed)
        {
            if (_fNowRotationZ < 0)
            {
                _velocity = -_fNowRotationZ * returningSpeed;
            }
        }
        else
        {
            return;
        }

        if (_velocity == 0)
        {
            return;
        }
        else if (Mathf.Abs(_velocity) < stopVelocity)
        {
            this._velocity = 0;
        }
        else
        {
            SetVelocity(Mathf.LerpAngle(_velocity, 0, decelerationVelocity * Time.deltaTime));
            RotateWorld();
        }
    }
    public void OnPointerDown(PointerEventData eventData)
    {
        _bIsTouchPressed = true;
        _velocity = 0;
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        _bIsTouchPressed = false;
    }

}

일단은 잘된다. 나중에 수정사항 있으면 업데이트 하겠음.

댓글
최근에 올라온 글
Total
Today
Yesterday
TAG
more
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31