Taking a moment to refine pathfinding.
Here’s the pathfinding package I am using. Simple Tile Pathfinding 2d
The path seems to be drawing correctly (the pathfinding dot sprite now has the same vertical offset that block tile pivots do), but the player sprite position is funky, ~it seems to be a tile too low~ it’s randomly all over. I’m going to try centering each click target to the middle of the grid square and see if it helps.
Hierarchy
PlayerObject
Grid
Nav Tilemap (where path blocking tiles are added- usually invisible)
Ground Tilemap (this is just visually where you walk)
Stacks Tilemap (this is aboveground where blocks get added)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using DoodleStudio95;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
//block stacking
public Tile block;
public Tile pathStop;
public bool hasBlock;
public Tilemap stackMap;
public Tilemap navMap;
//input and pathfinding
MouseInput mouseInput;
public Tilemap groundMap;
private Rigidbody2D rb;
private Vector3 destination;
private Vector3 nextPoint;
private SimplePF2D.Path path;
private bool isStationary = true;
public DoodleAnimationFile animFrontRight;
public DoodleAnimationFile animBackRight;
public GameObject reticuleObject;
// UI
public GameObject actionModal;
public Text actionText;
public GameObject hud;
public Text debt;
public Sprite hudHasBlock;
public Sprite hudNoBlock;
//sprite
public GameObject pivotObject;
[SerializeField] private float movementSpeed;
private void Awake()
{
mouseInput = new MouseInput();
}
private void OnEnable()
{
mouseInput.Enable();
}
private void OnDisable()
{
mouseInput.Disable();
}
void Start()
{
destination = transform.position;
mouseInput.Mouse.MouseLeftClick.performed += _ => MouseLeftClick();
mouseInput.Mouse.MouseRightClick.performed += _ => MouseRightClick();
SimplePathFinding2D pf = GameObject.Find("Grid").GetComponent<SimplePathFinding2D>();
path = new SimplePF2D.Path(pf);
rb = GetComponent<Rigidbody2D>();
nextPoint = Vector3.zero;
//Vector3Int ImagePosition = new Vector3Int(3, -2, 1);
//map.SetTile(ImagePosition, block);
//Debug.Log(map.GetSprite(ImagePosition));
}
public void OpenModal(Vector3 position)
{
if (actionModal != null)
{
actionModal.transform.position = position; // this is placing the ui element in the bottom left corner for some reason
Debug.Log("set action ui window at " + position);
actionModal.SetActive(true);
if (hasBlock == false)
{
actionText.text = "Get";
} else
{
actionText.text = "Put";
}
}
// how do we check if mouse is over UI?
}
public void CloseModal()
{
if (actionModal != null)
{
actionModal.SetActive(false);
}
}
public void getBlock(Vector3Int gridPosition)
{
if (hasBlock == false)
{
//take block from ground - need to elaborate on this for taking from stacks
groundMap.SetTile(gridPosition, null);
//pathfinding adjustment - this should be now done by "collider tilemaps" in STPF2d but its not working
Vector3Int pathStopPosition = new Vector3Int(gridPosition.x, gridPosition.y, 0);
navMap.SetTile(pathStopPosition, pathStop); // add a pathfinding barrier
Debug.Log("setting nav obstacle at " + pathStopPosition);
}
}
public void putBlock(Vector3Int gridPosition)
{
if (hasBlock == true)
{
//put block on ground- need to elaborate on this for adding to obelisk stacks
gridPosition.z = 1;
stackMap.SetTile(gridPosition, block);
//pathfinding adjustment - this should be now done by "collider tilemaps" in STPF2d but its not working
Vector3Int pathStopPosition = new Vector3Int(gridPosition.x, gridPosition.y, 0);
navMap.SetTile(pathStopPosition, pathStop); // add a pathfinding barrier
Debug.Log("setting nav obstacle at " + pathStopPosition);
}
}
public void toggleBlock()
{
if (hasBlock == false)
{
hasBlock = true;
hud.GetComponent<Image>().sprite = hudHasBlock;
} else
{
hasBlock = false;
hud.GetComponent<Image>().sprite = hudNoBlock;
}
}
void flipWalkingSprite(Vector3 destination)
{
// should this be a coroutine?
DoodleAnimator animator = pivotObject.GetComponent<DoodleAnimator>();
SpriteRenderer playerRenderer = pivotObject.GetComponent<SpriteRenderer>();
if (transform.position.y < destination.y)
{
animator.ChangeAnimation(animBackRight);
}
else
{
animator.ChangeAnimation(animFrontRight);
}
if (transform.position.x < destination.x)
{
playerRenderer.flipX = false;
}
else
{
playerRenderer.flipX = true;
}
path.CreatePath(transform.position, destination); // here's where we create the path
}
private void MouseLeftClick()
{
Vector2 mousePosition = mouseInput.Mouse.MousePosition.ReadValue<Vector2>();
mousePosition = Camera.main.ScreenToWorldPoint(mousePosition);
Vector3Int gridPosition = groundMap.WorldToCell(mousePosition);
DoodleAnimator animator = pivotObject.GetComponent<DoodleAnimator>();
SpriteRenderer playerRenderer = pivotObject.GetComponent<SpriteRenderer>();
if (groundMap.HasTile(gridPosition))
{
destination = mousePosition;
flipWalkingSprite(destination);
}
}
private void MouseRightClick()
{
Vector2 mousePosition = mouseInput.Mouse.MousePosition.ReadValue<Vector2>();
mousePosition = Camera.main.ScreenToWorldPoint(mousePosition);
Vector3Int gridPosition = groundMap.WorldToCell(mousePosition);
DoodleAnimator animator = GetComponent<DoodleAnimator>();
SpriteRenderer playerRenderer = GetComponent<SpriteRenderer>();
if (groundMap.HasTile(gridPosition))
{
// open ui to show action- "get stone/ put stone" (it's unimodal depending on if you have a stone)
OpenModal(mousePosition);
flipWalkingSprite(mousePosition);
if (hasBlock == false)
{
getBlock(gridPosition);
toggleBlock();
} else
{
putBlock(gridPosition);
toggleBlock();
}
}
}
// how to get cell center
//Vector3Int cellPosition = tilemap.WorldToCell(transform.position);
//transform.position = tilemap.GetCellCenterWorld(cellPosition);
// Update is called once per frame
void FixedUpdate()
{
// The player object has an inner gameobject called pivotObject to adjust the pivot since you can't do it on
//a doodleanimator like you can a sprite.
SpriteRenderer playerRenderer = pivotObject.GetComponent<SpriteRenderer>();
if (Vector3.Distance(transform.position, destination) > 0.1f)
{
if (path.IsGenerated())
{
reticuleObject.SetActive(true);
reticuleObject.transform.position = destination;
if (isStationary)
{
if (path.GetNextPoint(ref nextPoint))
{
rb.velocity = nextPoint - transform.position;
rb.velocity = rb.velocity.normalized;
rb.velocity *= movementSpeed;
isStationary = false;
}
else
{
rb.velocity = Vector3.zero;
isStationary = true;
reticuleObject.SetActive(false);
}
}
else
{
Vector3 delta = nextPoint - transform.position;
if (delta.magnitude <= 0.2f)
{
rb.velocity = Vector3.zero;
isStationary = true;
reticuleObject.SetActive(false);
}
}
}
else
{
rb.velocity = Vector3.zero;
isStationary = true;
}
}
}
}