[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 40회차 미션 시작합니다.
04. 배틀로얄 - 25, 26 번을 진행합니다.
저번 시간에 이어 ThirdPersonOrbitCam 스크립트를 지속 작성합니다.
우선 Unity Script의 이벤트 함수 실행 순서는 반드시 숙지해야 하는 내용입니다.
Unity 매뉴얼 최신 URL은 다음과 같습니다.
docs.unity3d.com/kr/2020.2/Manual/ExecutionOrder.html
그래도 정리된 Flowchart를 첨부합니다. 정리가 아주 죽입니다. ㅎㅎ
일단 Camera의 위치가 어떻게 위치하게 되는지 Update() 함수를 임시로 작성하여 확인해 봅니다.
위와 같이 작성후 플레이를 해보면 다음과 같이 오른쪽 어깨 위쯤에서 약간 위를 보는 듯한 시선으로 처리되는 것을 확인할 수 있습니다.
Update() 내용은 모두 지우고 ThirdPersonOrbitCam 스크립트를 계속 작성합니다.
[RequireComponent(typeof(Camera))] // Camera 컴포넌트 있어야 구동.
public class ThirdPersonOrbitCam : MonoBehaviour
{
// 저번 시간 작성한 변수들..
private void Awake() {
// 캐싱
cameraTransform = transform;
myCamera = cameraTransform.GetComponent<Camera>();
// 카메라기본 포지션 세팅
cameraTransform.position = player.position + Quaternion.identity * pivotOffset + Quaternion.identity * camOffset;
cameraTransform.rotation = Quaternion.identity;
// 카메라의 플레이어간의 상대 벡터, 충돌체크에 사용하기 위함
relCameraPos = cameraTransform.position - player.position;
relCameraPosMag = relCameraPos.magnitue - 0.5f; // 플레이어 충돌을 피하기 위한 Offset
// 기본 세팅
smoothPivotOffset = pivotOffset;
smoothCamOffset = camOffset;
defaultFOV = myCamera.fieldOfView;
angleH = player.eulerAngles.y;
ResetTargetOffsets();
ResetFOV();
ResetMaxVerticalAngle();
}
public void ResetTargetOffsets() {
targetPivotOffset = pivotOffset;
targetCamOffset = camOffset;
}
public void ResetFOV() {
targetFOV = defaultFOV;
}
public void ResetMaxVerticalAngle() {
targetMaxVerticalAngle = maxVerticalAngle;
}
public void BounceVertical(float degree) {
recoilAngle = degree;
}
public void SetTargetOffset(Vector3 newPivotOffset, Vector3 newCamOffset) {
targetPivotOffset = newPivotOffset;
targetCamOffset = newCamOffset;
}
public void SetFOV(float customFOV) {
targetFOV = customFOV;
}
bool ViewingPosCheck(Vector3 checkPos float deltaPlayerHeight) {
Vector3 target = player.position + (Vector3..up * deltaPlayerHeight);
if (Physics.SphereCast(checkPos, 0.2f, target - checkPos, out RaycastHit hit, relCameraPosMag)) {
if (hit.transform != player && !hit.transform.GetComponent<Collider>().isTrigger)
return false;
}
return true;
}
bool ReverseViewingPosCheck(Vector3 checkPos, float deltaPlayerHeight, float maxDistance) {
Vector3 origin = player.position + (Vector3.up * deltaPlayerHeight);
if (Physics.SphereCast(origin, 0.2f, checkPos - origin, out RaycastHit hit, maxDistance) {
if (hit.transform != player & hit.transform != transform && !hit.transform.GetComponent<Collider>().isTrigger)
return false;
}
return true;
}
bool DoubleViewingPosCheck(Vector3 checkPos, float offset) {
float playerFocusHeight = player.GetComponent<CapsuleCollider>().height * 0.75f;
return ViewingPosCheck(checkPos, playerFocusHeight) && ReverseViewingPosCheck(checkPos, playerFocusHeight, offset);
}
void Update() {
// 마우스 이동 값..
angleH += Mathf.Clamp(Input.GetAxis("Mouse X"), -1f, 1f) * horizontalAimingSpeed;
angleV += Mathf.Clamp(Input.GetAxis("Mouse Y"), -1f, 1f) * verticalAimingSpeed;
// 수직 이동 제한
angleV = Mathf.Clamp(angleV, minVerticalAngle, targetMaxVerticalAngle);
// 수직 카메라 바운스
angleV = Mathf.LerpAngle(angleV, angleV + recoilAngle, 10f * Time.deltaTime);
// 카메라 회전
Quaternion camYRotation = Quaternion.Euler(0.0f, angleH, 0.0f);
Quaternion aimRotation = Quaternion.Euler(-angleV, angleH, 0.0f);
cameraTransform.rotation = aimRotation;
// Set FOV
myCamera.fieldOfView = Mathf.Lerp(myCamera.fieldOfView, targetFOV, Time.deltaTime);
Vector3 baseTempPosition = player.position + camYRotation * targetPivotOffset;
Vector3 noCollisionOffset = targetCamOffset; // 조준할 때 카메라의 오프셋값, 조준할때와 평소때가 다르다.
for (float zOffset = targetCamOffset.z; zOffset <= 0f; zOffset += 0.5f) {
noCollisionOffset.z = zOffset;
if (DoubleViewingPosCheck(baseTempPosition + aimRotation * noCollisionOffset, Mathf.Abs(zOffset)) || zOffset == 0f) {
break;
}
}
// Reposition Camera
smoothPivotOffset = Vector3.Lerp(smoothPivotOffset, targetPivotOffset, smooth * Time.deltaTime);
smoothCamOffset = Vector3.Lerp(smoothCamOffset, noCollisionOffset, smooth * Time.deltaTime);
cameraTransform.position = player.position + camYRotation * smoothPivotOffset + aimRotation * smoothCamOffset;
if (recoilAngle > 0.0f) {
recoilAngle -= recoilAngleBounce * Time.deltaTime;
}
else if (recoilAngle < 0.0f) {
recoilAngle += recoilAngleBounce * Time.deltaTime;
}
public float GetCurrentPivotMagnitude(Vector3 finalPivotOffset) {
return Mathf.Abs((finalPivotOffset - smoothPivotOffset).magnitue);
}
}
}
위와 같이 하고 컴파일 에러가 없는 것을 확인 후, 플레이를 해보면 마우스 움직임에 따라 카메라 시점이 변경되는 것을 확인할 수 있습니다.
이제 플러거블 동작 시스템을 제작합니다.
우선 플러거블 동작 시스템에 대한 설명입니다. 우선 플러거블 패턴을 사용하지 않았을 때의 문제점에 대해 간략히 설명합니다.
나쁜 코드에 대한 예입니다. 하나의 Update()에서 특정 키를 누를 때 무얼하고 무엇하고, 그런데 이럴때는 예외처리를 하고 등을 넣고 하다보면 Update()가 엄청나게 길어지고 복잡한 코드로 만들어지는 것을 볼 수 있습니다. 이러한 문제가 발생한다는 것이지요.
[7]
디아블로 시간에 설명되었던 Transition에 대한 설명입니다 ^^~
그리고 이것을 구현하는 디자인 패턴 방법이 Pluggable Pattern인 것입니다.
캐릭터를 하나 가져다 놓고, Rigidbody와 CapsuleCollider를 추가하여 대략적인 세팅을 해줍니다.
다음 시간에는 Pluggable Pattern을 하나씩 만들어 보게 되겠네요 ^^~
<위의 코드들은 제가 보면서 주요한 함수, 코드를 확인하기 위해 타이핑한 용도로, 전체 소스코드가 아님에 주의해 주세요. 전체 코드는 교육 수강을 하면 완벽하게 받으실 수가 있답니다 ^^>
패스트캠퍼스 - 올인원 패키지 : 유니티 포트폴리오 완성 bit.ly/2R561g0
'[컴퓨터] > 웹 | 앱 | 게임 개발' 카테고리의 다른 글
[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 42회차 미션 (0) | 2020.11.29 |
---|---|
[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 41회차 미션 (0) | 2020.11.28 |
[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 39회차 미션 (0) | 2020.11.26 |
[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 38회차 미션 (0) | 2020.11.25 |
[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 37회차 미션 (0) | 2020.11.24 |