在 Unity (2D) 中连接具有不同纹理的规则图块
Posted
技术标签:
【中文标题】在 Unity (2D) 中连接具有不同纹理的规则图块【英文标题】:Connecting Rule-Tiles with different textures in Unity (2D) 【发布时间】:2018-12-02 07:14:08 【问题描述】:我正在 Unity 中创建 2D 平台游戏,并且正在使用“2D Extras”插件中的规则拼贴。我目前正试图让两个规则块相互连接,即使它们具有不同的纹理。在这里您可以看到Ruletiles which I want to connect 的示例。我想连接浅色和深色的草砖。它们位于两个单独的规则文件中。
我该如何管理?
【问题讨论】:
This unity asset(高级规则图块)已经存在很长时间了。它完全符合您的要求,并且与 2d 资产中的常规规则拼贴一样易于使用,不像硬编码每个拼贴以能够检测黑草等,这使您可以建立多种类型的关系在任何瓷砖类型之间。 【参考方案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。
请注意,使用此实现,您的规则图块将需要更多规则来描述每个图块。
【讨论】:
感谢您的回答。我检查了您的代码并且理解您的方法,但我不确定您如何询问邻居是否为空。这是如何工作的?如果您对此感到满意,我将使用您的代码,但我也想理解它。 是的,请随意使用。 :) 我也花了一段时间才明白第一次到底发生了什么。我一般理解这个类的方式是,每次刷新网格中的规则块时,它都会通过循环每个平铺规则来检查它需要什么,以返回第一个实际匹配您的规则的规则。换句话说,第一个没有违反规则的。这也意味着编辑器中平铺规则的顺序可能很重要。被编辑的brokenrule函数用于查找规则不匹配的情况。 brokenrule 函数本身会检查其 tilingruleset(编辑器 tilingrule)中的每个邻居是否有对应的邻居。如果瓦片(它是实际的邻居)违反了规则,那么它返回 true 并且规则被破坏,使函数寻找下一个瓦片。有关实际违反规则的信息,请参见 cmets。希望对您有所帮助。【参考方案2】:我遇到了同样的问题,但我看到包代码已更新,因此我将相同的解决方案应用于包的最新版本(适用于 Unity 2019.2.0f1)。我把它放在这里以防万一有人需要它:https://github.com/Scorpin/RuleTiles-differentiating-between-another-tile-and-empty
添加代码的最相关部分:
在 RuleTile.cs 中添加了新的邻居类型,在第 57 行(Neighbor 类):
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 :)
【讨论】:
您能否在答案中包含该链接中的相关部分? 嗯,这里和那里都有一些小的变化,但我会尽量以最清晰的方式表达:)【参考方案3】: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);
真的很好很简单。
【讨论】:
【参考方案4】:我使用了 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) 中连接具有不同纹理的规则图块的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Unity 中从 3D 对象中获取 2D 视图/纹理