1) Gizmo
: Scene뷰에서 게임 오브젝트와 관련된 그래픽으로 시각적 디버깅을 위해 사용된다. 설정된 Gizmo는 뷰에 보이게 된다.
1) RaycastHit의 인스턴스 hit을 통해 대상의 Component를 가져올 수 있다.
Interactable interactable = hit.collider.GetComponent<Interactable>();
2) 대상에 Interactable component가 있으면 focus로 지정
if (interactable != null)
{
SetFocus(interactable);
}
void SetFocus(Interactable newFocus)
{
focus = newFocus;
}
3) 마우스 왼클릭 시 focus 초기화
void RemoveFocus()
{
focus = null;
}
1) agent의 움직임을 담당하는 PlayerMotor.cs의 Update 안에서 target이 null이 아닐 때 agent를 target으로 이동시킨다.
public void FollowTarget(Interactable newTarget)
{
agent.stoppingDistance = newTarget.radius * .8f;
target = newTarget.transform;
}
public void StopFollowingTarget()
{
agent.stoppingDistance = 0f;
target = null;
}
private void Update()
{
if(target != null)
{
agent.SetDestination(target.position);
}
}
2) SetFocus함수 안에 FollowTarget함수를 추가한다.
motor.FollowTarget(newFocus);
1) 플레이어가 Target을 따라가는 동안 에이전트의 기본 회전을 끈다. (회전 속도가 너무 느림)
agent.updateRotation = false
2) agent를 회전하게 하는 FaceTarget함수를 만든다.
Quaternion.LookRotation(Vector3 forward)
: forward를 쳐다 보는 회전 값을 쿼터니언으로 리턴한다. Vector3를 인수로 넘기면 인수로 넘긴 Vector3의 방향을 쳐다보는 회전값(쿼터니언)을 리턴한다.
: 따라서 벡터의 뺄셈으로 목적지 위치좌표 - 출발지 위치좌표 해주어 필요한 방향과 거리를 나타낼 벡터를 구해주는 것이 좋다. 그리고 매개변수로 넘기기.
Quaternion Slerp(Quaternion a, Quaternion b, float t);
: a와 b 벡터 사이를 t 퍼센트로 보간한 결과를 쿼터니언으로 리턴한다.
: 부드러운 회전을 만들 때 쓰임
void FaceTarget()
{
Vector3 direction = (target.position - transform.position).normalized;
Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z));
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * .5f);
}
1) Player가 focus했을 때 Interactable Object에서 정보 받는 함수 만들기
public void OnFocused(Transform playerTransform)
{
isFocus = true;
player = playerTransform;
hasInteracted = false;
}
public void OnDefocused()
{
isFocus = false;
player = null;
hasInteracted = false;
}
2) Interacable Object가 focus되었고, 이미 Interacted된게 아니라면 Interaction하기
private void Update()
{
if (isFocus && !hasInteracted)
{
float distance = Vector3.Distance(player.position, transform.position);
if (distance <= radius)
{
Debug.Log("Interact");
hasInteracted = true;
}
}
}
3) Interaction 함수 만들기
virtual, override
: 상속할 클래스의 메서드에 virtual, 상속받는 클래스의 메서드에 override 키워드를 붙인다.
: 상속받는 자식이 부모와 이름은 같지만 다른 기능의 메서드를 사용하고 싶을 때 사용
public virtual void Interact()
{
// This method is meant to be overwritten
Debug.Log("Interacting with " + transform.name);
}
4) Player가 focus할 때 Interacable Object의 그래픽을 바라보게 하기 (상자를 열 때 상자의 앞을 보게 하기)
: 그래픽을 위한 Transform 변수 만들어 기존의 focus 함수들에 있는 transform 대체해주기
다른 오브젝트 컴포넌트 (스크립트)의 properties에 대한 접근이 필요할 때 쓰이는 방법은
1. GetCompoenent 함수 사용
2. public instance 만들기
3. static instance 생성하기 (후에 배울 예정)
이 있다. 의자는 세 번째 추천하는데, 이것을 복습할 때에 차이들을 공부할 것이다. 또 그 외의 방법들도 찾아보면 좋겠다.
Interaction을 구현할 때, 관련 함수의 사용과 예외설정 부분에서 헷갈리는 게 있다. 강의에서는
1. Interactable 스크립트의 변수에는
1) 플레이어가 오브젝트에 interaction 유무를 확인하는 isFocus
2) 오브젝트가 interaction 중인가를 확인하는 hasInteracted
가 있다.
오브젝트는 항상 isFocus && !hasInteracted일때 Interact 함수를 실행한다. (동시에 hasInteracted를 true로 바꿈)
2. PlayerController 스크립트의 변수에는
1) Interaction하는 오브젝트인 focus가 있다.
오브젝트가 우클릭되면, SetFocus 함수를 실행하고, SetFocus 함수의 알고리즘은 다음과 같다.
OnFocused가 실행되면 조건에 따라 변수의 설정이 바뀌지만, 결국 Interact된다고 생각하면 쉽다.
초기조건 (오브젝트에 마우스 우클릭)이 false인 마우스가 왼클릭 될 (플레이어가 지정한 곳으로 이동하는) 경우에는 RemoveFocus 함수를 실행한다.
RemoveFocus 함수는 간단한데, 이전에 상호작용 한 오브젝트가 있다면 오브젝트를 OnDeFocused하고, focus 변수를 null로 초기화하고 플레이어의 오브젝트 following을 해제한다.
정리하고 나면 이해가 되지만 상당히 복잡한 구조인데, 다음에 Interaction을 구현할 때, 이를 참고하여 더 간단하게 만들 수 있을 지 생각해 보아야겠다.