본문 바로가기

유니티

[Unity] Rigidbody 날아가는 궤적 그리기

앵그리버드 게임을 보면 어디로 날라갈지 미리 궤적을 보여줍니다.

이런건 어떻게 만드는지 궁금해서 영상 참고해서 만들어봤습니다!

참고한 유튜브링크는 글 아래에 적어뒀습니다.


 

 

원리를 간단하게 설명하자면
등가속운동 공식을 사용하여 시간에 따른 위치값을 미리 계산하는 것입니다!

 

스크립트는 3개로 만들어봤습니다

GameManager : force 계산해서 넣어주는애

BallController : force 받아서 날아가는 애

TrajectoryDrawer : force 받아서 궤적 그려주는 애

using UnityEngine;

public class GameManager : MonoBehaviour
{
    public BallController Ball;
    public TrajectoryDrawer Drawer;

    public float MaxDistance;
    public float ForcePower;

    private Vector2 _startPos;
    private Vector2 _endPos;
    private Vector2 _force;


    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Drawer.SetActiveTrajectory(true);
            _startPos = Ball.transform.position;
        }

        if (Input.GetMouseButton(0))
        {
            _endPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);

            var sub = _startPos - _endPos;
            if (sub.magnitude > MaxDistance)
            {
                sub = sub.normalized * MaxDistance;
                _endPos = _startPos - sub;
            }

            _force = sub * ForcePower;
            Ball.SetPosition(_endPos);
            Drawer.DrawDots(_endPos, _force);
        }

        if (Input.GetMouseButtonUp(0))
        {
            Ball.AddForce(_force);
            Drawer.SetActiveTrajectory(false);
        }

        if (Input.GetKeyDown(KeyCode.Space))
        {
            Ball.ResetPos();
        }
    }
}

 

using UnityEngine;

public class BallController : MonoBehaviour
{
    private Rigidbody2D _rigid;

    void Awake()
    {
        _rigid = GetComponent<Rigidbody2D>();
        _rigid.isKinematic = true;
    }
    
    public void SetPosition(Vector2 pos)
    {
        transform.position = pos;
    }

    public void AddForce(Vector2 force)
    {
        _rigid.isKinematic = false;
        _rigid.AddForce(force, ForceMode2D.Impulse);
    }

    public void ResetPos()
    {
        _rigid.isKinematic = true;
        _rigid.velocity = Vector2.zero;
        transform.position = Vector2.zero;
    }
}

 

using System.Collections.Generic;
using UnityEngine;

public class TrajectoryDrawer : MonoBehaviour
{
    public GameObject DotPrefab;
    public float TimeScale;
    public int DotCount;

    private List<GameObject> _dots;

    private void Awake()
    {
        _dots = new List<GameObject>(DotCount);
        for(int i = 0; i < DotCount; i++)
        {
            _dots.Add(Instantiate(DotPrefab, transform));
            _dots[i].SetActive(false);
        }
    }

    public void DrawDots(Vector2 startPos, Vector2 force)
    {
        for(int i = 0; i < _dots.Count; i++)
        {
            _dots[i].transform.position = GetDotPosition(i);
        }

        Vector2 GetDotPosition(int index)
        {
            float time = index * TimeScale;
            return startPos + force * time + 0.5f * Physics2D.gravity * time * time;
        }
    }

    public void SetActiveTrajectory(bool isActive)
    {
        foreach(var dot in _dots)
        {
            dot.SetActive(isActive);
        }
    }
}

 

 

참고자료

https://www.youtube.com/watch?v=9n4nEP8yD0U