在Unity(2D)中连接具有不同纹理的规则标题

时间:2018-06-22 19:03:10

标签: unity3d sprite unity3d-2dtools

我正在Unity中创建2D平台游戏,并且正在使用“ 2D Extras”附加组件中的Ruletiles。我目前正在尝试让两个规则块相互连接,即使它们的纹理不同。在这里,您可以看到Ruletiles which I want to connect的示例。我想连接较浅和较暗的草砖。它们位于两个独立的常规文件中。

我该如何管理?

感谢您的回答。 问候,朱利安

5 个答案:

答案 0 :(得分:1)

有几种方法可以解决此问题,这主要取决于您在视觉上如何连接所涉及的图块。我通常解决此问题的方式是通过更改标尺,以便在以下方面进行区分:

  • 相同的图块类型(此)
  • 另一种瓷砖类型(不是此类型)
  • 空的图块(空)

我认为该实现相当简单,可以通过在以下位置编辑原始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

请注意,通过这种实现方式,您的标尺将需要更多的规则来描述每个图块。

答案 1 :(得分:0)

我遇到了同样的问题,但是我看到软件包代码已更新,因此我对软件包的最新版本(Unity 2019.2.0f1)应用了相同的解决方案。我把它放在这里,以防有人需要:https://github.com/Scorpin/RuleTiles-differentiating-between-another-tile-and-empty

已添加代码的大部分相关部分

RuleTile.cs 中,在第57行(邻居类)添加了新的邻居类型:

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;

仅此而已:)

非常感谢您的解决方案Alexander:)

答案 2 :(得分:0)

This unity asset(高级规则图块)已经存在了很长时间。它完全符合您的要求,并且像2D资产中的常规Rule-Tile一样易于使用

与对每个图块进行硬编码以检测黑草等不同,这使您可以在任何图块类型之间建立几种类型的关系。

答案 3 :(得分:0)

2d Tilemap Extras的贡献者包括选择性替代规则图块。

示例可在此处找到:

https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@1.6/manual/CustomRulesForRuleTile.html

尤其是《同胞瓷砖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);
    }
}

真的很简单。

答案 4 :(得分:0)

我使用了 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);
        }
    }
}