먼저 플레이어의 이동을 구현해 보겠습니다.

float moveX = Input.GetAxisRaw("Horizontal"); //앞뒤 w일 경우 +1 s 일 경우 -1
float moveZ = Input.GetAxisRaw("Vertical"); //좌우 a일 경우 -1 d 일 경우 +1
Vector3 move = new Vector3(moveX, 0, moveZ).normalized; //이동 방향 벡터 계산
transform.Translate(move * runSpeed * Time.deltaTime, Space.World); //이동처리
주석에 달아놓은 것 처럼 Horizontal은 키보드 키에서 W 와 S 키 입니다.
Vertical은 A와 D 입니다. "Horizontal"과 "Vertical"은 유니티에서 제공하는 Input Manager 축 이름입니다.
GetAxisRaw 같은 경우에 입력을 받는 즉시 값이 바로 바뀌게 됩니다. 즉, 부드러운 이동 없이 즉각적으로 반응하기에 게임 플레이에 안성맞춤이라고 할 수 있습니다.
GetAxis 같은 경우는 부드럽게 보간이 되므로 천천히 가속/감속하게 됩니다.
해당 코드를 보면 wasd 와 같은 이동 방향의 키가 입력이 되면 1 또는 -1이 입력이 되어 해당 타겟이 이동하게 됩니다. 여기서 대각으로 이동하게 되면 문제가 발생하게 됩니다.
해당 키를 입력해 (1, 0, 1) 가 된다면 대각 이동의 값이 루트2가 된다는 건데 루트2는 1.414의 근사치를 가지기 때문에 1보다 크게 됩니다, 즉 .normalized는 대각이동이 다른 이동보다 더 빠른 속도를 가지게 되어 1로 보강해주는 역할을 합니다.
해당 코드를 보면 이미 달리기 변수를 만들어 놓은게 보일 수 있습니다.
달리기는 간단하게 조건문으로 완성했습니다.
이 함수의 동작 시점은 키를 누르는 순간 한 번만 실행하게 됩니다.
예시로 공격 버튼을 눌렀을 때가 될 수 있습니다.
이 함수는 키를 누르고 있는 동안 계속 실행하게 됩니다. 달리는 상태라든지 스태미나 감소를 이용할때 사용할 수 있습니다.
이 함수는 키를 뗄 때 한 번만 실행하게 됩니다.

위에서 부터 천천히 살펴보면 Vector3.zero는 타겟이 움직이지 않았을때를 말합니다. 즉, 플레이어가 움직였을때만 실행하게 되는 조건문이 됩니다.
회전(Rotation)을 표현하는 수학적 구조체입니다.
Unity에서의 회전값은 Euler(오일러) 각도 대신 Quaternion으로 저장됩니다.
유니티에서는 그냥 회전을 다루는 데이터 구조 라고 이해하시면 됩니다.
Quaternion targetRotation = Quaternion.LookRotation(move)
이동하는 방향을 바라보는 회전값을 생성하게 됩니다.
이동방향(move)를 바라보는 회전 상태를 Quaternion 형태로 계산해서 targetRotation에 저장하게 됩니다.
Slerp = Spherical Linear Interpolation (구면 선형 보간)
Slerp는 부드럽게 회전하기 위한 보간 함수입니다.
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
이 구문은 현재 회전(transform.rotation)에서 목표 회전(targetRotation)으로 rotationSpeed 속도 만큼 회전시켜라! 라는 의미입니다.
위처럼 사용하지 않고
transform.rotation = targetRotation;
이런식으로 구현했으면 캐릭터가 순산적으로 확 돌아가 버립니다.