unity脚本逻辑问题

如何在unity中实现,物体在一个长宽都为10米的平面边缘逆时针移动,输入1移动1格子,输入4移动4格子。


using System;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 移动方向
/// </summary>
public enum MoveDirection
{
    X,
    OppositeX,
    Z,
    OppositeZ
}

public sealed class CreateMap : MonoBehaviour
{
    [SerializeField] private Vector3 startPoint;
    [SerializeField] private Vector3 endPoint;
    [SerializeField] private float length;
    [SerializeField] private float width;
    [SerializeField] private GameObject player;
    [SerializeField] private InputField input;

    /// <summary>
    /// 每步的米数
    /// </summary>
    private const sbyte Step = 1;

    private void Awake()
    {
        startPoint = player.transform.position;
        length = startPoint.z - endPoint.z;
        width = startPoint.x - endPoint.x;
        input.onEndEdit.AddListener((value) =>
        {
            if (!sbyte.TryParse(value, out var result)) 
                return;
            switch (result)
            {
                case 1:
                    Move(result);
                    break;
                case 4:
                    Move(result);
                    break;
                default:
                    Debug.LogError("输入错误");
                    break;
            }
        });
    }

    private void Move(sbyte step)
    {
        var playerPos = player.transform.position;
        //OppositeZ
        if (Math.Abs(playerPos.x - startPoint.x) < 0.05f)
        {
            if (playerPos.z + endPoint.z - step * Step >= -length)
            {
                playerPos.z -= step * Step;
            }
            else
            {
                var (x, z) = CalculateMove(step, MoveDirection.OppositeZ, playerPos);
                playerPos.x += x * Step;
                playerPos.z -= z * Step;
            }
        }
        //Z
        else if (Math.Abs(playerPos.x - endPoint.x) < 0.05f)
        {
            if (playerPos.z + startPoint.z + step * Step <= length)
            {
                playerPos.z += step * Step;
            }
            else
            {
                var (x, z) = CalculateMove(step, MoveDirection.Z, playerPos);
                playerPos.x -= x * Step;
                playerPos.z += z * Step;
            }
        }
        //OppositeX
        else if (Math.Abs(playerPos.z - startPoint.z) < 0.05f)
        {
            if (playerPos.x + startPoint.x - step * Step >= -width)
            {
                playerPos.x -= step * Step;
            }
            else
            {
                var (x, z) = CalculateMove(step, MoveDirection.OppositeX, playerPos);
                playerPos.x -= x * Step;
                playerPos.z -= z * Step;
            }
        }
        //X
        else if (Math.Abs(playerPos.z - endPoint.z) < 0.05f)
        {
            if (playerPos.x + endPoint.x + step * Step <= width)
            {
                playerPos.x += step * Step;
            }
            else
            {
                var (x, z) = CalculateMove(step, MoveDirection.X, playerPos);
                playerPos.x += x * Step;
                playerPos.z += z * Step;
            }
        }

        player.transform.position = playerPos;
    }

    /// <summary>
    /// 移动后超出界限重新计算
    /// </summary>
    /// <param name="step"></param>
    /// <param name="direction">该移动的方向</param>
    /// <param name="playerPos"></param>
    /// <returns>返回x或z该移动的距离</returns>
    private (float x, float z) CalculateMove(sbyte step, MoveDirection direction, Vector3 playerPos)
    {
        var stepToMove = step;
        while (true)
        {
            switch (direction)
            {
                case MoveDirection.X:
                    if (!(step * Step + playerPos.x > endPoint.x)) return (step, stepToMove - step);
                    step--; //xStep
                    direction = MoveDirection.X;
                    continue;
                case MoveDirection.OppositeX:
                    if (!(-step * Step + playerPos.x < startPoint.x)) return (step, stepToMove - step);
                    step--; //xStep
                    direction = MoveDirection.OppositeX;
                    continue;
                case MoveDirection.Z:
                    if (!(step * Step + playerPos.z > startPoint.z)) return (stepToMove - step, step);
                    step--; //zStep
                    direction = MoveDirection.Z;
                    continue;
                case MoveDirection.OppositeZ:
                    if (!(-step * Step + playerPos.z < endPoint.z)) return (stepToMove - step, step);
                    step--; //zStep
                    direction = MoveDirection.OppositeZ;
                    continue;
                default:
                    throw new ArgumentOutOfRangeException(nameof(direction), direction, null);
            }
        }
    }
}

img

img

代码有点长且注释不全,隔了一天就忘记自己写了啥,算法这块我不会,就用最简单的数学知识实现了,脚本挂哪个物体都行,参数设置好就行。

看起来有点像只有一个圈的飞行棋,在所有可能的点位放置都放置一个GameObject,然后在脚本中添加List链表字段,然后在场景编辑器中将所有GameObject依次放入链表中序列化存储,运行时记录当前位置索引,使用Input.GetKeyDown(KeyCode.Alpha1)获取键盘输入,索引根据输入增加,超出长度则回到链表开头,然后将需要移动的物体的Positon改变为对应GameObject的位置。
最好是使用算法来控制移动的位置而不是使用序列化链表,但需要一定的编程基础和Unity知识,建议先找些教程看。