在 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);
        }
    }
}