Я делаю клон игры "Arrow Out". Я не уверен, что это вообще правильный путь, но я подумываю использовать штуковины, чтобы проверить, есть ли еще одна стрелка на пути нажатой стрелки. Прямо сейчас стрелки работают так, как ожидалось, но я хочу, чтобы нажатая кнопка находилась на своем месте, если на ее пути есть еще одна стрелка. Как мне это сделать? Сценарий стрелки выглядит следующим образом:
using System.Collections.Generic;
using UnityEngine;
public class Arrow : MonoBehaviour
{
public enum Direction { Up, Down, Left, Right }
[Header("Runtime settings (per-instance in Inspector)")]
[SerializeField] private Direction arrowDirection = Direction.Up;
[SerializeField] private Vector2Int gridPosition = Vector2Int.zero;
[SerializeField] private float moveTimerMax = 1f;
[Header("References")]
[SerializeField] private Transform arrowHead;
[SerializeField] private Transform arrowContainer;
private float moveTimer;
private bool moveInitialized;
// manual body parts (child components)
private List bodyParts = new List();
private List bodyGridPositions = new List();
private void Awake()
{
// preserve existing behaviour you wanted
moveTimer = 0f;
moveInitialized = false;
// gather body parts beneath the container in Hierarchy order
if (arrowContainer != null)
{
bodyParts.Clear();
foreach (var bp in arrowContainer.GetComponentsInChildren())
{
bodyParts.Add(bp);
}
// initialize body positions from inspector values on each part
bodyGridPositions.Clear();
for (int i = 0; i < bodyParts.Count; i++)
{
bodyParts[i].Init();
bodyGridPositions.Add(bodyParts[i].GetGridPosition());
}
}
// place head using localPosition relative to ArrowParent
if (arrowHead != null)
{
arrowHead.localPosition = GridToLocal(gridPosition);
}
else
{
// if no head ref assigned, assume this object acts as head
transform.localPosition = GridToLocal(gridPosition);
}
}
private void Update()
{
HandleTouch();
moveTimer += Time.deltaTime;
if (moveInitialized && moveTimer > moveTimerMax)
{
Vector2Int prevHead = gridPosition;
gridPosition += DirectionToVector(arrowDirection);
moveTimer -= moveTimerMax;
// shift body positions
if (bodyGridPositions.Count > 0)
{
bodyGridPositions.Insert(0, prevHead);
if (bodyGridPositions.Count > bodyParts.Count)
{
bodyGridPositions.RemoveAt(bodyGridPositions.Count - 1);
}
// apply positions & computed facing to each child body part
for (int i = 0; i < bodyParts.Count; i++)
{
var gridPos = bodyGridPositions[i];
// compute facing for this segment based on its next position
ArrowBodyPart.Direction dir = GetDirectionForBodySegment(i);
bodyParts[i].SetGridPosition(gridPos, dir);
}
}
// update head local position
if (arrowHead != null) arrowHead.localPosition = GridToLocal(gridPosition);
}
}
// compute local vector for grid coordinates (local to ArrowParent)
private Vector3 GridToLocal(Vector2Int g)
{
return new Vector3(g.x, g.y, 0f);
}
private ArrowBodyPart.Direction GetDirectionForBodySegment(int index)
{
// from = this segment pos, to = preceding pos
Vector2Int from = bodyGridPositions[index];
Vector2Int to = (index == 0) ? gridPosition : bodyGridPositions[index - 1];
Vector2Int delta = to - from;
if (delta == new Vector2Int(0, 1)) return ArrowBodyPart.Direction.Up;
if (delta == new Vector2Int(0, -1)) return ArrowBodyPart.Direction.Down;
if (delta == new Vector2Int(1, 0)) return ArrowBodyPart.Direction.Right;
if (delta == new Vector2Int(-1, 0)) return ArrowBodyPart.Direction.Left;
return bodyParts[index].GetDirection();
}
private void HandleTouch()
{
if (Input.touchCount == 0) return;
Touch touch = Input.GetTouch(0);
if (touch.phase != TouchPhase.Ended) return;
Vector3 worldPoint = Camera.main.ScreenToWorldPoint(touch.position);
Vector2 point2D = new Vector2(worldPoint.x, worldPoint.y);
RaycastHit2D hit = Physics2D.Raycast(point2D, Vector2.zero);
if (hit.collider != null)
{
// if arrowHead has collider and was hit, start movement
if (arrowHead != null && hit.collider.gameObject == arrowHead.gameObject)
{
moveInitialized = true;
}
else
{
foreach (var bp in bodyParts)
{
if (hit.collider.gameObject == bp.gameObject)
{
moveInitialized = true;
break;
}
}
}
}
}
private Vector2Int DirectionToVector(Direction d)
{
switch (d)
{
case Direction.Up: return new Vector2Int(0, 1);
case Direction.Down: return new Vector2Int(0, -1);
case Direction.Left: return new Vector2Int(-1, 0);
case Direction.Right: return new Vector2Int(1, 0);
default: return Vector2Int.zero;
}
}
}
Я понял, что стрелки следуют за движением змеи из аркадной игры Snake, поэтому я реализовал движение стрелок с помощью сетки. Если вы считаете, что есть лучший способ, предложите, пожалуйста!
Я делаю клон игры "Arrow Out". Я не уверен, что это вообще правильный путь, но я подумываю использовать штуковины, чтобы проверить, есть ли еще одна стрелка на пути нажатой стрелки. Прямо сейчас стрелки работают так, как ожидалось, но я хочу, чтобы нажатая кнопка находилась на своем месте, если на ее пути есть еще одна стрелка. Как мне это сделать? Сценарий стрелки выглядит следующим образом: [code]using System.Collections.Generic; using UnityEngine;
public class Arrow : MonoBehaviour { public enum Direction { Up, Down, Left, Right }
// gather body parts beneath the container in Hierarchy order if (arrowContainer != null) { bodyParts.Clear(); foreach (var bp in arrowContainer.GetComponentsInChildren()) { bodyParts.Add(bp); }
// initialize body positions from inspector values on each part bodyGridPositions.Clear(); for (int i = 0; i < bodyParts.Count; i++) { bodyParts[i].Init(); bodyGridPositions.Add(bodyParts[i].GetGridPosition()); } }
// place head using localPosition relative to ArrowParent if (arrowHead != null) { arrowHead.localPosition = GridToLocal(gridPosition); } else { // if no head ref assigned, assume this object acts as head transform.localPosition = GridToLocal(gridPosition); } }
// shift body positions if (bodyGridPositions.Count > 0) { bodyGridPositions.Insert(0, prevHead); if (bodyGridPositions.Count > bodyParts.Count) { bodyGridPositions.RemoveAt(bodyGridPositions.Count - 1); }
// apply positions & computed facing to each child body part for (int i = 0; i < bodyParts.Count; i++) { var gridPos = bodyGridPositions[i]; // compute facing for this segment based on its next position ArrowBodyPart.Direction dir = GetDirectionForBodySegment(i); bodyParts[i].SetGridPosition(gridPos, dir); } }
// update head local position if (arrowHead != null) arrowHead.localPosition = GridToLocal(gridPosition); } }
// compute local vector for grid coordinates (local to ArrowParent) private Vector3 GridToLocal(Vector2Int g) { return new Vector3(g.x, g.y, 0f); }
private ArrowBodyPart.Direction GetDirectionForBodySegment(int index) { // from = this segment pos, to = preceding pos Vector2Int from = bodyGridPositions[index]; Vector2Int to = (index == 0) ? gridPosition : bodyGridPositions[index - 1]; Vector2Int delta = to - from;
if (delta == new Vector2Int(0, 1)) return ArrowBodyPart.Direction.Up; if (delta == new Vector2Int(0, -1)) return ArrowBodyPart.Direction.Down; if (delta == new Vector2Int(1, 0)) return ArrowBodyPart.Direction.Right; if (delta == new Vector2Int(-1, 0)) return ArrowBodyPart.Direction.Left;
return bodyParts[index].GetDirection(); }
private void HandleTouch() { if (Input.touchCount == 0) return;
Touch touch = Input.GetTouch(0); if (touch.phase != TouchPhase.Ended) return;
Vector3 worldPoint = Camera.main.ScreenToWorldPoint(touch.position); Vector2 point2D = new Vector2(worldPoint.x, worldPoint.y); RaycastHit2D hit = Physics2D.Raycast(point2D, Vector2.zero);
if (hit.collider != null) { // if arrowHead has collider and was hit, start movement if (arrowHead != null && hit.collider.gameObject == arrowHead.gameObject) { moveInitialized = true; } else { foreach (var bp in bodyParts) { if (hit.collider.gameObject == bp.gameObject) { moveInitialized = true; break; } } } } }
private Vector2Int DirectionToVector(Direction d) { switch (d) { case Direction.Up: return new Vector2Int(0, 1); case Direction.Down: return new Vector2Int(0, -1); case Direction.Left: return new Vector2Int(-1, 0); case Direction.Right: return new Vector2Int(1, 0); default: return Vector2Int.zero; } } } [/code] Я понял, что стрелки следуют за движением змеи из аркадной игры Snake, поэтому я реализовал движение стрелок с помощью сетки. Если вы считаете, что есть лучший способ, предложите, пожалуйста!