유니티/실습

오브젝트풀 - 체인라이트닝

파란색까마귀 2022. 2. 15. 16:46

 2022. 2. 5. 22:24

https://blog.naver.com/nagne2011/222639841785

 

오브젝트풀 - 체인라이트닝

#유니티 #오프젝트풀 #체인라이트닝 오브젝트풀 활용, 라인렌더러를 이용한 체인라이트닝 구현 1. 오브젝트...

blog.naver.com

 

오브젝트풀 활용, 라인렌더러를 이용한 체인라이트닝 구현

 

 

1. 오브젝트풀 사용해서 라인렌더러, 강조이펙트 각각 생성

2. 각 오브젝트 사이를 라인렌더러로 이어준 다음 일정 갯수로 쪼개서 임의수치만큼 포지션을 흔든다

3. 강조이펙트도 하나 만들어서 붙여준다 (번개의 빛 효과를 위해)

4. 위 작업을 모든 오브젝트들 사이에서 일정시간동안 동작하도록 반복한다

 


0. 일단 오브젝트 부터 준비하자

사용할 스프라이는 두가지, 라인렌더러와 강조이펙트다

 

강조이펙트 전용

클릭해야 보입니다

직선오브젝트다..

 

해당 스프라이트로 마테리얼을 만들어주고

라인렌더러를 구성해준다

 

같은방식으로

강조이펙트도 생성해준다

 

두 오브젝트는 각각 프리펩화 해서 준비시켜준다

 

 

1. 오브젝트풀 사용

라인렌더러와 강조이펙트 관리를 위한 오브젝트 풀을 먼저 구현해준다

https://nagne2011.tistory.com/141

 

유니티 오브젝트풀링(object pooling)

2022. 2. 3. 19:37 https://blog.naver.com/nagne2011/222638060370 유니티 오브젝트풀링(object pooling) #유니티 #오브젝트풀링 #오브젝트풀링 #슈팅게임 #서바이벌게임 오브젝트이 생성(Instantiate)과 삭제(De..

nagne2011.tistory.com

public class LightningBoltManager : MonoBehaviour
{
	[SerializeField]
	private GameObject lineRendererPrefab;
	[SerializeField]
	private GameObject lightRendererPrefab;

	[SerializeField]
	private Transform m_effectParent;
	[SerializeField]
	private Transform m_usedParent;

	Queue<LineRenderer> m_poolingLineObjectQueue = new Queue<LineRenderer>();
	Queue<LineRenderer> m_poolingLightObjectQueue = new Queue<LineRenderer>();

	public void InitalizeLine(int count)
	{
		for (int i = 0; i < count; i++)
		{
			CreateNewLineEffect();
		}
	}
	public void InitializeLight(int count)
	{
		for (int i = 0; i < count; i++)
		{
			CreateNewLightEffect();
		}
	}

	private LineRenderer CreateNewLineEffect()
	{
		var obj = Instantiate(lineRendererPrefab.GetComponent<LineRenderer>());
		obj.gameObject.SetActive(false);
		obj.transform.SetParent(m_usedParent);
		m_poolingLineObjectQueue.Enqueue(obj);

		return obj;
	}

	private LineRenderer CreateNewLightEffect()
	{
		var obj = Instantiate(lightRendererPrefab.GetComponent<LineRenderer>());
		obj.gameObject.SetActive(false);
		obj.transform.SetParent(m_usedParent);
		m_poolingLightObjectQueue.Enqueue(obj);

		return obj;
	}

	public LineRenderer GetLineObject()
	{
		if (m_poolingLineObjectQueue.Count <= 0)
		{
			CreateNewLineEffect();
		}

		var obj = m_poolingLineObjectQueue.Dequeue();
		obj.gameObject.SetActive(true);
		obj.transform.SetParent(m_effectParent);
		return obj;
	}

	public LineRenderer GetLightObject()
	{
		if (m_poolingLightObjectQueue.Count <= 0)
		{
			CreateNewLightEffect();
		}

		var obj = m_poolingLightObjectQueue.Dequeue();
		obj.gameObject.SetActive(true);
		obj.transform.SetParent(m_effectParent);
		return obj;
	}

	public void ReturnLineObject(LineRenderer obj)
	{
		obj.gameObject.SetActive(false);
		obj.transform.SetParent(m_usedParent);
		m_poolingLineObjectQueue.Enqueue(obj);
	}

	public void ReturnLightObject(LineRenderer obj)
	{
		obj.gameObject.SetActive(false);
		obj.transform.SetParent(m_usedParent);
		m_poolingLightObjectQueue.Enqueue(obj);
	}
}
 

코드는 링크를 참고해서 기존 오브젝트풀 코드를 응용해서 추가해준다

라인렌더러와 이펙트 각각 만들어주자

 

그리고 해당 라인렌더러와 이펙트를 묶어준 클래스하나를 미리 만든다

public class LightningRenderer
{
	public LineRenderer[] lineRendererArray;
	public LineRenderer lightRenderer;

	public void Init(LightningBoltManager lightningBoltManager, int count)
	{
		lineRendererArray = new LineRenderer[count];
		lightRenderer = new LineRenderer();

		for (int i = 0; i < count; i++)
		{
			lineRendererArray[i] = lightningBoltManager.GetLineObject();
		}

		lightRenderer = lightningBoltManager.GetLightObject();
	}

	public void ReturnRenderer(LightningBoltManager lightningBoltManager)
	{
		for (int i = 0; i < lineRendererArray.Length; i++)
		{
			lightningBoltManager.ReturnLineObject(lineRendererArray[i]);
		}

		lightningBoltManager.ReturnLightObject(lightRenderer);
	}
}
 

따로 스크립트를 만들지 않고 다른 클래스위에 만들어서 꺼내어쓰자

이제 관리 스크립트를 만들어서 초기 세팅을 해준다

이때 미리 오브젝트풀에 사용할 오브젝트 몇개 만들어서 최적화를 하자

 

public class ChainLightning : MonoBehaviour
{
	public LightningBoltManager m_lightningBoltManager;
	public GameObject[] TargetObj;
	
	[Header("Config")]
	public int lightnings;
	public float segmentLength = 0.2f;
	public float duringTime = 0.2f;

	private void Awake()
	{
		m_lightningBoltManager.InitalizeLine(12);
		m_lightningBoltManager.InitializeLight(3);
	}
 

 

2. 각 오브젝트 사이를 라인렌더러로 이어준 다음 일정 갯수로 쪼개서 임의수치만큼 포지션을 흔든다

	public void DrawLightning(LineRenderer[] lineRenderer, LineRenderer lightRenderer, Vector2 source, Vector2 target)
	{
		float distance = Vector2.Distance(source, target);
		int segments = 5;
		if (distance > segmentLength)
			segments = Mathf.FloorToInt(distance / segmentLength) + 2;
		else
			segments = 4;

		for (int i = 0; i < lineRenderer.Length; i++)
		{
			lineRenderer[i].positionCount = segments;
			lineRenderer[i].SetPosition(0, source);
			Vector2 lastPostion = source;
			for (int j = 1; j < segments - 1; j++)
			{
				Vector2 temp = Vector2.Lerp(source, target, (float)j / (float)segments);
				lastPostion = new Vector2(temp.x + Random.Range(-0.1f, 0.1f), temp.y + Random.Range(-0.1f, 0.1f));
				lineRenderer[i].SetPosition(j, lastPostion);
			}
			lineRenderer[i].SetPosition(segments - 1, target);
		}

		lightRenderer.SetPosition(0, source);
		lightRenderer.SetPosition(1, source);

		Color lightColor = new Color(0.5647f, 0.58823f, 1f, Random.Range(0.2f, 1f));
		lightRenderer.startColor = lightColor;
		lightRenderer.endColor = lightColor;
	}
 

라인렌더러를 본격적으로 활용하는 부분이다

라인렌더러는 시작점~끝점 두개의 점으로 이을수도있고 두 점 사이에 추가로 '점'을 더 찍어서 여러가지로 활용할수 있다

이걸 활용하는 방식이다

최소 4개, 그리고 시작-끝 두 점의 길이에 비례한 일정 갯수의 '점'을 추가한뒤

해당 점을 선의 방향과 추가로 x,y축으로 임의로 이동시킨다

 

글자로 쓰면 복잡한데.. 그림으로 보면 간단하다

추가로 강조효과 이펙트를 시작-끝 두 점에 배치하면

'번개'의 '빛'효과를 줄수있다

 

이제 관련 이펙트를 코루틴을 이용해서 구현해주면된다

	public void CastingLightning(GameObject[] targetArray, float effectTimer)
	{
		StartCoroutine(CoCasting(targetArray, effectTimer));
	}

	private IEnumerator CoCasting(GameObject[] targetArray, float effectTimer)
	{
		Debug.Log(targetArray.Length);

		if (targetArray.Length <= 1)
			yield break;

		float timer = 0;
		float endTimer = effectTimer;

		List<LightningRenderer> temp = new List<LightningRenderer>();
		for (int i = 1; i < targetArray.Length; i++)
		{
			if (targetArray[i] == null)
				break;

			LightningRenderer lightningRenderer = new LightningRenderer();
			lightningRenderer.Init(m_lightningBoltManager, lightnings);
			temp.Add(lightningRenderer);
		}

		while (endTimer > timer)
		{
			for (int i = 1; i < targetArray.Length; i++)
			{
				if (targetArray[i] == null)
					break;

				DrawLightning(temp[i-1].lineRendererArray, temp[i-1].lightRenderer, targetArray[i - 1].transform.position, targetArray[i].transform.position);
			}

			timer += Time.deltaTime;
			yield return null;
		}

		for (int i = 0; i < temp.Count; i++)
		{
			temp[i].ReturnRenderer(m_lightningBoltManager);
		}
	}
 
 

체인라이트닝의 특징인 '각 대상에게 맞고, 다음대상에게 순차적으로 튕김'을 구현하기위해

'대상'을 Gameobject의 array로 받아서 각각 오브젝트를 시작-끝점으로 잡아서 이펙트를 그려준다

 

해당 이펙트는 코루틴 함수를 통해 정해진 시간만큼만 표시해주고 오브젝트풀 응용해서 삭제해준다

 

 

 

728x90