Как переместить Pacman в автоматическом Unity2d через путь?C#

Место общения программистов C#
Ответить
Anonymous
 Как переместить Pacman в автоматическом Unity2d через путь?

Сообщение Anonymous »

Перемещение Pacman с помощью Keys работает отлично. pong. < /p>
Этот метод должен обрабатывать автоматический метод. Я также проверяю, чтобы избежать обратного движения, чтобы Пакман всегда двигался вперед. < /p>
void HandleAutoInputDirection()
{
// Define direction priority
Vector2Int[] directions = new Vector2Int[]
{
Vector2Int.right,
-Vector2Int.up,
Vector2Int.left,
-Vector2Int.down
};

// Try all directions except the reverse of the current moveDir
foreach (var dir in directions)
{
// Skip reversing back to where we came from
if (dir == -moveDir)
continue;

Vector2Int nextGrid = currentGrid + dir;

if (IsWalkable(nextGrid))
{
nextDir = dir;
break;
}
}

// Only change moveDir if we stopped or hit a wall
if (moveDir == Vector2Int.zero && IsWalkable(currentGrid + nextDir))
{
moveDir = nextDir;
targetPos = GridToWorld(currentGrid + moveDir);
UpdateFacingDirection();
}
}
< /code>
Используя его в Update () < /p>
void Update()
{
if (!handleInputDirectinManualAuto)
{
HandleManualInputDirection();
}
else
{
HandleAutoInputDirection();
}

if (moveDir != Vector2Int.zero)
{
float step = moveSpeed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, targetPos, step);

if (Vector3.Distance(transform.position, targetPos) < 0.001f)
{
currentGrid += moveDir;

textCurrentGridValue.text = currentGrid.ToString();

int width = layout[0].Length;

// Tunnel wrap logic
if (currentGrid.x = width - 1)
{
currentGrid.x = 0;
transform.position = GridToWorld(currentGrid);
targetPos = GridToWorld(currentGrid + moveDir);
}

if (IsWalkable(currentGrid + nextDir))
{
moveDir = nextDir;
targetPos = GridToWorld(currentGrid + moveDir);
UpdateFacingDirection();
}
else if (IsWalkable(currentGrid + moveDir))
{
targetPos = GridToWorld(currentGrid + moveDir);
UpdateFacingDirection();
}
else
{
moveDir = Vector2Int.zero;
}
}
}

// Pellet eating logic
for (int i = allPellets.Count - 1; i >= 0; i--)
{
var pellet = allPellets;
if (pellet == null) continue;

if (Vector2.Distance(transform.position, pellet.transform.position) < 0.1f)
{
pellet.OnEaten();
allPellets.RemoveAt(i);
break;
}
}
}

Я создал короткое видео, показывающее проблему в Unity при запуске игры и настройке Bool для перемещения Pacman Automatic.using System.Collections.Generic;
using System.IO;
using System.Linq;
using TMPro;
using UnityEngine;

public class PacManMover : MonoBehaviour
{
public float moveSpeed = 5f;
public float distancePacmanFromPellet;
public bool handleInputDirectinManualAuto = false;
public TextMeshProUGUI textCurrentGridValue;

private Vector2Int currentGrid;
private Vector2Int moveDir = Vector2Int.zero;
private Vector2Int nextDir = Vector2Int.zero;
private Vector3 targetPos;

private Dictionary waypointDict = new();
private Vector3 mazeOffset;
private string[] layout;
private float tileSize;
private StreamWriter logWriter;
private List allPellets = new();

void Start()
{
MazeGenerator mazeGen = FindFirstObjectByType();
layout = MazeGenerator.layout;
tileSize = mazeGen.tileSize;
mazeOffset = mazeGen.offset;
logWriter = new StreamWriter(@"D:\PacManMoveLog.txt", false);
Log("=== PacMan Start ===");

var waypoints = GameObject.FindGameObjectsWithTag("Waypoint");
foreach (var wp in waypoints)
{
Vector2Int gridPos = WorldToGrid(wp.transform.position);
if (!waypointDict.ContainsKey(gridPos))
waypointDict[gridPos] = wp.transform;
}

currentGrid = WorldToGrid(transform.position);
moveDir = Vector2Int.zero;
nextDir = Vector2Int.zero;
targetPos = transform.position;

Log($"Start Grid: {currentGrid} -> {transform.position}");

allPellets = Object.FindObjectsByType(FindObjectsSortMode.None).ToList();
}

void Update()
{
if (!handleInputDirectinManualAuto)
{
HandleManualInputDirection();
}
else
{
HandleAutoInputDirection();
}

if (moveDir != Vector2Int.zero)
{
float step = moveSpeed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, targetPos, step);

if (Vector3.Distance(transform.position, targetPos) < 0.001f)
{
currentGrid += moveDir;

textCurrentGridValue.text = currentGrid.ToString();

int width = layout[0].Length;

// Tunnel wrap logic
if (currentGrid.x = width - 1)
{
currentGrid.x = 0;
transform.position = GridToWorld(currentGrid);
targetPos = GridToWorld(currentGrid + moveDir);
}

if (IsWalkable(currentGrid + nextDir))
{
moveDir = nextDir;
targetPos = GridToWorld(currentGrid + moveDir);
UpdateFacingDirection();
}
else if (IsWalkable(currentGrid + moveDir))
{
targetPos = GridToWorld(currentGrid + moveDir);
UpdateFacingDirection();
}
else
{
moveDir = Vector2Int.zero;
}
}
}

// Pellet eating logic
for (int i = allPellets.Count - 1; i >= 0; i--)
{
var pellet = allPellets;
if (pellet == null) continue;

if (Vector2.Distance(transform.position, pellet.transform.position) < 0.1f)
{
pellet.OnEaten();
allPellets.RemoveAt(i);
break;
}
}
}

void HandleManualInputDirection()
{
if (Input.GetKeyDown(KeyCode.UpArrow)) nextDir = -Vector2Int.up;
if (Input.GetKeyDown(KeyCode.DownArrow)) nextDir = -Vector2Int.down;
if (Input.GetKeyDown(KeyCode.LeftArrow)) nextDir = Vector2Int.left;
if (Input.GetKeyDown(KeyCode.RightArrow))
{
nextDir = Vector2Int.right;
Debug.Log($"Trying right → Grid: {currentGrid + Vector2Int.right}, Walkable: {IsWalkable(currentGrid + Vector2Int.right)}");
}

if (moveDir == Vector2Int.zero && IsWalkable(currentGrid + nextDir))
{
moveDir = nextDir;
targetPos = GridToWorld(currentGrid + moveDir);
UpdateFacingDirection();
}
}

void HandleAutoInputDirection()
{
// Define direction priority
Vector2Int[] directions = new Vector2Int[]
{
Vector2Int.right,
-Vector2Int.up,
Vector2Int.left,
-Vector2Int.down
};

// Try all directions except the reverse of the current moveDir
foreach (var dir in directions)
{
// Skip reversing back to where we came from
if (dir == -moveDir)
continue;

Vector2Int nextGrid = currentGrid + dir;

if (IsWalkable(nextGrid))
{
nextDir = dir;
break;
}
}

// Only change moveDir if we stopped or hit a wall
if (moveDir == Vector2Int.zero && IsWalkable(currentGrid + nextDir))
{
moveDir = nextDir;
targetPos = GridToWorld(currentGrid + moveDir);
UpdateFacingDirection();
}
}

void UpdateFacingDirection()
{
if (moveDir == Vector2Int.left)
{
transform.localScale = new Vector3(-1f, 1f, 1f);
transform.rotation = Quaternion.Euler(0, 0, 0f);
}
else if (moveDir == Vector2Int.right)
{
transform.localScale = new Vector3(1f, 1f, 1f);
transform.rotation = Quaternion.Euler(0, 0, 0f);
}
else if (moveDir == -Vector2Int.up) // Up
{
transform.localScale = new Vector3(1f, 1f, 1f);
transform.rotation = Quaternion.Euler(0, 0, 90f);
}
else if (moveDir == -Vector2Int.down) // Down
{
transform.localScale = new Vector3(1f, 1f, 1f);
transform.rotation = Quaternion.Euler(0, 0, -90f);
}
}

bool IsWalkable(Vector2Int gridPos)
{
int height = layout.Length;
int width = layout[0].Length;

int x = gridPos.x;
int y = gridPos.y;

if (y < 0 || y >= height)
return false;

if (x < 0) x = width - 1;
else if (x >= width) x = 0;

char c = layout[y][x];
return c == '.' || c == ' ' || c == 'P';
}

Vector2Int WorldToGrid(Vector3 worldPos)
{
float x = (worldPos.x - mazeOffset.x + tileSize / 2f) / tileSize;
float y = (mazeOffset.y - worldPos.y + tileSize / 2f) / tileSize;
return new Vector2Int(Mathf.RoundToInt(x), Mathf.RoundToInt(y));
}

Vector3 GridToWorld(Vector2Int gridPos)
{
int width = layout[0].Length;

int x = gridPos.x;
int y = gridPos.y;

if (x < 0) x = width - 1;
else if (x >= width) x = 0;

float worldX = x * tileSize;
float worldY = -y * tileSize;
return new Vector3(worldX, worldY, -1f) + mazeOffset;
}

void Log(string msg)
{
Debug.Log(msg);
if (logWriter != null)
logWriter.WriteLine($"[{System.DateTime.Now:HH:mm:ss}] {msg}");
}

void OnApplicationQuit()
{
if (logWriter != null)
{
logWriter.Close();
logWriter = null;
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/796 ... h-the-path
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»