일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- XR
- OVR
- VR
- 가상현실
- 유니티 Json 데이터 연동
- Oculus
- HAPTIC
- 팀프로젝트
- 개발일지
- 오브젝트 풀링
- 오큘러스
- 팀 프로젝트
- 드래곤 플라이트 모작
- 길건너 친구들
- input system
- 유니티 GUI
- 연습
- 유니티 UI
- 드래곤 플라이트
- Photon Fusion
- 모작
- meta xr
- 유니티
- ChatGPT
- meta
- CGV
- 멀티플레이
- 개발
- 앱 배포
- 포트폴리오
- Today
- Total
EasyCastleUNITY
길건너 친구들 모작 개발일지6 (Ray를 통한 장애물 검출 및 이동금지) 본문
길건너 친구들 모작 개발일지6 (Ray를 통한 장애물 검출 및 이동금지)
EasyCastleT 2023. 10. 4. 17:17추석 연휴 동안 푹 쉬고 다시 모작 개발을 시작했습니다.
여러분은 푹 쉬셨나요?
푹 쉬셨기를 바라며,
이제 다시 모작 개발 시작해보겠습니다.
이동제한
여태까지는 미봉책으로 Clamp를 사용하여, 플레이어의 움직임 범위를 제한했습니다.
하지만, 실제 길건너 친구들에서는, 특정 범위를 넘어가면, 죽는 기믹이 있습니다.
따라서, 이동 위치를 직접적으로 제한하는 Clamp는 사용하지 않는 것이 맞습니다.
그래서 자세히 살펴본 결과, 게임 내에서는 위에 나온 강 말고는, 모두 여러가지 장애물을 통해
이동을 막아둔 것을 확인 할 수 있었습니다.
장애물의 특징은, 플레이어 앞에 장애물이 있을 경우, 그 위치로 이동하지 못한다는 점이 있습니다.
그래서 캐릭터가 본인 앞에 장애물이 있다는 것을 인식하고 있어야 합니다.
여러 방법을 고려해보고, 캐릭터 정면을 향해, Ray를 발사하여, 검출하는 방법으로 만들어 보기로 하였습니다.
먼저 플레이어의 앞으로 레이를 발사할 위치를 빈 오브젝트로 만들고, 플레이어의 자식으로 만들어 주었습니다.
그리고 이 위치에서 레이를 발사하고, Obstacle이라는 Layer를 가지고 있는 오브젝트만을 검출하도록 만들어주었습니다.
그리고, isFrontObstacle이라는 bool 변수를 선언하고, 앞에 장애물이 있다면 true 없다면 false로 되도록 만들었습니다.
기존의 만들어둔 이동부분의 조건으로서 isFrontObstalce을 추가하여
false인 경우에만 움직이도록, 즉 앞에 장애물이 없을때만 움직이도록 했습니다.
위에 결과처럼, 잘 작동하는 것을 볼 수 있습니다.
사용한 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Player : MonoBehaviour
{
#region Delegate
private System.Action<Vector3> onCanceled;
public System.Action onCoin;
public System.Action onPoint;
public System.Action onDie;
#endregion
private Vector3 moveDir;
private Animator anim;
#region PlayerMove
private PlayerInput playerInput;
private InputActionMap mainActionMap;
private InputAction moveAction;
#endregion
#region State
private bool isDie = false;
private bool isMoveAble = false;
public bool IsMoveAble { get => isMoveAble; set => isMoveAble = value; }
public bool IsOut { get => isOut; set => isOut = value; }
#endregion
[SerializeField] private float turnSpeed = 3.0f;
[SerializeField] private Transform raySpot;
[SerializeField] private bool isFrontObstacle = false;
private bool isOnRaft = false;
private bool isOut = false;
// Start is called before the first frame update
void Start()
{
this.anim = GetComponent<Animator>();
this.PlayerMoveInit();
this.PlayerMove();
}
// Update is called once per frame
void Update()
{
this.PlayerRotation();
this.RayHitObstacle();
if (this.isOut) this.isDie = true;
}
private void PlayerMoveInit()
{
this.playerInput = this.GetComponent<PlayerInput>();
this.mainActionMap = this.playerInput.actions.FindActionMap("Player");
this.moveAction = this.mainActionMap.FindAction("Move");
}
private void PlayerMove()
{
this.moveAction.performed += (context) =>
{
if (this.isMoveAble && this.isDie == false)
{
Vector2 dir = context.ReadValue<Vector2>();
this.moveDir = new Vector3(dir.x, 0, dir.y);
//애니메이션 실행
this.anim.SetTrigger("Input");
}
};
this.moveAction.canceled += (context) =>
{
if (this.isMoveAble && this.isDie == false)
{
this.anim.SetTrigger("Idle");
this.onCanceled(moveDir);
}
};
this.onCanceled = (moveDir) =>
{
if (this.isFrontObstacle == false)
{
this.anim.SetTrigger("Jump");
// StartCoroutine(CoMove(this.transform.position,moveDir));
this.transform.position = this.transform.position + (moveDir.normalized);
}
};
}
private void PlayerRotation()
{
if (this.moveDir != Vector3.zero && this.isDie == false)
{
Quaternion rot = Quaternion.LookRotation(this.moveDir);
this.transform.rotation = Quaternion.Slerp(this.transform.rotation, rot,
Time.deltaTime * this.turnSpeed);
}
}
private void RayHitObstacle()
{
Ray ray = new Ray(this.raySpot.position, this.raySpot.forward);
Debug.DrawRay(ray.origin, ray.direction * 1f, Color.red);
int layerMask = 1 << LayerMask.NameToLayer("Obstacle");
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 1f, layerMask))
{
this.isFrontObstacle = true;
}
else
{
this.isFrontObstacle = false;
}
}
private Vector3 ClampPosition(Vector3 position)
{
return new Vector3(Mathf.Clamp(position.x, -4.0f, 6f),
position.y, position.z);
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Ground"))
{
if (this.moveDir == Vector3.forward && other.gameObject.GetComponent<GroundPlayerCheck>().IsCheck==false)
{
this.onPoint();
}
}
else if (other.CompareTag("Coin"))
{
this.onCoin();
}
else if (other.CompareTag("Vehicle"))
{
this.onDie();
this.isDie = true;
this.anim.SetTrigger("DieByCar");
}
else if (other.CompareTag("Raft"))
{
this.isOnRaft=true;
this.transform.SetParent(other.transform);
if (this.moveDir == Vector3.forward && other.gameObject.GetComponent<RaftAnimControl>().IsCheck==false)
{
this.onPoint();
}
}
if (other.CompareTag("Water") && this.isOnRaft==false)
{
this.onDie();
this.isDie = true;
this.anim.SetTrigger("DieByWater");
}
}
private void OnTriggerExit(Collider other)
{
if (other.CompareTag("Raft"))
{
this.isOnRaft = false;
this.transform.SetParent(null);
this.transform.position = new Vector3((int)this.transform.position.x,
this.transform.position.y, this.transform.position.z);
}
}
}
이렇게 장애물을 통해, 플레이어의 이동을 제한하는 방법 구현을 완료했습니다.
'3D 프로젝트 개발 일지(Crossy Road, 한글명: 길건너 친구들)' 카테고리의 다른 글
길건너 친구들 모작 개발일지8 (플레이어 점수 측정, UI 표시) (0) | 2023.10.05 |
---|---|
길건너 친구들 모작 개발일지 7(장애물 랜덤하게 생성) (1) | 2023.10.04 |
길건너 친구들 모작 개발일지5 (뗏목 만들기 및 뗏목 탑승) (0) | 2023.09.27 |
길건너 친구들 모작 개발일지4 (코인 랜덤 생성) (0) | 2023.09.26 |
길건너 친구들 모작 개발일지3 (맵 구성 및 무한 맵 생성) (1) | 2023.09.26 |