public class PlayerController : MonoBehaviour
{
void Update()
{
if (Input.GetKey(KeyCode.W)) //앞
{
transform.position += new Vector3(0.0f, 0.0f, 1.0f);
}
if(Input.GetKey(KeyCode.S)) //뒤
{
transform.position -= new Vector3(0.0f, 0.0f, 1.0f);
}
if (Input.GetKey(KeyCode.A)) //좌
{
transform.position -= new Vector3(1.0f, 0.0f, 0.0f);
}
if (Input.GetKey(KeyCode.D)) //우
{
transform.position += new Vector3(1.0f, 0.0f, 0.0f);
}
}
}
Player 객체에 PlayerController.cs 붙여준다.
⚠️ 하지만 지금은 너무 빨리 움직인다!!
-> Update()는 한 프레임당 호출되는 함수로 60프레임의 게임이 돈다면 1/60초마다 포지션을 이동하는 함수가 실행되므로 매우 빠를 수밖에 없다.
💡 이전 프레임과 지금 프레임의 시간차를 구해서 동작하도록 해야함 -> Time.deltaTime;을 사용한다.
Time.deltaTime;
: 지난 프레임이 이후 경과된 시간
⚠️ 이러면 또 너무 느려지기 때문에 상수값 speed 변수를 선언하고 각 포지션 이동값에 곱해서 속도를 맞춰준다.
public class PlayerController : MonoBehaviour
{
[SerializeField] float _speed = 10.0f;
void Update()
{
if (Input.GetKey(KeyCode.W))
{
transform.position += new Vector3(0.0f, 0.0f, 1.0f) * Time.deltaTime * _speed;
}
if(Input.GetKey(KeyCode.S))
{
transform.position -= new Vector3(0.0f, 0.0f, 1.0f) * Time.deltaTime * _speed;
}
if (Input.GetKey(KeyCode.A))
{
transform.position -= new Vector3(1.0f, 0.0f, 0.0f) * Time.deltaTime * _speed;
}
if (Input.GetKey(KeyCode.D))
{
transform.position += new Vector3(1.0f, 0.0f, 0.0f) * Time.deltaTime * _speed;
}
}
}
: Private으로 선언된 필드를 Unity Inspector 창에서 제어할 수 있도록 해주는 기능
(Public으로 선언해도 Inspector에서 제어할 수 있지만 외부 접근도 가능하기 때문에 보안에 취약하다)
Unity에 내재되어 있는 'Vector3.방향'을 넣어서 코드의 가독성을 높이자!
public class PlayerController : MonoBehaviour
{
[SerializeField] float _speed = 10.0f;
void Update()
{
if (Input.GetKey(KeyCode.W))
{
//transform.position += new Vector3(0.0f, 0.0f, 1.0f) * Time.deltaTime * _speed;
transform.position += Vector3.forward * Time.deltaTime * _speed;
}
if(Input.GetKey(KeyCode.S))
{
//transform.position -= new Vector3(0.0f, 0.0f, 1.0f) * Time.deltaTime * _speed;
transform.position -= Vector3.back * Time.deltaTime * _speed;
}
if (Input.GetKey(KeyCode.A))
{
//transform.position -= new Vector3(1.0f, 0.0f, 0.0f) * Time.deltaTime * _speed;
transform.position -= Vector3.left * Time.deltaTime * _speed;
}
if (Input.GetKey(KeyCode.D))
{
//transform.position += new Vector3(1.0f, 0.0f, 0.0f) * Time.deltaTime * _speed;
transform.position += Vector3.right * Time.deltaTime * _speed;
}
}
}
⚠️ 만약 Player의 Transform.Rotate값을 조절해서 Player가 바라보는 방향을 바꾼 다음 현재 코드를 실행시키면, Player가 바라보는 방향이 '앞'이 되는 것이 아니라, World좌표 기준으로 '앞, 뒤, 좌, 우'가 움직여서 매우 부자연스러운 움직임이 발생한다;;
: Local 좌표 -> World 좌표로
public class PlayerController : MonoBehaviour
{
[SerializeField] float _speed = 10.0f;
void Update()
{
if (Input.GetKey(KeyCode.W))
{
transform.position += transform.TransformDirection(Vector3.forward * Time.deltaTime * _speed);
}
if(Input.GetKey(KeyCode.S))
{
transform.position -= transform.TransformDirection(Vector3.back * Time.deltaTime * _speed);
}
if (Input.GetKey(KeyCode.A))
{
transform.position -= transform.TransformDirection(Vector3.left * Time.deltaTime * _speed);
}
if (Input.GetKey(KeyCode.D))
{
transform.position += transform.TransformDirection(Vector3.right * Time.deltaTime * _speed);
}
}
}
ㄴ 이렇게 오브젝트의 움직임 좌표계를 변경시켜주면 오브젝트가 바라보고 있는 방향이 '앞'이 된다.
: 오브젝트가 바라보는 방향인 Local을 기준으로 연산하기 때문에 Translate(Local좌표 기준의 연산)을 해도 된다.
public class PlayerController : MonoBehaviour
{
[SerializeField] float _speed = 10.0f;
void Update()
{
if (Input.GetKey(KeyCode.W))
{
transform.Translate(Vector3.forward * Time.deltaTime * _speed);
}
if(Input.GetKey(KeyCode.S))
{
transform.Translate(Vector3.back * Time.deltaTime * _speed);
}
if (Input.GetKey(KeyCode.A))
{
transform.Translate(Vector3.left * Time.deltaTime * _speed);
}
if (Input.GetKey(KeyCode.D))
{
transform.Translate(Vector3.right * Time.deltaTime * _speed);
}
}
}