이번에는 이동플랫폼이 가로방향일 때 지정된 범위까지 왔다갔다하는 구현을 해 보았다.
위의 영상처럼 플랫폼이 어느 방향이든 지정 방향과 거리만큼 왔다갔다 할 것이다.
구현할때 이렇게 생각했다.
먼저 Start함수를 호출할 때 시작 위치와 그 위치의 방향의 거리를 계산해서 이동시키려고 했다.
private void MovePlatform() //발판 움직임
{
int moveReverse = isReverse ? -1 : 1;
if (moveData.movableType == MovablePlatformType.Horizontal)
{
//x축 이동
//현재 위치에서 최대 거리보다 넘어가면
if (transform.position.x >= endPos.x && !isReverse)
WaitToReverse();
else if(transform.position.x <= startPos.x && isReverse)
WaitToReverse();
else
{
transform.Translate(Vector3.right * moveData.platformSpeed * moveReverse * Time.deltaTime);
}
}
else if (moveData.movableType == MovablePlatformType.Vertical)
{
//y축 이동
if (transform.position.y >= endPos.y && !isReverse)
WaitToReverse();
else if (transform.position.y <= startPos.y && isReverse)
WaitToReverse();
else
{
transform.Translate(Vector3.up * moveData.platformSpeed * moveReverse * Time.deltaTime);
}
}
}
어제 TIL의 코드의 일부분인데, 조건문의 "transform.position.x >= endPos.x"같은 문장을 보면
endPos가 startPos에서 지정된 거리만큼 떨어져 있는 지점인데(startPos가 시작했을때 위치를 저장한다)
예를 들어 endPos가 5일때 오브젝트 transform.rotation값이 50˚로 설정한다면 50˚에서 로컬에서 x좌표를 해당 거리까지 이동해야 하는데 월드 좌표계에서 계산이 되어 버려 각도가 높게 나오면 좀 더 멀리 나갈수가 있고 90˚로 하면 끝까지 나가버리는 현상이 발생한다.
그리고 코드를 저렇게 짜면 읽기 복잡할 뿐 아니라 코드가 반복적인 것이 나오고 WaitToReverse함수를 많이 호출되는 것이 나와서 효율적이지 못하다.
이런 문제를 해결하는 방법은 Vector3에 내장되어있는 Distance함수로 비교하는 것이다.
Vector3.Distance(시작위치, 목표위치);
public class MovablePlatform : Platform
{
...
private float nowTime = 0;
private Vector3 startPos;
private Vector3 endPos;
private Vector3 moveDirection; //이동하려는 방향
...
private void Start()
{
startPos = transform.localPosition; //원래 자리로 돌아오기 위한 위치
endPos = transform.TransformPoint(new Vector3(maxDistance, 0f, 0f));
//Debug.Log(Vector3.Distance(startPos, endPos)); 두 벡터의 길이가 어디까지인지를 계산한다.
if (moveData.movableType == MovablePlatformType.Horizontal)
moveDirection = Vector3.right;
else if (moveData.movableType == MovablePlatformType.Vertical)
moveDirection = Vector3.up;
}
private void Update()
{
MovePlatform();
}
private void MovePlatform() //발판 움직임
{
int moveReverse = isReverse ? -1 : 1;
//현재 위치에서 최대 거리보다 넘어가면
if (Vector3.Distance(startPos, transform.position) > maxDistance && !isReverse)
WaitToReverse();
else if(Vector3.Distance(transform.position, startPos) < 0.1f && isReverse) //0으로 하면 그냥 지나가버린다.
WaitToReverse();
else
{
transform.Translate(moveDirection * moveData.platformSpeed * moveReverse * Time.deltaTime);
}
}
...
}
이전 스크립트와 비교하면 우선 조건문으로 MovablePlatformType으로 받지 않았다. 그리고 방향을 결정할때 moveDirection이라는 벡터를 만들고 Start에서 방향을 결정하고 이동할때 Translate를 Vector3.up, Vector3.right로 하는것보다 moveDirection으로 하는 것이 효율적이라고 생각한다. 그리고 WaitToReverse함수가 덜 호출이 되었다.
이건 개인과제하면서 만들었던 건데 똑같이 이동하는 플랫폼을 만든 스크립드다.
void Update()
{
if (startPos.x != endPos.x)
MovePlatform(transform.position.x, startPos.x, endPos.x);
if (startPos.y != endPos.y)
MovePlatform(transform.position.y, startPos.y, endPos.y);
if (startPos.z != endPos.z)
MovePlatform(transform.position.z, startPos.z, endPos.z);
}
void MovePlatform(float nowTransfom, float startTransform, float endTransform)
{
if (startTransform < endTransform)
{
//endPos까지 닿으면 대기시간 후 다시 반대로
if (nowTransfom >= endTransform)
{
transform.Translate(Vector3.zero);
time += Time.deltaTime;
if (time >= waitTime)
{
time = 0;
ChangePosition();
}
}
else
{
transform.Translate((endPos - startPos).normalized * Time.deltaTime * speed);
}
}
if (startTransform > endTransform)
{
if (nowTransfom <= endTransform)
{
transform.Translate(Vector3.zero);
time += Time.deltaTime;
if (time >= waitTime)
{
time = 0;
ChangePosition();
}
}
else
{
transform.Translate((startPos - endPos).normalized * Time.deltaTime * -speed);
}
}
}
이 코드는 두 벡터로 비교를 하여 수행시켰다.
이렇게 하면 조건문들이 덕지덕지 붙어있고 기다리는 역시 코드가 두번 중복되어있다.
그래서 이동 플랫폼을 구현할 때 이전 스크립트를 참고하는게 효율적이다.
한가지 발견한 문제가 있는데, 플레이어가 발판을 밟을 때 플레이어가 앞 방향을 바라보지 않고 이상한 방향으로 틀어버리는 현상이 발생했다.
이러한 이유는 Player의 회전하는 코드를 transform.localEulerAngles = new Vector3(0, yaw, 0);로 짜놨기 때문에 발판에 닿으면 플레이어가 부모 오브젝트의 영향을 받아 회전값이 같이 돌아버리게 된다.
그래서 코드만 살짝 바꾸기만 하면 되는데 transform.rotation = Quaternion.Euler(0, yaw, 0);로 바꾸면 플레이어는 부모 오브젝트의 transform의 영향을 받지 않을 것이다. (권관우 튜터님)
발판 오브젝트가 플레이어와 콜라이전 했으면 플레이어의 부모 오브젝트가 발판으로 설정한 코드를 짜 놨다.
by 스파르타 코딩클럽
'개발 TIL' 카테고리의 다른 글
6/10 부트캠프 개발 TIL (Json 메뉴) (0) | 2024.06.11 |
---|---|
6/7 부트캠프 개발 TIL (자료구조) (1) | 2024.06.07 |
6/4 부트캠프 개발 TIL (플레이어와 발판 상호작용) (0) | 2024.06.04 |
6/3 부트캠프 개발 TIL (Nav Mesh 활용) (0) | 2024.06.03 |
5/31 부트캠프 개발 TIL (Nav Mesh) (0) | 2024.05.31 |