https://diding0222.tistory.com/38
일정한 간격으로 오브젝트 생성
private IEnumerator 코루틴이름() { //15개 생성할거니까 15, 간격은 2정도 CreateMagicPosWithInterval(15, 2f) } private void CreateMagicPosWithInterval(int count, float interval) { //플레이어 위치에서 살짝 떨어진 y값 4와 z값 -
diding0222.tistory.com
지난번에 광선을 발사할 rayStartPos를 생성했다.
이번엔 광선이 도착할 rayEndPos를 만들것.


//마법진과 물방울 생성 프리팹
public GameObject magicCircle;
public Transform megidoTargetPrefab;
//광선이 랜덤으로 도착할 magicPos 리스트로 저장
List<Transform> magicPosition = new List<Trasnform>
for (int = 0; i < 30; i++)
{
//랜덤하게 물방울 생성
Vector3 randomTargetOffset = new Vector3(UnityEngine.Random.Range(-15f, 15f),
UnityEngine.Random.Range(0f, 10f), UnityEngine.Random.Range(-15f, 15f));
//물방울은 마법진 기준으로 생성할것
Transform magicTarget = Instantiate(megidoTargetPrefab, magicCircle.transform.position + randomTargetOffset, Quaternion.identity);
//리스트에 저장된 위치에 랜덤하게 물방울 생성
magicTargetPosition.Add(magicTarget);
//한번에 생성하면 안 이뻐서 따다다다닥 생성
yield return new WaitforSeconds(0.1f);
}

//광선을 발사하는 기능 구현
foreach (Transform startPos in magicPosition) //List에 저장된 각 위치에서 시작한다
{
int randomTargetIndex = UnityEngine.Random.Range(0, magicPosition.Count);
Transform endPos = magicPosition[randomTargetIndex];
//광선 발사 코루틴 : From startPos ~ To endPos
//랜덤으로 목표를 정하여 무한히 튕긴다
StartCorotine(ShootRayFromTo(startPos, endPos, 10f)); //10f는 광선의 속도
}
private IEnmuerator ShootRayFromTo(Transform from, Transform to, float raySpeed)
{
//시작위치와 도착위치는 위에서 설정한 startPos, endPos이다.
Vector3 startPosition = from.position;
Vector3 endPosition = to.position;
While (Vector3.Distance(startPosition, endPosition) > 0.1f)
{
//상대적 위치와 방향을 알기위한 endPos - startPos
Ray ray = new Ray (startPosition, endPosition - startPosition)
RaycastHit hitInfo;
if (Physcis.Raycast(ray, ouhitInfo, raySpeed * Time.deltaTime))
{
//광선이 목표 지점에 도착했다면 다시한번 새로운 목표를 찾음
if (hitInfo.transform == to)
{
Debug.Log("광선이 목표에 도달했습니다.");
//List에서 저장된 'magicPosition'에 랜덤한 인덱스를 불러옴
int randomTargetIndex = UnityEngine.Random.Range(0, magicPosition.Count);
//해당 인덱스에 목표 'to'를 저장
to = magicPosition[randomTargetIndex]
//to의 위치를 endPos에 전달
endPosition = to.position
}
}
//광선이 잘 이동하는지 그려주기
Debug.DrawLine(startPosition, endPosition, Color.red , 0.5f);
//위에 ray에서 위치와 방향을 얻었으니
//startPosition에서 목표 방향까지 속도와 위치를 반환해준다.
startPosition = ray.GetPoint(raySpeed * Time.deltaTime);
yield return null;
}
}
이제 광선이 빠른속도로 발사는 되는데, Debug.DrawLine으로 육안으로 표시하면 쉽게 확인이 가능하다.
하지만 문제가 있다. 내가 원하는건 rayStartPos에서 광선을 1회만 발사하고, rayEndPos끼리 계속 광선이 튕기는 것을 원했다. 지금은 rayStartPos와 rayEndPos이 차별없이 서로 튕기고있다.
문제는 바로 List<Transform> magicPosition; 때문인데, 위치를 저장할 List에 나는 광선이 시작될 지점과 도착될 지점을 구분하지 않고 저장했기 때문이었습니다.
그래서 광선이 발사될 시작 위치와 광선이 튈길 대상 위치를 저장할 리스트를 구분해서 재 생성했습니다.
//시작 위치, 튕길 대상 위치 저장 리스트 생성
private List<Transform> magicStartPosition = new List<Transform>
private List<Transform> magicTargetPositions = new List<Transform>
//Instanitate와 List.Add하던 부분도 수정해줍니다
Transform magicTarget = Instantiate(megidoTargetPrefab, magicCircle.transform.position +
randomTargetOffset, Quaternion.identity);
magicTargetPositions.Add(magicTarget);
//광선을 발사하는 기능 구현
//magicPosition을 Start, Target으로 수정
foreach (Transform startPos in magicStartPosition) //수정
{
int randomTargetIndex = UnityEngine.Random.Range(0, magicTargetPosition.Count); //수정
Transform endPos = magicTargetPosition[randomTargetIndex]; //수정
StartCorotine(ShootRayFromTo(startPos, endPos, 10f));
}
===========================================
while (Vector3.Distance(startPosition, endPosition) > 0.1f)
{
...기존 코드
if (Physics.Raycast(ray, out hitInfo, speed * Time.deltaTime))
{
if (hitInfo.transform == to)
{
//광선이 목표에서만 튕기도록 Target으로 수정
int randomTargetIndex = UnityEngine.Random.Range(0, magicTargetPosition.Count);
to = magicTargetPosition[randomTargetIndex];
endPosition = to.position;
}
}
...기존코드
}
이제 megido를 발사할 Pos에서는 광선을 1회만 발사할수있도록하자.
다음 아래 부분을 While문 위에 넣어준다.
// 광선을 1회 발사햇다면
// List에 저장된 magicPosition을 제거해 다시 발사Pos로 돌아올수없도록 한다.
if (magicStartPosition.Contains(from))
{
magicStartPosition.Remove(from)
}
이제 되겠지? 안됩니다.
InvalidOperationException: Collection was modified; enumeration operation may not execute.
System.Collections.Generic.List`1+Enumerator[T].MoveNextRare () (at <605bf8b31fcb444b85176da963870aa7>:0)
System.Collections.Generic.List`1+Enumerator[T].MoveNext () (at <605bf8b31fcb444b85176da963870aa7>:0)
SpecialSkill+<ExeCuteJump>d__17.MoveNext () (at Assets/Scripts/Skill/SpecialSkill.cs:119)
UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at <c2d036c16ca64e0eb93703a3b13e733a>:0)
InvalidOperationException 블라블라.... 이 오류 예전에 인벤토리 연습하다 마주쳤다.
리스트 열거하는 도중에 항목을 추가 또는 제거 도중에 발생하는 List문제라고 기억하는데, 알아도 어떻게 고쳐야하지...
제거하는 도중에 오류니까, magicStartPosition의 모든 요소를 저장할 리스트를 하나 더 만들어줬다.
//Remove로 magicStartPosition을 제거하므로 오류가 발생
//magicStartPosition을 안전하게 저장할 리스트를 하나 더 생성해 tempList에 복사
var tempList = new List<Transform>(magicStartPosition);
foreach (Transform startPos in tempList) //안전하게 복사한 tempList넣기
{
...기존코드
StartCoroutine(ShootRayFromTo(startPos, endPos, 10f));
}
private IEnumerator ShootRayFromTo(Transform from, Transform to, float raySpeed)
{
...기존코드
//광선을 1회 발사했으면 발사 위치를 제거.
//제거해도 tempList가 있으니 안전하다.
if (magicStartPosition.Contains(from))
{
magicStartPosition.Remove(from);
}
...
}


광선끼리 무제한으로 튕긴다.
완성본

'Unity Engine > Unity 3D.' 카테고리의 다른 글
| [유니티 3D] Enemy 상태패턴 작성 (0) | 2023.10.22 |
|---|---|
| [Unity 3D] Creating Monster State Machine (0) | 2023.10.21 |
| 일정한 간격으로 오브젝트 생성 (0) | 2023.10.20 |
| 유니티 3D 잔상효과 (1) | 2023.10.20 |
| 콤보어택 정리 전 (0) | 2023.10.19 |