Posted July 12, 2024 by ViiKi
#unity #input #movement
Antes de começar a fazer a primeira mecânica do jogo, a movimentação do personagem, anotei pontos decisivos de como eu queria que fosse o resultado final. Decidir esses pontos é importante para pensar na lógica do script e saber por qual ponto começar.
Os principais pontos envolvendo a movimentação do personagem que eu quero no meu jogo são:
1. Após baixar o pacote do input system e criar uma pasta no Assets para as coisas relacionadas ao player, criei um input action chamado "Player" e configurei da seguinte forma:
Action Map "Player" -> Action "Move", com Action Type como um "Button" -> binding sendo o botão esquerdo do mouse.
obs: recomendo ativar o Auto-Save.
Inicialmente usei o input referenciando ele dentro do script, como no exemplo abaixo:
MouseInput input; void Awake(){ input = new MouseInput(); } void Start(){ input.Player.Move.performed += _ => Metodo(); }
Mas resolvi fazer de outra forma (para deixar o script mais "limpo"), criando no player um componente chamado "Player Input":
obs: colocar as informações conforme o input action e action map escolhidos; alterar o Behaviour para Invoke Unity Events; colocar o script e o método a ser chamado.
E no script apenas referenciar o uso do input system e fazer o método no seguinte padrão:
using UnityEngine.InputSystem; . . . public void OnClick(InputAction.CallbackContext ctx){ if (ctx.performed) //resto do metodo... }
Antes de colocar mais coisas no script de movimento, é bom revisar se o player tem um Rigibody2D e um Collider2D. Como o jogo tem perspectiva isométrica (parecido com um jogo top-down), é necessário colocar o Gravity Scale em 0 e marcar o Freeze Rotation.
A lógica do script de movimento se resume em:
[SerializedField] private float speed; private Vector2 destination; private bool isMoving = false; void Start(){ isMoving = false; }
if (ctx.performed){ Vector2 mousePosition = Mouse.current.position.ReadValue(); Vector2 worldPosition = Camera.main.ScreenToWorldPoint(mousePosition); destination = worldPosition; isMoving = true; }
if (isMoving){ transform.position = Vector2.MoveTowards(transform.position, destination, speed * Time.deltaTime); if ((Vector2)transform.position == destination) isMoving = false; }
2. Criei uma layer "Ground" para colocar em todos os objetos considerados como chão; é usado o RaycastHit2D para verificar se essa layer foi clicada. O RaycastHit2D funciona verificando se o click "colidiu" em algo com a layer Ground, mas as outras variáveis usadas, direction e distance, são colocadas como um numero "zerado", pois nesse caso em especifico não são necessárias para a verificação.
[SerializeField] private LayerMask groundLayer; . . . public void OnClick(InputAction.CallbackContext ctx){ if (ctx.performed){ Vector2 mousePosition = Mouse.current.position.ReadValue(); Vector2 worldPosition = Camera.main.ScreenToWorldPoint(mousePosition); RaycastHit2D hitGround = Physics2D.Raycast(worldPosition, Vector2.zero, Mathf.Infinity, groundLayer); if (hitGround.collider != null){ destination = hitGround.point; isMoving = true; . . .
No inspector: no script dentro do player, é necessário atribuir a layer que seria a "groundLayer"; nos objetos considerados "chão", colocar a layer correta e um Collider2D.
3. Existe várias formas de lidar com a perspectiva e ordem dos sprites, mas resolvi escolher a forma mais fácil sem precisar fazer um script:
Para que os objetos da MiddleLayer se arrumem de acordo com a perspectiva isométrica:
Edit -> Project Settings -> Graphics -> mudar o Transparency Sort Mode para Custom Axis -> mudar o Transparency Sort Axis para 0, 1, 0.
Última coisa importante para revisar é a posição do Collider2D e do Pivot da imagem, pois em um jogo isométrico estes precisam estar no "pé" do player; e também é necessário fazer essas mudanças nos objetos em cena. Para alterar o Pivot da imagem:
Acessar o Import Settings, clicando na imagem que está em alguma pasta no Assets -> alterar o Pivot para Custom -> alterar o local do Pivot -> clicar em Apply -> no componente Sprite Renderer, alterar o Sprite Sort Point para Pivot.
O próximo devlog será focado em explicar como fazer o personagem desviar sozinho de obstáculos.