4 - Interagindo com Itens


A primeira coisa que eu fiz após terminar de fazer a movimentação foi acrescentar a mecânica "ir até interagivel", que seria clicar em qualquer coisa interativa e fazer o player ir até um local designado. Isso é usado quando um objeto/npc é clicado e o player se locomove até este sem precisar clicar no chão. Os seguintes passos para essa mecânica são:

  1. configuração do prefab do item na cena; criação do script ItemData_Scene;
  2. criação do script PlayerInteractions;
  3. criação do Vector2 Game Event e o Vector2 Event Listener;
  4. modificações no script PlayerMovement;


1. Criei um prefab de item genérico para usar como referência. Este prefab contém mais 2 gameObjects, o InteractableArea e o ClickableArea, pois cada um tem um propósito diferente:

obs: os dois gameObjects têm o Collider com "Is Trigger" ativado;

  • o InteractableArea, com a Tag "InteractableArea", tem o propósito de indicar a área perto o suficiente para a interação;
  • o ClickableArea, com a Tag "Clickable" e Layer "Obstacle", tem o propósito de definir onde deve ser clicado para a interação;

No script ItemData_Scene é referenciado um bool e um Collider2D:

public bool isClose;
public Collider2D interactableArea;


2. Conforme aumenta as funcionalidades envolvendo o click do mouse resolvi colocar o método OnClick, que anteriormente estava no PlayerMovement, num script chamado "PlayerInteractions". 

Para ter melhor controle de todos os eventos e variáveis, eu gosto de usar um asset que se baseia na arquitetura de scriptable objects. Um exemplo dessa ferramenta é o salvamento de variáveis por fora de um script e, por causa disso, qualquer script pode ter acesso à essa mesma variável e mudar seu valor.

  • no script PlayerInteractions é referenciado um evento que passará um Vector2, o destino clicado, para o PlayerMovement receber;
using UnityEngine.InputSystem;
using ScriptableObjectArchitecture;
public LayerMask groundLayer;
public LayerMask obstacleLayer;
[SerializeField] private Vector2GameEvent walkToDestination;
  • é criado um OnTriggerEnter2D e um OnTriggerExit2D para a mudança do bool isClose;
private void OnTriggerEnter2D(Collider2D collision){
    if (collision.gameObject.CompareTag("InteractableArea")){
        collision.GetComponentInParent<ItemData_Scene>().isClose = true;
    }
}
private void OnTriggerExit2D(Collider2D collision){
    if (collision.gameObject.CompareTag("InteractableArea")){
        collision.GetComponentInParent<itemdata_scene>().isClose = false;
    }     
}

No método OnClick:

  •  RaycastHit2D hitObs é usado para verificar clicks na Layer obstacleLayer;
  • é primeiro verificado se foi clicado em um obstáculo e este tem uma Tag específica;

Se for este caso e o bool isClose == false

pegar o Collider2D do interactableArea -> pegar o centro do Collider2D do player -> usar ClosestPoint para conseguir o destino final

  • caso contrário é verificado se foi clicado no chão e não num obstáculo;
. . .
RaycastHit2D hitObs = Physics2D.Raycast(worldPosition, Vector2.zero, Mathf.Infinity, obstacleLayer);
if (hitObs.collider != null && hitObs.transform.gameObject.CompareTag("Clickable")){
    GameObject obj = hitObs.transform.gameObject;
    ItemData_Scene script = obj.GetComponentInParent<itemdata_scene>();
    if (script.isClose == false){
        Collider2D goToCollider = script.interactableArea;
        Collider2D playerCollider = GetComponentInChildren<collider2d>();
        Vector2 playerCenter = playerCollider.bounds.center;
        Vector2 point = goToCollider.ClosestPoint(playerCenter);
        walkToDestination.Raise(point);
    }
}
else if (hitGround.collider != null && hitObs.collider == null){
    walkToDestination.Raise(hitGround.point);
}       


3.  Este passo é apenas para quem tem interesse em conhecer a ferramenta SO Architecture citada acima.

Para criar o Vector2 Game Event:

em uma pasta escolhida, ir em Create -> Game Events -> Structs -> Vector2

O resultado fica assim:

  • Para enviar um evento é necessário arrastar ele para a sua referência no inspector e seu padrão é:

 NomeDoEvento.Raise(variável);    walkToDestination.Raise(hitGround.point);

  • Para usar um evento é necessário criar um componente Listener e atribuir o resultado:


4. Foi necessário mudanças no script PlayerMovement devido a exclusão do método OnClick.

Para usar a LayerMask obstacleLayer, que não existe mais no script:

  • criar uma referência para o script PlayerInteractions:  private PlayerInteractions playerInteractions;
  • no Start, atribuir seu valor:  playerInteractions = GetComponent<PlayerInteractions>();
  • usar a referência playerInteractions.obstacleLayer;

Para receber o Vector2 e salva-lo como destino final:

public void CheckObstacles(Vector2 target){
    destination = target;
. . .


A partir dessas mudanças é possivel começar o sistema de inventário.    :)

Leave a comment

Log in with itch.io to leave a comment.