Ok, I condensed all my scripts so I just have a MasterPlayerScript that goes on the player object, and a MasterGridScript that goes on the grid object. The only thing in the grid script is setting grid width and height. This is what I have for my player script as of now:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEngine.InputSystem;
public class MasterPlayerScript : MonoBehaviour
{
private Vector2 movement;
private float deadZone = 0.5f;
private int inputx, inputy;
private int initCellx, initCelly;
//Test variables (what I think I will need)
public int cellx, celly, targetx, targety;
bool moving = false;
int worldx, worldy, worldTargetx, worldTargety;
Vector3Int origPos, targetPos;
float moveSpeed = 0.8f;
private Rigidbody2D rb;
private Animator anim;
private string currentState;
[SerializeField] Tilemap obstacles;
bool blockedHori, blockedVert;
TileBase targetTile;
MasterGridScript masterGridScript;
[SerializeField] GameObject grid;
int[,] playerPos;
private int newx, newy;
// Start is called before the first frame update
void Start()
{
masterGridScript = grid.GetComponent<MasterGridScript>();
anim = GetComponent<Animator>();
SpawnObjectOnGrid();
cellx = initCellx;
celly = initCelly;
for (int x = 0; x < masterGridScript.gridWidth; x++)
{
for (int y = 0; y < masterGridScript.gridHeight; y++)
{
if (cellx == x && celly == y)
{
playerPos = new int[x, y];
}
}
}
}
// Update is called once per frame
void Update()
{
DirInput();
if (!moving)
{
if (inputx != 0 || inputy != 0)
{
PlayerCellMove(inputx, inputy);
Debug.Log("Target X: " + targetx + " Target Y: " + targety);
worldTargetx = targetx;
worldTargety = targety;
targetPos = new Vector3Int(worldTargetx, worldTargety, 0);
StartCoroutine(Move(targetPos));
}
//Facing horizontally
if (inputy == 0)
{
if (inputx == 1)
{
ChangeAnimationState("WalkRight");
}
else if (inputx == -1)
{
ChangeAnimationState("WalkLeft");
}
}
//Facing vertically
if (inputx == 0)
{
if (inputy == 1)
{
ChangeAnimationState("WalkUp");
}
else if (inputy == -1)
{
ChangeAnimationState("WalkDown");
}
}
//Stopping animation when idle
if (inputx == 0 && inputy == 0)
{
if (currentState == "WalkRight")
{
ChangeAnimationState("IdleRight");
}
if (currentState == "WalkLeft")
{
ChangeAnimationState("IdleLeft");
}
if (currentState == "WalkUp")
{
ChangeAnimationState("IdleUp");
}
if (currentState == "WalkDown")
{
ChangeAnimationState("IdleDown");
}
}
//Preventing moonwalking
if (currentState == "WalkRight" && inputx == -1)
{
ChangeAnimationState("WalkLeft");
}
if (currentState == "WalkLeft" && inputx == 1)
{
ChangeAnimationState("WalkRight");
}
if (currentState == "WalkUp" && inputy == -1)
{
ChangeAnimationState("WalkDown");
}
if (currentState == "WalkDown" && inputy == 1)
{
ChangeAnimationState("WalkUp");
}
if (currentState == "IdleRight" && inputx == -1)
{
ChangeAnimationState("WalkLeft");
}
if (currentState == "IdleLeft" && inputx == 1)
{
ChangeAnimationState("WalkRight");
}
if (currentState == "IdleUp" && inputy == -1)
{
ChangeAnimationState("WalkDown");
}
if (currentState == "IdleDown" && inputy == 1)
{
ChangeAnimationState("WalkUp");
}
}
}
private void OnMovement(InputValue value)
{
movement = value.Get<Vector2>();
}
void TargetCheck(Vector3Int posToCheck)
{
targetTile = obstacles.GetTile(posToCheck);
//Debug.Log(targetTile);
if (targetTile != null)
{
if (posToCheck.x != cellx)
{
blockedHori = true;
} else { blockedHori = false; }
if (posToCheck.y != celly)
{
blockedVert = true;
} else { blockedVert = false; }
Debug.Log("Blocked Horizontally: " + blockedHori + " Blocked Vertically: " + blockedVert);
}
}
IEnumerator Move(Vector3Int newPos)
{
TargetCheck(newPos);
if (blockedHori && blockedVert)
{
yield break;
}
moving = true;
if (blockedHori)
{
newPos.x = worldx;
}
if (blockedVert)
{
newPos.y = worldy;
}
while ((newPos - transform.position).sqrMagnitude > Mathf.Epsilon)
{
transform.position = Vector3.MoveTowards(transform.position, newPos, moveSpeed * Time.fixedDeltaTime);
yield return null;
}
transform.position = newPos;
cellx = targetx;
celly = targety;
moving = false;
}
void ChangeAnimationState(string newState)
{
if (currentState == newState) return;
anim.Play(newState);
currentState = newState;
}
private void DirInput()
{
//Get horizontal input as a -1 - 1
if (movement.x > deadZone)
{
inputx = 1;
}
else if (movement.x < -deadZone)
{
inputx = -1;
}
else if (Mathf.Abs(movement.x) < deadZone)
{
inputx = 0;
}
//Get vertical input as a -1 - 1
if (movement.y > deadZone)
{
inputy = 1;
}
else if (movement.y < -deadZone)
{
inputy = -1;
}
else if (Mathf.Abs(movement.y) < deadZone)
{
inputy = 0;
}
}
private void SpawnObjectOnGrid()
{
Transform t = transform;
Vector3 pos = t.position;
initCellx = (int)pos.x;
initCelly = (int)pos.y;
}
public void PlayerCellMove(int deltax, int deltay)
{
newx = cellx + deltax;
newy = celly + deltay;
playerPos = new int[newx, newy];
Debug.Log("Player Grid Target: (" + newx + ", " + newy + ")");
for (int x = 0; x < masterGridScript.gridWidth; x++)
{
for (int y = 0; y < masterGridScript.gridHeight; y++)
{
if (playerPos == new int[x, y])
{
targetx = x;
targety = y;
}
}
}
Debug.Log("To X: " + targetx + " To Y: " + targety);
}
}
The problem I am now having is that somewhere between the two debugs in the PlayerCellMove function something goes wrong…the first debug there accurately returns newx and newy as the correct coordinates for each move. However the second debug returns targetx and targety both as 0; this results in my player immediately moving to (0, 0) upon receiving input, no matter where they start. After they reach (0, 0) they can’t move at all. I feel like I’m very close but I’m missing something crucial. At least it’s now cleaner/just one script to post lol
EDIT: Got it working - instead of using for loops I ended up just storing x and y grid positions as their own variables. For anyone who might come across this and is interested in the topic, here’s what I landed on:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEngine.InputSystem;
public class MasterPlayerScript : MonoBehaviour
{
//Variables related to input
private Vector2 movement;
private float deadZone = 0.5f;
private int inputx, inputy;
//Variables that read initial player position
private int initCellx, initCelly;
//Current and target cells' positions
public int cellx, celly, targetx, targety;
//Status of moving or not
bool moving = false;
//World position in terms of Transform coordinates
int worldTargetx, worldTargety;
//World position as a Vector3
Vector3Int targetPos;
//Adjustable player move speed
float moveSpeed = 0.8f;
//Variables related to animation
private Animator anim;
private string currentState;
//Player sidling status (important for prevention of skipping openings in walls)
private bool sidlingHori, sidlingVert;
//Game object where non-passable obstacles are placed
[SerializeField] Tilemap obstacles;
//Status of being blocked by obstacles/edges horizontally, vertically, and diagonally
bool blockedHori, blockedVert, blockedDiag;
//Slots for getting tiles on target positions
TileBase targetTileDiag, targetTileHori, targetTileVert;
//Grid game object that holds grid dimensions
MasterGridScript masterGridScript;
[SerializeField] GameObject grid;
// Start is called before the first frame update
void Start()
{
//Script that holds grid dimensions
masterGridScript = grid.GetComponent<MasterGridScript>();
//Animator for player
anim = GetComponent<Animator>();
//Function that gets player's initial grid position
SpawnObjectOnGrid();
//Reads initial grid position and sets as current on launch
cellx = initCellx;
celly = initCelly;
}
// Update is called once per frame
void Update()
{
//Script that converts input to -1, 0, or 1 for each axis
DirInput();
//If on the grid not moving or between steps
if (!moving)
{
//If receiving input
if (inputx != 0 || inputy != 0)
{
//Adjust target cell and world position
targetx = cellx + inputx;
targety = celly + inputy;
worldTargetx = targetx;
worldTargety = targety;
targetPos = new Vector3Int(worldTargetx, worldTargety, 0);
//Check to see if movement to target is possible
CheckForEdges(targetx, targety);
CheckForObstacles(worldTargetx, worldTargety);
//If movement is not possible, what to do
if (blockedHori)
{
targetx = cellx;
if (targety != celly)
{
sidlingVert = true;
sidlingHori = false;
}
}
if (blockedVert)
{
targety = celly;
if (targetx != cellx)
{
sidlingHori = true;
sidlingVert = false;
}
}
if (blockedDiag && !blockedHori && !blockedVert)
{
if (sidlingHori)
{
targetx = cellx;
sidlingHori = false;
}
if (sidlingVert)
{
targety = celly;
sidlingVert = false;
}
}
//Update target world position
worldTargetx = targetx;
worldTargety = targety;
targetPos = new Vector3Int(worldTargetx, worldTargety, 0);
//Function to execute the movement
StartCoroutine(Move(targetPos));
}
//Facing horizontally
if (inputy == 0)
{
if (inputx == 1)
{
ChangeAnimationState("WalkRight");
}
else if (inputx == -1)
{
ChangeAnimationState("WalkLeft");
}
}
//Facing vertically
if (inputx == 0)
{
if (inputy == 1)
{
ChangeAnimationState("WalkUp");
}
else if (inputy == -1)
{
ChangeAnimationState("WalkDown");
}
}
//Stopping animation when idle
if (inputx == 0 && inputy == 0)
{
if (currentState == "WalkRight")
{
ChangeAnimationState("IdleRight");
}
if (currentState == "WalkLeft")
{
ChangeAnimationState("IdleLeft");
}
if (currentState == "WalkUp")
{
ChangeAnimationState("IdleUp");
}
if (currentState == "WalkDown")
{
ChangeAnimationState("IdleDown");
}
}
//Preventing moonwalking
if (currentState == "WalkRight" && inputx == -1)
{
ChangeAnimationState("WalkLeft");
}
if (currentState == "WalkLeft" && inputx == 1)
{
ChangeAnimationState("WalkRight");
}
if (currentState == "WalkUp" && inputy == -1)
{
ChangeAnimationState("WalkDown");
}
if (currentState == "WalkDown" && inputy == 1)
{
ChangeAnimationState("WalkUp");
}
}
}
private void OnMovement(InputValue value)
{
movement = value.Get<Vector2>();
}
IEnumerator Move(Vector3Int newPos)
{
moving = true;
while ((newPos - transform.position).sqrMagnitude > Mathf.Epsilon)
{
transform.position = Vector3.MoveTowards(transform.position, newPos, moveSpeed * Time.fixedDeltaTime);
yield return null;
}
transform.position = newPos;
cellx = targetx;
celly = targety;
blockedHori = false;
blockedVert = false;
blockedDiag = false;
moving = false;
}
void CheckForEdges(int tx, int ty)
{
if (!blockedHori)
{
if (tx < 0 || tx > masterGridScript.gridWidth)
{
blockedHori = true;
}
}
if (!blockedVert)
{
if (ty < 0 || ty > masterGridScript.gridHeight)
{
blockedVert = true;
}
}
}
void CheckForObstacles(int tx, int ty)
{
// targetTile = obstacles.GetTile(target);
targetTileHori = obstacles.GetTile(new Vector3Int(tx, celly, 0));
targetTileVert = obstacles.GetTile(new Vector3Int(cellx, ty, 0));
targetTileDiag = obstacles.GetTile(new Vector3Int(tx, ty, 0));
if (!blockedHori && targetTileHori != null)
{
blockedHori = true;
}
if (!blockedVert && targetTileVert != null)
{
blockedVert = true;
}
if (!blockedDiag && targetTileDiag != null)
{
blockedDiag = true;
}
}
void ChangeAnimationState(string newState)
{
if (currentState == newState) return;
anim.Play(newState);
currentState = newState;
}
private void DirInput()
{
//Get horizontal input as a -1, 0, or 1
if (movement.x > deadZone)
{
inputx = 1;
}
else if (movement.x < -deadZone)
{
inputx = -1;
}
else if (Mathf.Abs(movement.x) < deadZone)
{
inputx = 0;
}
//Get vertical input as a -1, 0, or 1
if (movement.y > deadZone)
{
inputy = 1;
}
else if (movement.y < -deadZone)
{
inputy = -1;
}
else if (Mathf.Abs(movement.y) < deadZone)
{
inputy = 0;
}
}
private void SpawnObjectOnGrid()
{
Transform t = transform;
Vector3 pos = t.position;
initCellx = (int)pos.x;
initCelly = (int)pos.y;
}
}