이동발판을 이용하는 로직을 짤때 해당 발판의 자식으로 들어가 캐릭터를 같이 이동 시켰다.
MovePlatform .cs
private void OnCollisionEnter(Collision collision)
{
if (TargetLayerMask == (TargetLayerMask | 1 << collision.gameObject.layer))
{
collision.transform.SetParent(transform);
}
}
private void OnCollisionExit(Collision collision)
{
if (TargetLayerMask == (TargetLayerMask | 1 << collision.gameObject.layer))
{
collision.transform.SetParent(null);
}
}
이 코드는 충돌한 오브젝트를 검사해서 이동발판 오브젝트에 자식으로 설정해서 캐릭터와 이동발판이 같이 이동하는 로직으로 만들었다.
하지만 [Potal]게임처럼 물체를 잡고 움직이는 현상에 이와 같은 동작을 취했을때는 잡힌 물체의 Rigidbody로 인해 물리연산으로 인해 잡힌 물체가 원하는 위치에 있지 않았기에 키네마틱을 켜고 설정하였다.
하지만 키네마틱은 설정시에는 velocity나 force를 사용할순 있지만 외부의 물리충돌연산을 하지 않기에 다른 오브젝트들과의 충돌이 없어진게 문제였다.
물리충돌 연산은 필요하지만 , 잡힌 물체의 위치값이 계속 고정되어있기를 원했다.
튜터님께 질문해서 받은 답변은
<잡힌 물체의 좌표를 계속 갱신해줘야한다.> 였다.
방법 1. 잡힌 물체가 플레이어를 계속 따라다니게 하는 방법
방법 2. 잡힌 물체의 위치를 고정 좌표를 만든뒤 Player가 이동시 좌표를 갱신 하는 방법
두가지 방법이 있었다.
나는 방법1을 이용하여 그냥 고정좌표를 만들어주었고, 해당 좌표를 계속 갱신해주었다.
ObjectGrip.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.HID;
public class ObjectGrip : MonoBehaviour
{
[Header("Object Grip")]
public Transform GripPivotTr; //잡고있는 오브젝트의 위치
private bool isGrip; //오브젝트를 잡고있는상태
private GameObject target; //잡고있는 오브젝트의 정보
public LayerMask GripObjectLayerMask;
public float GripDistance = 3.0f;
//잡힌 물체의 좌표를 계속 갱신해줘야한다.
//이유 : 잡힌 물체의 물리 충돌연산을 해야되려면 잡힌 위치를 계속 갱신하고 키네마닉을 꺼야만 사용이 물리연산이 가능하기 때문
//방법 1. 잡힌 물체가 플레이어를 계속 따라다니게 하는 방법
//방법 2. 잡힌 물체의 위치를 고정 좌표를 만든뒤 Player가 이동시 좌표를 갱신 하는 방법
private void Update()
{
//방법 2. 잡힌 물체의 위치를 고정 좌표를 만든뒤 Player가 이동시 따라가게 하는 방법
if (isGrip)
{
target.transform.position = GripPivotTr.position + new Vector3 (0,1,0);
}
}
public void OnGrip(InputAction.CallbackContext context)
{
if (context.phase == InputActionPhase.Started)
{
if (!isGrip && target == null)
{
Ray ray = Camera.main.ScreenPointToRay(new Vector2(Screen.width / 2, Screen.height / 2));
RaycastHit hit;
if (Physics.Raycast(ray, out hit, GripDistance, GripObjectLayerMask))
{
target = hit.transform.gameObject;
if(target.transform.TryGetComponent(out Rigidbody targetRigid))
{
targetRigid.freezeRotation = true;
}
isGrip = true;
}
}
else if (isGrip && target != null)
{
isGrip = false;
if (target.transform.TryGetComponent<Rigidbody>(out Rigidbody targetRigid))
{
targetRigid.freezeRotation = false;
}
target = null;
}
}
}
}