2 - Movimentação Point and Click + new input system
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:
- movimentação em point and click usando o novo input system da unity2D;
- poder clicar apenas em objetos escolhidos para ser o chão;
- o personagem poder passar pela frente e atrás do mesmo objeto e sua imagem se corrigir de acordo com a perspectiva isométrica;
- fazer o personagem desviar sozinho de qualquer obstáculo que esteja no caminho.
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:
- criar um float da velocidade que de para alterar no inspector; criar um Vector2 para o destino; e criar um bool para o movimento;
[SerializedField] private float speed; private Vector2 destination; private bool isMoving = false; void Start(){ isMoving = false; }
- no método chamado depois de clicar: salvar a posição do mouse; definir o destino como a posição do mouse; bool isMoving = true;
if (ctx.performed){ Vector2 mousePosition = Mouse.current.position.ReadValue(); Vector2 worldPosition = Camera.main.ScreenToWorldPoint(mousePosition); destination = worldPosition; isMoving = true; }
- no Update: mover a posição do player até o destino usando o MoveTowards; parar quando a posição for igual a do destino;
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:
- Primeiro criei 2 Sorting Layers: uma para objetos que sempre ficão atras do jogador, "BackLayer"; e uma para objetos que o player poderá passar atrás e na frente, "MiddleLayer";
- Organizei os objetos da hierarquia em pastas diferentes, conforme cada Sorting Layer;
- O player deverá receber a Sorting Layer "MiddleLayer", mas ficará fora da pasta dos objetos.
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.
Souls' Memories
Status | In development |
Author | ViiKi |
Genre | Puzzle |
Tags | Ghosts, Narrative, Point & Click |
More posts
- 4 - Interagindo com ItensJul 25, 2024
- 3 - Movimentação Point and Click + ObstáculosJul 17, 2024
- 1 - Unity e git lfs (large file storage)Jul 10, 2024
Leave a comment
Log in with itch.io to leave a comment.