在 Unity 中连接具有不同纹理的 Rule-Tiles (2D)
Connecting Rule-Tiles with different textures in Unity (2D)
我正在 Unity 中创建一个 2D 平台游戏,我正在使用“2D Extras”附加组件中的规则块。我目前正在尝试让两个 ruletiles 相互连接,即使它们具有不同的纹理。在这里您可以看到 Ruletiles which I want to connect 的示例。我想连接较浅和较深的草地砖。它们在两个单独的 ruletile 文件中。
我该如何管理?
有几种方法可以解决这个问题,主要取决于您希望如何在视觉上连接有问题的图块。我一般解决这个问题的方法是改变 ruletile 以便区分:
- 相同的图块类型(这个)
- 另一种瓷砖类型(不是这个)
- 一个 emtpy 磁贴(空)
我认为实现相当简单,可以通过在以下位置编辑原始 ruletile.cs 来完成:
public enum Neighbor { DontCare, This, NotThis, Empty }
最重要的是:
// When this returns true, that means that the rule does not match
// IE this is testing if any of the rules are broken
// If the rule matches that means that the sprite associated to the rule will be the new main sprite
// These are the rules which are being checked if they are broken
// This - should only be triggered for the same tile type,
// which is not the case when the tile is not this
// NotThis - should only be triggered for another tile, which is not empty
// IE broken when it is this or null(empty)
// Empty - should only be triggered when there is no tile
// IE broken when it is this or not null(empty)
private bool RuleBroken(TilingRule rule, int index, TileBase tile)
{
return (rule.m_Neighbors[index] == TilingRule.Neighbor.This && tile != this)
|| (rule.m_Neighbors[index] == TilingRule.Neighbor.NotThis && (tile == this || tile == null))
|| (rule.m_Neighbors[index] == TilingRule.Neighbor.Empty && (tile == this || tile != null))
;
}
剩下的就是对编辑器文件进行更改,以便您实际上可以在 4 个而不是 3 个枚举状态之间切换,然后在网格中绘制一个选择的图形。
如果您想使用我更改后的版本,您可以找到 ruletile.cs and ruletileeditor.cs in this gist。
请注意,对于此实现,您的规则块将需要更多规则来描述每个块。
我遇到了同样的问题,但我看到包代码已经更新,所以我将相同的解决方案应用于最新版本的包(适用于 Unity 2019.2.0f1)。我把它放在这里以防万一有人需要它:https://github.com/Scorpin/RuleTiles-differentiating-between-another-tile-and-empty
已添加代码的最相关部分:
在RuleTile.cs中添加了新的邻居类型,在第57行(class邻居):
public const int Empty = 3;
以及如何管理它(RuleMatch 的更基本实现):
在 413 更改为:
case TilingRule.Neighbor.NotThis: return (tile != m_Self && tile != null);
并在之后添加:
case TilingRule.Neighbor.Empty: return tile == null;
在RuleTileEditor.cs中,在第28行添加图标:
private const string s_OtherTile = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAABNmlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjarY6xSsNQFEDPi6LiUCsEcXB4kygotupgxqQtRRCs1SHJ1qShSmkSXl7VfoSjWwcXd7/AyVFwUPwC/0Bx6uAQIYODCJ7p3MPlcsGo2HWnYZRhEGvVbjrS9Xw5+8QMUwDQCbPUbrUOAOIkjvjB5ysC4HnTrjsN/sZ8mCoNTIDtbpSFICpA/0KnGsQYMIN+qkHcAaY6addAPAClXu4vQCnI/Q0oKdfzQXwAZs/1fDDmADPIfQUwdXSpAWpJOlJnvVMtq5ZlSbubBJE8HmU6GmRyPw4TlSaqo6MukP8HwGK+2G46cq1qWXvr/DOu58vc3o8QgFh6LFpBOFTn3yqMnd/n4sZ4GQ5vYXpStN0ruNmAheuirVahvAX34y/Axk/96FpPYgAAACBjSFJNAAB6JQAAgIMAAPn/AACA6AAAUggAARVYAAA6lwAAF2/XWh+QAAAAdElEQVR42qyTOxKAIAxEWcbCK1B5/2NZcQW7ZwMNMCROTMM3S/YBAlIkjt3iJT29f8P5SUASdRgDGvdlK7m0trZ5U2BMBrQTySkYEwNA/ZSV56li6xpXltwWrGQ3g7KxE4boYrCDGa7ABXH1An+zoOh3fgcAkVNC6ZGUg/8AAAAASUVORK5CYII=";
在第 47 行添加到纹理数组(并在第 37 行将数组的项目数更改为 11):
s_Arrows[10] = Base64ToTexture(s_OtherTile);
最后,将 "NotThis" GUI 移动到数组中的第 10 项,因此我们可以添加 "Empty" 并为其使用第 198 行的图标编号 9,如下所示:
case RuleTile.TilingRule.Neighbor.NotThis:
GUI.DrawTexture(rect, arrows[10]);
break;
case RuleTile.TilingRule.Neighbor.Empty:
GUI.DrawTexture(rect, arrows[9]);
break;
仅此而已:)
非常感谢您的解决方案亚历山大 :)
2d Tilemap Extras 的贡献者包括对规则图块的选择性覆盖。
示例可在此处找到:
https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@1.6/manual/CustomRulesForRuleTile.html
特别是 Siblings Tiles 1。
这将创建一个新的规则拼贴,其功能与规则拼贴相同,只是它还包括也在可扩展列表中的规则拼贴。
我不想遍历我的一百万个半规则块并将所有规则从绿色箭头“This”更改为#3“Sibling”所以我只是用它来覆盖“This”到包括“兄弟姐妹”。
public class SiblingTile : RuleTile<SiblingTile> {
public List<TileBase> Siblings = new List<TileBase>();
public override bool RuleMatch(int neighbor, TileBase tile) {
// Direct override of rule tile's "this" check with an inclusion of those in Siblings list.
switch (neighbor) {
case TilingRuleOutput.Neighbor.This:
return tile == this || Siblings.Contains(tile);
}
return base.RuleMatch(neighbor, tile);
}
}
真的很好很简单。
我使用了 Kmsxkuse 的解决方案,但我不得不对其进行一些修改,因为它对我不起作用。
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using static UnityEngine.RuleTile.TilingRuleOutput;
namespace Assets.Scripts.Tiles
{
[CreateAssetMenu]
public class PathHighlightTile : IsometricRuleTile<Neighbor>
{
public List<TileBase> Siblings = new List<TileBase>();
public override bool RuleMatch(int neighbor, TileBase other)
{
switch (neighbor)
{
case Neighbor.This:
{
return other == this || Siblings.Contains(other);
}
case Neighbor.NotThis:
{
return other != this && !Siblings.Contains(other);
}
}
return base.RuleMatch(neighbor, other);
}
}
}
我正在 Unity 中创建一个 2D 平台游戏,我正在使用“2D Extras”附加组件中的规则块。我目前正在尝试让两个 ruletiles 相互连接,即使它们具有不同的纹理。在这里您可以看到 Ruletiles which I want to connect 的示例。我想连接较浅和较深的草地砖。它们在两个单独的 ruletile 文件中。
我该如何管理?
有几种方法可以解决这个问题,主要取决于您希望如何在视觉上连接有问题的图块。我一般解决这个问题的方法是改变 ruletile 以便区分:
- 相同的图块类型(这个)
- 另一种瓷砖类型(不是这个)
- 一个 emtpy 磁贴(空)
我认为实现相当简单,可以通过在以下位置编辑原始 ruletile.cs 来完成:
public enum Neighbor { DontCare, This, NotThis, Empty }
最重要的是:
// When this returns true, that means that the rule does not match
// IE this is testing if any of the rules are broken
// If the rule matches that means that the sprite associated to the rule will be the new main sprite
// These are the rules which are being checked if they are broken
// This - should only be triggered for the same tile type,
// which is not the case when the tile is not this
// NotThis - should only be triggered for another tile, which is not empty
// IE broken when it is this or null(empty)
// Empty - should only be triggered when there is no tile
// IE broken when it is this or not null(empty)
private bool RuleBroken(TilingRule rule, int index, TileBase tile)
{
return (rule.m_Neighbors[index] == TilingRule.Neighbor.This && tile != this)
|| (rule.m_Neighbors[index] == TilingRule.Neighbor.NotThis && (tile == this || tile == null))
|| (rule.m_Neighbors[index] == TilingRule.Neighbor.Empty && (tile == this || tile != null))
;
}
剩下的就是对编辑器文件进行更改,以便您实际上可以在 4 个而不是 3 个枚举状态之间切换,然后在网格中绘制一个选择的图形。
如果您想使用我更改后的版本,您可以找到 ruletile.cs and ruletileeditor.cs in this gist。
请注意,对于此实现,您的规则块将需要更多规则来描述每个块。
我遇到了同样的问题,但我看到包代码已经更新,所以我将相同的解决方案应用于最新版本的包(适用于 Unity 2019.2.0f1)。我把它放在这里以防万一有人需要它:https://github.com/Scorpin/RuleTiles-differentiating-between-another-tile-and-empty
已添加代码的最相关部分:
在RuleTile.cs中添加了新的邻居类型,在第57行(class邻居):
public const int Empty = 3;
以及如何管理它(RuleMatch 的更基本实现):
在 413 更改为:
case TilingRule.Neighbor.NotThis: return (tile != m_Self && tile != null);
并在之后添加:
case TilingRule.Neighbor.Empty: return tile == null;
在RuleTileEditor.cs中,在第28行添加图标:
private const string s_OtherTile = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAABNmlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjarY6xSsNQFEDPi6LiUCsEcXB4kygotupgxqQtRRCs1SHJ1qShSmkSXl7VfoSjWwcXd7/AyVFwUPwC/0Bx6uAQIYODCJ7p3MPlcsGo2HWnYZRhEGvVbjrS9Xw5+8QMUwDQCbPUbrUOAOIkjvjB5ysC4HnTrjsN/sZ8mCoNTIDtbpSFICpA/0KnGsQYMIN+qkHcAaY6addAPAClXu4vQCnI/Q0oKdfzQXwAZs/1fDDmADPIfQUwdXSpAWpJOlJnvVMtq5ZlSbubBJE8HmU6GmRyPw4TlSaqo6MukP8HwGK+2G46cq1qWXvr/DOu58vc3o8QgFh6LFpBOFTn3yqMnd/n4sZ4GQ5vYXpStN0ruNmAheuirVahvAX34y/Axk/96FpPYgAAACBjSFJNAAB6JQAAgIMAAPn/AACA6AAAUggAARVYAAA6lwAAF2/XWh+QAAAAdElEQVR42qyTOxKAIAxEWcbCK1B5/2NZcQW7ZwMNMCROTMM3S/YBAlIkjt3iJT29f8P5SUASdRgDGvdlK7m0trZ5U2BMBrQTySkYEwNA/ZSV56li6xpXltwWrGQ3g7KxE4boYrCDGa7ABXH1An+zoOh3fgcAkVNC6ZGUg/8AAAAASUVORK5CYII=";
在第 47 行添加到纹理数组(并在第 37 行将数组的项目数更改为 11):
s_Arrows[10] = Base64ToTexture(s_OtherTile);
最后,将 "NotThis" GUI 移动到数组中的第 10 项,因此我们可以添加 "Empty" 并为其使用第 198 行的图标编号 9,如下所示:
case RuleTile.TilingRule.Neighbor.NotThis:
GUI.DrawTexture(rect, arrows[10]);
break;
case RuleTile.TilingRule.Neighbor.Empty:
GUI.DrawTexture(rect, arrows[9]);
break;
仅此而已:)
非常感谢您的解决方案亚历山大 :)
2d Tilemap Extras 的贡献者包括对规则图块的选择性覆盖。
示例可在此处找到:
https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@1.6/manual/CustomRulesForRuleTile.html
特别是 Siblings Tiles 1。
这将创建一个新的规则拼贴,其功能与规则拼贴相同,只是它还包括也在可扩展列表中的规则拼贴。
我不想遍历我的一百万个半规则块并将所有规则从绿色箭头“This”更改为#3“Sibling”所以我只是用它来覆盖“This”到包括“兄弟姐妹”。
public class SiblingTile : RuleTile<SiblingTile> {
public List<TileBase> Siblings = new List<TileBase>();
public override bool RuleMatch(int neighbor, TileBase tile) {
// Direct override of rule tile's "this" check with an inclusion of those in Siblings list.
switch (neighbor) {
case TilingRuleOutput.Neighbor.This:
return tile == this || Siblings.Contains(tile);
}
return base.RuleMatch(neighbor, tile);
}
}
真的很好很简单。
我使用了 Kmsxkuse 的解决方案,但我不得不对其进行一些修改,因为它对我不起作用。
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using static UnityEngine.RuleTile.TilingRuleOutput;
namespace Assets.Scripts.Tiles
{
[CreateAssetMenu]
public class PathHighlightTile : IsometricRuleTile<Neighbor>
{
public List<TileBase> Siblings = new List<TileBase>();
public override bool RuleMatch(int neighbor, TileBase other)
{
switch (neighbor)
{
case Neighbor.This:
{
return other == this || Siblings.Contains(other);
}
case Neighbor.NotThis:
{
return other != this && !Siblings.Contains(other);
}
}
return base.RuleMatch(neighbor, other);
}
}
}