unity复刻重装机兵(一)玩家的移动和跟随及障碍

复刻重装机兵玩家地图加载和移动及队列(队友战车)跟随,直接来吧!

移动测试

地图加载:

using Newtonsoft.Json;
using System;
using System.Linq;
using UnityEngine;

public class MapLoader : MonoBehaviour
{
    public GameObject cardPrefab; //预制体
    public float tileSize; // 地图格子大小
    public TextAsset json;

    Sprite[] sprites;

    public static int[,] mapdata;

    void Start()
    {
        // 将JSON字符串转换为Jagged Array
        int[][] jaggedArray = JsonConvert.DeserializeObject<int[][]>(json.ToString());
        // 加载精灵图集
        sprites = Resources.LoadAll<Sprite>("map");

        int rows = jaggedArray.Length;
        int cols = jaggedArray.Max(innerArray => innerArray.Length);

        int[,] mapArray = new int[rows, cols];

        mapdata = new int[cols, rows];//其他脚本引用使用

        for (int i = 0; i < rows; i++)
        {
            if (jaggedArray[i].Length > cols)
            {
                throw new InvalidOperationException("Jagged array has rows of different lengths.");
            }
            for (int j = 0; j < jaggedArray[i].Length; j++)
            {
                mapArray[i, j] = jaggedArray[i][j];
            }
        }
        LoadMap(mapArray);


    }

    void LoadMap(int[,] map)
    {
        //Debug.Log("列:"+map.GetLength(1) + "~~~" + "行:"+map.GetLength(0));
        for (int y = 0; y < map.GetLength(0); y++)
        {
            for (int x = 0; x < map.GetLength(1); x++)
            {
                int tileType = map[y, x];

                //Vector3 position = new Vector3(x, -y, 0) * tileSize;
                //让生成得地图坐标在第一象限
                Vector3 position = new Vector3(x, -y + map.GetLength(0) - 1, 0) * tileSize;
                string str = "map_"+ tileType.ToString();
                GameObject go = Instantiate(cardPrefab, position, Quaternion.identity);
                go.transform.SetParent(transform);

                foreach (Sprite s in sprites)
                {
                    if (s.name == str)
                    {
                        SpriteRenderer spriteRenderer = go.transform.GetComponent<SpriteRenderer>();
                        if (spriteRenderer != null)
                        {
                            spriteRenderer.sprite = s;
                        }
                        break;
                    }
                }
                go.SetActive(true);

            }
        }

        //反向映射地图障碍等,json数组从左上到右下计算下标,而地图左下到右上其初始位置(x=0,y=0)
        for (int x = 0; x < map.GetLength(1); x++)
        {
            for (int y = 0; y < map.GetLength(0); y++)
            {
                mapdata[x, y] = map[map.GetLength(0) - y - 1, x];
            }
        }

    }
}

玩家移动:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpriteAnim : MonoBehaviour
{
    public float moveSpeed = 3;
    Sprite[] sprites;

    string dir = "";//移动方向
    string currentStr = "DOWN";//默认方向
    public int tox = 1;
    public int toy = 1;

    Vector3 myCoordinate;//探路坐标

    float animTimer = 0;//动画帧
    bool isKeyUp = true;
    bool isMoving = false;

    int keyboard = 0;

    int STEP = 0;//移动步数,预留遇敌功能

    void Start()
    {
        transform.position = new Vector2(tox, toy);

        myCoordinate = transform.position;
        // 加载精灵图集
        sprites = Resources.LoadAll<Sprite>("主角1");

        transform.GetComponent<SpriteRenderer>().sprite = sprites[0];

        //tox = (int)myCoordinate.x;
        //toy = (int)myCoordinate.y;

    }

    void Update()
    {

        if (Input.GetKeyUp(KeyCode.S) || Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.D) || Input.GetKeyUp(KeyCode.W))
        {
            keyboard = 0;
            isKeyUp = true;
        }

        if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.S) 
            || Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.A)
             || Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.D)
             || Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.A)
             || Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.D)
             || Input.GetKey(KeyCode.A) && Input.GetKey(KeyCode.D))
        {
            isKeyUp = true;
            keyboard = 2;//同时有两个按键则返回
        }

        if (!isMoving)
        {
            if (Input.GetKey(KeyCode.W))
            {
                isKeyUp = false;
                dir = "UP";
            }
            else if (Input.GetKey(KeyCode.S))
            {
                isKeyUp = false;
                dir = "DOWN";
            }
            else if (Input.GetKey(KeyCode.A))
            {
                isKeyUp = false;
                dir = "LEFT";
            }
            else if (Input.GetKey(KeyCode.D))
            {
                isKeyUp = false;
                dir = "RIGHT";

            }
        }

        //多个方向同时按键则急停
        switch (dir)
        {
            case "UP":
                if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D) || Input.GetKeyUp(KeyCode.W))
                {
                    isKeyUp = true;
                }
                break;
            case "LEFT":
                if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.D) || Input.GetKeyUp(KeyCode.A))
                {
                    isKeyUp = true;
                }
                break;
            case "RIGHT":
                if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.W) || Input.GetKeyUp(KeyCode.D))
                {
                    isKeyUp = true;
                }
                break;
            case "DOWN":
                if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D) || Input.GetKeyUp(KeyCode.S))
                {
                    isKeyUp = true;
                }
                break;
        }


        if (myCoordinate == transform.position)
        {
            isMoving = false;

            switch (dir)
            {
                case "UP":
                    tox = (int)myCoordinate.x;
                    toy = (int)myCoordinate.y + 1;
                    break;
                case "LEFT":
                    tox = (int)myCoordinate.x - 1;
                    toy = (int)myCoordinate.y;
                    break;
                case "RIGHT":
                    tox = (int)myCoordinate.x + 1;
                    toy = (int)myCoordinate.y;
                    break;
                case "DOWN":
                    tox = (int)myCoordinate.x;
                    toy = (int)myCoordinate.y - 1;
                    break;
            }

            if (currentStr != dir)
            {
                if (keyboard < 2)
                {
                    Debug.Log("方向不同");
                    PlayerAnim(0);
                    currentStr = dir;
                }
            }

            //不可移动判断
            if (isKeyUp) return;
            //如果移动的范围超过地图的范围,则不可移动
            if (toy < 0 || tox < 0) return;
            if (toy > MapLoader.mapdata.GetLength(1) - 1 || tox > MapLoader.mapdata.GetLength(0) - 1) return;
            if (MapLoader.mapdata[tox, toy] == 29) return;
            if (MapLoader.mapdata[tox, toy] == 7) return;//增加水上无法移动
            animTimer = 0;
            myCoordinate = new Vector2(tox, toy);

            STEP++;
        }
        else
        {
            isMoving = true;
            transform.position = Vector2.MoveTowards(transform.position, myCoordinate, moveSpeed * Time.deltaTime);

            if (animTimer < moveSpeed)
            {
                animTimer += moveSpeed * Time.deltaTime;

                if (animTimer < 0.5f)
                {
                    PlayerAnim(1);
                }
                else
                {
                    PlayerAnim(0);
                }
            }

        }
    }

    void PlayerAnim(int stage)
    {
        //stage为0,各方向第一张精灵图,非移动状态
        //stage为1,各方向第二张精灵图,移动状态
        switch (dir)
        {
            case "UP":
                transform.GetComponent<SpriteRenderer>().sprite = sprites[12 + stage];
                break;
            case "LEFT":
                transform.GetComponent<SpriteRenderer>().sprite = sprites[4 + stage];
                break;
            case "RIGHT":
                transform.GetComponent<SpriteRenderer>().sprite = sprites[8 + stage];
                break;
            case "DOWN":
                transform.GetComponent<SpriteRenderer>().sprite = sprites[0 + stage];
                break;
        }
    }
}

队友跟随:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FollowHand : MonoBehaviour
{
    Sprite[] sprites;//精灵动画
    float animTimer = 0;//动画帧
    public Transform followObj;//跟随目标
    public float moveSpeed = 3;//这个速度和followObj的速度必须保持一致
    Vector3 movePoint;//下一个移动点
    Vector3 prevPos;//玩家移动插值帧
    Vector3 prevSelfPos;//自身移动插值帧
    string dir = "DOWN";//默认移动方向

    bool startFollow = false;//第一次如果是重合防止移动

    void Start()
    {        
        // 加载精灵图集
        sprites = Resources.LoadAll<Sprite>("主角1");
        transform.GetComponent<SpriteRenderer>().sprite = sprites[0];
        transform.position = followObj.position;
        prevPos = followObj.position;
        movePoint = transform.position;
    }

    private void Update()
    {
        Follow();
    }

    //精灵动画方向工具
    void PlayerAnim(int stage)
    {
        switch (dir)
        {
            case "UP":
                transform.GetComponent<SpriteRenderer>().sprite = sprites[12 + stage];
                break;
            case "LEFT":
                transform.GetComponent<SpriteRenderer>().sprite = sprites[4 + stage];
                break;
            case "RIGHT":
                transform.GetComponent<SpriteRenderer>().sprite = sprites[8 + stage];
                break;
            case "DOWN":
                transform.GetComponent<SpriteRenderer>().sprite = sprites[0 + stage];
                break;
        }
    }

    void Follow()
    {
        if (Vector3.Distance(transform.position, followObj.position) >= 1)
        {
            startFollow = true;
        }

        if (followObj && startFollow)
        {
            transform.position = Vector3.MoveTowards(transform.position, movePoint, moveSpeed * Time.deltaTime);

            float moveX = followObj.position.x - prevPos.x;
            float moveY = followObj.position.y - prevPos.y;

            float mX = transform.position.x - prevSelfPos.x;
            float mY = transform.position.y - prevSelfPos.y;
            
            if (mX > 0)
            {
                dir = "RIGHT";
            }
            if (mX < 0)
            {
                dir = "LEFT";
            }
            if (mY > 0)
            {
                dir = "UP";
            }
            if (mY < 0)
            {
                dir = "DOWN";
            }
            //跟随原理,unity玩家队列跟随
            if (Vector3.Distance(movePoint, transform.position) == 0)
            {
                if (Vector3.Distance(transform.position, followObj.position) != 1)
                {
                    animTimer = 0;
                    movePoint = new Vector3(Mathf.RoundToInt(prevPos.x), Mathf.RoundToInt(prevPos.y), 0);
                }
                if (Vector3.Distance(transform.position, followObj.position) > 1)
                {
                    if (transform.position.x == followObj.position.x && moveX == 0)
                    {
                        if (transform.position.y < followObj.position.y)
                        {
                            transform.position = new Vector3(followObj.position.x, followObj.position.y - 1, 0);
                        }
                        else if (transform.position.y > followObj.position.y)
                        {
                            transform.position = new Vector3(followObj.position.x, followObj.position.y + 1, 0);
                        }
                    }
                    if (transform.position.y == followObj.position.y && moveY == 0)
                    {
                        if (transform.position.x < followObj.position.x)
                        {
                            transform.position = new Vector3(followObj.position.x - 1, followObj.position.y, 0);
                        }
                        else if (transform.position.x > followObj.position.x)
                        {
                            transform.position = new Vector3(followObj.position.x + 1, followObj.position.y, 0);
                        }
                    }
                }
                prevPos = followObj.position;
                prevSelfPos = transform.position;
            }
            else
            {
                //移动就播放动画帧
                if (animTimer < moveSpeed)
                {
                    animTimer += moveSpeed * Time.deltaTime;

                    if (animTimer < 0.5f)
                    {
                        PlayerAnim(1);//移动中
                    }
                    else
                    {
                        PlayerAnim(0);//待机中
                    }
                }
            }
        }
    }
}

场景布局:
主角:
主角挂在脚本
地图加载:
队列脚本
队列:
跟随
地图json二维数组:
地图
主角精灵素材:
主角
地图素材:
地图资源
我切换了json脚本,使用拉多地图测试:
在这里插入图片描述
在这里插入图片描述

运行效果:

重装机兵

npc和玩家移动一格播放两张精灵图片,这个也适用于吞食天地2。
剩余部分就是显示玩家区域部分地图块了,大地图非常大,计算玩家坐标和区域范围,只加载玩家范围内地图,超出部分置为空减少消耗。

源码:
莫要客气

地图滚动在此文章:unity复刻重装机兵地图滚动

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值