Game Development, 게임개발/개발

투사체 경로 흔적 남기기, ProjectileTrail [ Unity]

게임이 더 좋아 2021. 4. 11. 23:02
반응형
728x170

 

투사체에 Effect를 주거나 흔적을 남기고 싶을 때가 있다.

 

아니면 앵그리버드처럼 궤적을 남기거나 무슨 일을 하고싶을 때가 있다.

 

알아보자

 


 

우선 유니티에는 Trail Renderer라는 것이 내장되어있다.

그래서 단순히 이 렌더러를 붙여서 약간을 조작하는 것만으로도 Trail을 그릴 수 있다.

스크립트 없이도 단순히 해당 투사체에 렌더러를 붙여 조작하는 것만으로도 충분히 좋은 효과를 만들 수 있다.

 

 

뭐 이런 식으로 만들 수 있다.

이렇게 많은 Property들이 있어 가능하다.

 

 

모든 것을 살펴볼 필요는 없고

 

 

주요 기능을 보자면

Time: Trail을 몇 초 동안이나 유지할 것이냐?

-> 값이 커지면 Trail이 Scene에 더 오래 남아있음

 

Width: Trail의 시간에 따른 넓이를 어떻게 할 것이냐??

-> 많은 경우에 0으로 삭제하는 경우가 많음.(서서히 사라지는 것 같은 효과)

 

Min Vertex Distance: point간의 넓이 즉, Trail을 어느 구간마다 찍을 것이냐?

-> 직선을 촘촘하게 이어서 곡선으로 보이게하는 기법이다.

Distance가 높아지면 직선이 보이기 시작한다.

 

 

 

AutoDestruct: 일정 시간동안 움직이지 않으면 Trail Renderer를 가진 오브젝트 파괴

-> 유용하게 쓸 수 있다.

위와 같은 경우 Camera가 오브젝트를 바라보지만 null이 되었을 경우 초기값으로 돌아가게 할 수 있다.

 

Emitting: Trail을 만드느냐? 

-> checked하면 Trail을 만들 것이고 unchecked는 Trail을 만들지 않는다. 

Trail을 조절할 수 있다.

 

나머지는 알아보고 싶으면 더 알아보자.

 


 

하지만 Trail Renderer도 분명 좋지만

시간이 지나면 궤적들이 사라진다. 

이걸 시간을 늘려서 남겨놓기도 조금 그렇잖아..?

만약 시간 조절을 못하면 3,4개의 궤적들이 화면에 돌아다니면 더 헷갈릴 것이다.

 

사실 Trail Renderer는 Line Renderer의 파생이라고 보면 된다.

즉, Line Renderer에서도 구현할 수 있다는 말이다. 

 

나는 이렇게 구현하고 싶다.

1. 이전의 던진 궤적은 남아있으되

2. 새로운 투사체가 생기면 이전의 궤적을 없애고 새로운 투사체의 궤적을 저장해놓는 것이다.

-> 이러한 궤적들을 따로 저장해놓는다면 게임에서 이전에 어떻게 던졌는지도 볼 수 있겠지?? 

 

아무튼 그래서 이것을 구현하기엔 Trail Renderer로는 부족하다.

 

Line Renderer를 통해 바꾸려고 한다.

 

우선 Empty Object를 만들어 거기에 LineRenderer를 넣어서 구현하려고 한다.

 

이제 Trail Renderer의 기능을 Line Renderer를 Script로 바꾸어서 구현해야 한다.

있는 것을 쓰자지만.. 내가 구현하고 싶은 기능은 없는걸..ㅎ

 

이렇게 Variables를 선언해준다.

++영어가 문법이 맞는지는 모르나 나에게는 이해가 된... 다.ㅎㅎ 영어로 써야 공부도 되는 것이니까

 

** Header를 쓰는 것은 정말 좋은 습관같다. 이번에 들여보려고 한다.

 

    static public ProjectileLine S; // Singleton

    [Header("Set in Inspector")]
    public float minDist = 0.1f;

    private LineRenderer line; // trailer
    private GameObject _poi; // Object to be trail
    private List<Vector3> points; // List for saving points

 

 

Initializing

   void Awake()
    {
        S = this;

        //Disable the LineRenderer until it's need.
        line = GetComponent<LineRenderer>();
        line.enabled = false;

        points = new List<Vector3>();


    }

 

필요한 Property

    public GameObject poi
    {
        get
        {
            return _poi;
        }

        set
        {
            _poi = value;
            if(_poi != null)
            {
                //set to something new
                line.enabled = false;
                points = new List<Vector3>();
                AddPoint();
            }
        }
    }

    //return the location of the most recently added point
    public Vector3 lastPoint
    {
        get
        {
            if (points == null)
            {
                return Vector3.zero;
            }
            return points[points.Count - 1];
        }

    }

 

Method

해당 오브젝트의 위치를 pt 에 저장

    public void AddPoint()
    {
        Vector3 pt = _poi.transform.position;

        //if the point isn't far enough from the last point, it returns
        if(points.Count > 0 && (pt - lastPoint).magnitude < minDist)
        {
            return;
        }
        if(points.Count == 0)
        {
            Vector3 launchPosDiff = pt - Slingshot.LAUNCH_POS;

            //it adds an extra bit of line to aid aiming later 
            points.Add(pt + launchPosDiff);
            points.Add(pt);
            line.positionCount = 2;

            //sets the first two points
            line.SetPosition(0, points[0]);
            line.SetPosition(1, points[1]);

            //enable LineRenderer
            line.enabled = true;

        }
        else
        {
            //normal adding of point
            points.Add(pt);
            line.positionCount = points.Count;
            line.SetPosition(points.Count - 1, lastPoint);
            line.enabled = true;
        }
    }

 

 

그리거 어떻게 실행될 지를 정하는 FixedUpdate()

void FixedUpdate()
    {
        if(poi == null)
        {
            //if there is no poi, then search
            if(FollowCam.POI != null)
            {
                if(FollowCam.POI.tag == "Projectile")
                {
                    poi = FollowCam.POI;
                }
                else
                {
                    //there is no poi
                    return;
                }
            }
            else
            {
                //there is no poi
                return;
            }
        }

        //if there is no poi, it's loc is added every fixedupdate
        AddPoint();
        if(FollowCam.POI == null)
        {
            //once followcam POi is null, make the local poi null too
            poi = null;
        }
    }

 

1. poi를 찾자

-> 투사체를 찾자.

 

2. 투사체가 있으면 해당 포지션을 더해주자.

 

3. FollowCam.POI == null이 되면 내가 참조하는 poi도 null로 만들어서 새로운 투사체를 찾자.

(FollowCam은 내가 임의로 만든 Script로 참조하고 있는 투사체가 일정 시간 이상 멈춰있으면 null로 만들었다)

-> 1 번으로감

 

**다른 사람이 Trail를 만들고 싶다면 AddPoints 부분만 보는 것이 낫다. 나는 다른 스크립트와 연계해서 구현했기 때문이다.

 

 

핵심을 한글로 다시 보자.

    public void AddPoint()
    {
    	
        
        //투사체의 위치를 받아옴.
        Vector3 pt = _poi.transform.position;

        //투사체의 모든 위치를 받아오는 것이 아니라, Trail Renderer의 minDistance처럼 간격을 둔다.
        if(points.Count > 0 && (pt - lastPoint).magnitude < minDist)
        {
            return;
        }
        
        
        
        //투사체의 시작 위치를 지정, Trail의 시작위치 조정
        if(points.Count == 0)
        {
            Vector3 launchPosDiff = pt - Slingshot.LAUNCH_POS;
			
            //해당 지점을 더해준다.
            points.Add(pt + launchPosDiff);
            points.Add(pt);
            line.positionCount = 2;
			
            
            line.SetPosition(0, points[0]);
            line.SetPosition(1, points[1]);


            line.enabled = true;
			
        }
        
        
        // position이 저장되었으면 투사체 trail 시작
        else
        {
            //normal adding of point
            points.Add(pt);
            line.positionCount = points.Count;
            line.SetPosition(points.Count - 1, lastPoint);
            line.enabled = true;
        }
    }

 

Line Renderer로 Trail을 구성한 것의 요약은

1. Time에 따라 지워지는 것이 아닌 Position이 그대로 남음

2. 다음 투사체를 발사하기 전까지 Trail이 남고 투사체가 발사되면 position이 초기화되어 자동으로 사라짐

위의 기능을 수행할 수 있다는 것이다.

 

핵심은 LineRenderer의 Position을 오브젝트에서 받아서 넣어준다는 것

 

 

 

 

 

 

728x90
반응형
그리드형