나는 퍼즐의 표면 스냅 조각에 대한 이 블로그 게시물 의 도움으로 필요한 것을 달성 했으며 플레이어 움직임과 카메라에 대한 내 자신의 아이디어를 생각해 냈습니다.
플레이어를 객체 표면에 물리기
기본 설정은 큰 구체 (세계)와 작은 구체 (플레이어)로 구성되어 있으며 구체 구체가 부착되어 있습니다.
수행되는 대부분의 작업은 다음 두 가지 방법으로 이루어졌습니다.
private void UpdatePlayerTransform(Vector3 movementDirection)
{
RaycastHit hitInfo;
if (GetRaycastDownAtNewPosition(movementDirection, out hitInfo))
{
Quaternion targetRotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);
Quaternion finalRotation = Quaternion.RotateTowards(transform.rotation, targetRotation, float.PositiveInfinity);
transform.rotation = finalRotation;
transform.position = hitInfo.point + hitInfo.normal * .5f;
}
}
private bool GetRaycastDownAtNewPosition(Vector3 movementDirection, out RaycastHit hitInfo)
{
Vector3 newPosition = transform.position;
Ray ray = new Ray(transform.position + movementDirection * Speed, -transform.up);
if (Physics.Raycast(ray, out hitInfo, float.PositiveInfinity, WorldLayerMask))
{
return true;
}
return false;
}
Vector3 movementDirection
나 처음에 파악하기 위해 매개 변수는 소리대로, 우리는이 예에서는 비교적 간단한 결국하면서,이 프레임에 우리의 플레이어를 이동하고, 그 벡터를 계산하는 가고있는 방향은 조금 까다했다. 나중에 더 자세히 설명하지만 플레이어 가이 프레임을 움직이는 방향으로 표준화 된 벡터라는 점을 명심하십시오.
먼저, 우리가하는 첫 번째 일은 플레이어 다운 벡터 (-transform.up)를 향한 가상의 미래 위치에서 발생하는 광선이 스크립트의 공용 LayerMask 속성 인 WorldLayerMask를 사용하여 세계에 닿는 지 확인하는 것입니다. 더 복잡한 충돌이나 여러 레이어를 원한다면 자신 만의 레이어 마스크를 만들어야합니다. 레이 캐스트가 성공적으로 충돌하면 hitInfo를 사용하여 오브젝트의 올바른 위치와 회전을 계산하기 위해 정상 및 적중 지점을 검색합니다. 문제의 플레이어 객체의 크기와 원점에 따라 플레이어의 위치를 상쇄해야 할 수도 있습니다.
마지막으로, 이것은 실제로 테스트되었으며 구체와 같은 간단한 물체에서만 잘 작동합니다. 내가 제안한 솔루션을 기반으로 한 블로그 게시물에서 여러 복잡한 레이 캐스트를 수행하고 위치와 회전에 대한 평균을 계산하여 더 복잡한 지형을 이동할 때 훨씬 더 좋은 전환을 얻을 수 있습니다. 이 시점에서 내가 생각하지 않은 다른 함정이있을 수도 있습니다.
카메라와 움직임
플레이어가 물체의 표면에 달라 붙으면 다음으로해야 할 일은 움직임이었습니다. 나는 원래 플레이어를 상대로 움직임을 시작했지만 구 방향에서 갑자기 방향이 바뀌면서 플레이어가 빠르게 방향을 바꾸고 극을 통과하지 못하게하는 문제가 발생하기 시작했습니다. 내가 상처를 준 것은 플레이어들이 카메라를 기준으로 움직이게하는 것이 었습니다.
내 필요에 잘 맞는 것은 플레이어 위치만을 기준으로 플레이어를 엄격하게 따르는 카메라를 갖추는 것이 었습니다. 결과적으로, 카메라가 기술적으로 회전하고 있더라도 위를 누르면 플레이어가 항상 화면의 상단을 향하고 하단을 향하는 방향으로 좌우로 이동합니다.
이를 위해 대상 객체가 플레이어 인 카메라에서 다음이 실행되었습니다.
private void FixedUpdate()
{
// Calculate and set camera position
Vector3 desiredPosition = this.target.TransformPoint(0, this.height, -this.distance);
this.transform.position = Vector3.Lerp(this.transform.position, desiredPosition, Time.deltaTime * this.damping);
// Calculate and set camera rotation
Quaternion desiredRotation = Quaternion.LookRotation(this.target.position - this.transform.position, this.target.up);
this.transform.rotation = Quaternion.Slerp(this.transform.rotation, desiredRotation, Time.deltaTime * this.rotationDamping);
}
마지막으로 플레이어를 움직이기 위해 메인 카메라의 변형을 활용하여 컨트롤을 위로, 아래로 아래로 이동하는 등의 작업을 수행했습니다. 그리고 여기에서는 UpdatePlayerTransform을 호출하여 위치를 월드 오브젝트에 고정시킵니다.
void Update ()
{
Vector3 movementDirection = Vector3.zero;
if (Input.GetAxisRaw("Vertical") > 0)
{
movementDirection += cameraTransform.up;
}
else if (Input.GetAxisRaw("Vertical") < 0)
{
movementDirection += -cameraTransform.up;
}
if (Input.GetAxisRaw("Horizontal") > 0)
{
movementDirection += cameraTransform.right;
}
else if (Input.GetAxisRaw("Horizontal") < 0)
{
movementDirection += -cameraTransform.right;
}
movementDirection.Normalize();
UpdatePlayerTransform(movementDirection);
}
보다 흥미로운 카메라를 구현하지만 컨트롤이 여기에있는 것과 거의 동일하게 렌더링하기 위해 렌더링되지 않은 카메라 또는 움직임을 기반으로하는 다른 더미 오브젝트를 쉽게 구현 한 다음 더 흥미로운 카메라를 사용하여 당신은 게임처럼 보이기를 원합니다. 이를 통해 컨트롤을 깨지 않고도 객체를 둘러 볼 때 멋진 카메라 전환이 가능합니다.