Posted July 25, 2024 by ViiKi
#unity #movement #itens #interaction
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. 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;
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.
using UnityEngine.InputSystem; using ScriptableObjectArchitecture; public LayerMask groundLayer; public LayerMask obstacleLayer; [SerializeField] private Vector2GameEvent walkToDestination;
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:
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
. . . 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:
NomeDoEvento.Raise(variável); walkToDestination.Raise(hitGround.point);
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:
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. :)