[英]Grid-based/Tile Movement + Collisions in Unity?
在弄清楚如何进行基于网格的运动或基于图块的运动时遇到了一个巨大的问题。 有点类似于 Nitrome 的 Redungeon:无法真正发布图片:所以这是一个 gif。 http://www.eneminds.com/redungeon/img/gifs/gif_1.gif
我想我应该创建一个网格系统。 我认为这很简单,就像旧游戏(口袋妖怪等)一样。但不知道该怎么做。 但我也希望动作快。
Unity拥有自己的tilemap实现,应该可以让您以背景为基础构建背景: https ://docs.unity3d.com/Manual/Tilemap.html
此外,Unity提供了更多2d内容来帮助您在此处构建内容: https : //github.com/Unity-Technologies/2d-extras
在此处找到的许多教程中概述了冲突: https : //unity3d.com/learn/tutorials/s/2d-game-creation
要制作像GIF动画那样的游戏并不容易 。 如果您是游戏开发者的新手,那么尤其是这样,不要指望简单的解决方案。
您可能想查看Unity资产商店,以快速获得基于图块的移动的肮脏方式,但这将一如既往地附带价格,并且无济于事。 https://assetstore.unity.com/
关于移动速度,这始终只是游戏中的变量,可以根据自己的喜好进行调整。 在基于图块的游戏中,它对应于角色在视觉上从一个图块转移到另一个图块所花费的时间。 尝试阅读Lerping,它是Unity引擎的一部分。 https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html
我能够完成。 我刚刚从Unity学习部分的RogueLike教程中修改了输入内容。
所以这是负责运动的代码
void Move(string direction_string)
{
ChangeDirection(direction_string);
Vector2 start = transform.position;
Vector2 end = start + direction;
boxCollider.enabled = false;
hit = Physics2D.Linecast(start, end, blockingLayer);
boxCollider.enabled = true;
if (hit.transform == null) {
StartCoroutine(Movement(end));
animator.SetTrigger(direction_string);
return;
} else {
moveSequence.RemoveAt(0);
animator.SetTrigger(direction_string);
return;
}
}
void ChangeDirection(string direction_string)
{
switch (direction_string) {
case "up":
direction = dir_Up;
break;
case "down":
direction = dir_Down;
break;
case "left":
direction = dir_Left;
break;
case "right":
direction = dir_Right;
break;
}
}
IEnumerator Movement(Vector3 end)
{
moving = true;
float sqrRemainingDistance = (transform.position - end).sqrMagnitude;
while (sqrRemainingDistance > float.Epsilon) {
Vector3 newPosition = Vector3.MoveTowards(rb2D.position, end, moveSpeed * Time.deltaTime);
rb2D.MovePosition(newPosition);
sqrRemainingDistance = (transform.position - end).sqrMagnitude;
yield return null;
}
currentPos = end;
moveSequence.RemoveAt(0);
moving = false;
}
}
这是负责输入的内容
void FixedUpdate ()
{
if (moveSequence.Count > 0 && !moving) {
Move(moveSequence[0]);
}
}
然后将其连接到一个Update()函数,该函数侦听按钮的按下并将一个列表项添加到moveSequence List中,例如
moveSequence.Add("up");
刚刚为 reddit 上的某个人做了一个这样的代码,来这里看看之前是否有人问过它。 我知道我迟到了 2 年,但如果有人需要它,它就在这里。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameController : MonoBehaviour
{
// a script created so that a player always moves one direction at a time on a grid.
// It uses a plane with even width and height to make a grid
// - if needed, turn off the mesh renderer so that you dont see the tiled grid.
// the game object we use to create a grid. Should be a plane with an even width and height.
public GameObject tile_object;
// grid x and y sizes, set them to odd numbers
public float x_grid_size, y_grid_size;
// List of all our floor tiles
Dictionary<(float x, float y), GameObject> floor_list = new Dictionary<(float x, float y), GameObject>();
// Reference to the player prefab
public GameObject player;
// reference to player character
private GameObject player_character;
// a tool used for debugging
bool debugging = true;
//check if player is moving
bool player_is_moving = false;
(float x, float y) players_current_tile;
// players speed
public float player_speed = 35f;
// used in calculating movements
(float x, float y) to_tile;
//used to calculate movement
Vector3 to_pos;
// Start is called before the first frame update
void Start()
{
// put the player into the scene
player_character = Instantiate(player, Vector3.zero, player.transform.rotation);
// Sets the Middle Tile and checks grid is odd
SetMiddleTile();
// create a floor grid to help us visualize our play field.
CreateGrid();
}
// Update is called once per frame
void Update()
{
PlayerMovement();
MovePlayer();
}
// gets inputs on A S W D keys for movement
void PlayerMovement() {
if (Input.GetKeyDown(KeyCode.W)){
PlayerInput((0, 1));
}
if (Input.GetKeyDown(KeyCode.A))
{
PlayerInput((-1, 0));
}
if (Input.GetKeyDown(KeyCode.S))
{
PlayerInput((0, -1));
}
if (Input.GetKeyDown(KeyCode.D))
{
PlayerInput((1, 0));
}
}
// simplifies player entries, and gets input directional data
void PlayerInput((float x, float y) input)
{
if (!player_is_moving)
{
(float x, float y) to_tile_check = (players_current_tile.x + input.x, players_current_tile.y + input.y);
if (floor_list[to_tile_check] != null)
{
player_is_moving = true;
to_tile = (players_current_tile.x + input.x, players_current_tile.y + input.y);
to_pos = floor_list[to_tile].transform.position;
}
}
}
// used to move the player
void MovePlayer()
{
if (player_is_moving)
{
player_character.transform.position = Vector3.MoveTowards(player_character.transform.position, to_pos, Time.deltaTime * player_speed);
if (player_character.transform.position == to_pos)
{
players_current_tile = to_tile;
player_is_moving = false;
}
}
}
// used to create the floor grid
void CreateGrid()
{
// Create an empty to hold our floor grid
GameObject grid_empty = new GameObject();
grid_empty.name = "grid_floor";
// get the size of our floor tile so we know how far to space them.
float tile_size = tile_object.GetComponent<MeshRenderer>().bounds.size.x;
// create an offset so the grid is always centered in game view
Vector3 offSet = new Vector3((x_grid_size * tile_size) / 2 - (tile_size / 2), 0, (y_grid_size * tile_size)/2 - (tile_size / 2));
// iterate to create tiles on x axis
for (int x = 0; x < x_grid_size; x++)
{
// iterate to create tiles on y axis
for (int y = 0; y < y_grid_size; y++)
{
// instantiate new tile
GameObject floor_tile = Instantiate(tile_object, (new Vector3(x * tile_size, 0, y * tile_size) - offSet), tile_object.transform.rotation);
floor_tile.name = "flr_x: " + (x + 1) + " y:" + (y + 1);
// set the parent to grid empty so the scene isnt filled with objects and all floor tiles are neatly centerd
floor_tile.transform.parent = grid_empty.transform;
// add the tile to our dictionary.
floor_list.Add(((x + 1),(y + 1)), floor_tile);
}
}
if (debugging) { print("Created Floors: " + (x_grid_size * y_grid_size) + " Floor List Size: " + floor_list.Count);}
}
// sets the middle tile the player is spawned on, also checks to make sure grid size is set correctly
void SetMiddleTile()
{
// these check to make sure grid size isnt 0 and are odd
if (x_grid_size == 0 && y_grid_size == 0) { print("Forgot to set grid size! setting default to 7x and 7y"); x_grid_size = 7; y_grid_size = 7; }
if (x_grid_size % 2 == 0) { print("x_grid_size is set to an even number(" + x_grid_size + "), changing it to odd(" + (x_grid_size + 1) + ")"); x_grid_size += 1; }
if (y_grid_size % 2 == 0) { print("y_grid_size is set to an even number(" + y_grid_size + "), changing it to odd(" + (y_grid_size + 1) + ")"); y_grid_size += 1; }
// splits the grid and half
float x = x_grid_size / 2 + 0.5f;
float y = y_grid_size / 2 + 0.5f;
// set the players current tile to middle tile
players_current_tile = (x, y);
// set the to tile to current tile to avoid null instances when first checking our dictionary
to_tile = players_current_tile;
// used for debugging
if (debugging) { print("the middle tile is: x(" + x + ")" + " y(" + y + ")"); }
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.