Giter Club home page Giter Club logo

Comments (29)

chalmersgit avatar chalmersgit commented on July 27, 2024 1

@johnsoncodehk Just a minor fix to make your code compile:

public class MyTile: RuleTile<MyTile.Neighbor>
{
    public List<RuleTile> sibings = new List<RuleTile>(); 

    public class Neighbor : RuleTile.TilingRule.Neighbor
    {
        public const int Sibing = 3;
    }

    public override bool RuleMatch(int neighbor, TileBase other)
    {
        // should support RuleOverrideTile
        if (other is RuleOverrideTile) other = (other as RuleOverrideTile).m_InstanceTile;

        RuleTile otherRuleTile = other as RuleTile; // <-- Need to cast it to make it compatible with siblings list

        switch (neighbor)
        {
            case Neighbor.Sibing: return sibings.Contains(otherRuleTile);
        }

        return base.RuleMatch(neighbor, other);
    }
}

But regardless, the list is of type RuleTile, which means it only lists entries of entire rule sets (whereas before when it was a list of type TileBase, it would at least allow me to select the specific tile I want to react to (e.g., a wall tile)).

from 2d-extras.

timminkov avatar timminkov commented on July 27, 2024

Managed to somewhat figure it out, but I doubt it'll be performant:

First we grab the neighbor tiles' neighbors:

private void SetMatchingNeighboringTiles(ITilemap tilemap, Vector3Int position, TileBase baseTile, int xIndex)
		{
			if (baseTile == null) {
				return;
			}

            neighboringNeighbors[xIndex] = new TileBase[NeighborCount];
			int index = 0;
			for (int y = 1; y >= -1; y--)
			{
				for (int x = -1; x <= 1; x++)
				{
					if (x != 0 || y != 0)
					{
						Vector3Int tilePosition = new Vector3Int(position.x + x, position.y + y, position.z);
						neighboringNeighbors[xIndex][index] = tilemap.GetTile(tilePosition);
						index++;
					}
				}
			}
		}

Then we check against them during rule checks:

		public virtual bool RuleMatch(int neighbor, TileBase tile, int index)
		{
			switch (neighbor)
			{
				case TilingRule.Neighbor.This: return tile == m_Self;
				case TilingRule.Neighbor.NotThis: return tile != m_Self;
				case TilingRule.Neighbor.SkipATile: 
					TileBase[] baseTileArray = neighboringNeighbors[index];
					TileBase baseTile = baseTileArray[index];
					return baseTile != m_Self;
			}
			return true;
		}

from 2d-extras.

timminkov avatar timminkov commented on July 27, 2024

This doesn't work well on corners, as you can see here:
image

The only real way to do it is to build out a UI to select neighboring sprites to use as rules, which I feel like would take forever. Anyone have a better idea?

from 2d-extras.

johnsoncodehk avatar johnsoncodehk commented on July 27, 2024

This seems to be a problem with the rule setting, as far as I know it doesn't even need to change the code.
For the lack of corners, add the rules in the picture to fill it.
tile

from 2d-extras.

timminkov avatar timminkov commented on July 27, 2024

That won't work - The tiles I'm talking about are surrounded on all sides.

from 2d-extras.

johnsoncodehk avatar johnsoncodehk commented on July 27, 2024

What do you want to do is the dark part of this picture?
tile

from 2d-extras.

timminkov avatar timminkov commented on July 27, 2024

Yes - Using a single rule tile for the entire set.

from 2d-extras.

johnsoncodehk avatar johnsoncodehk commented on July 27, 2024

I made a light part, the same as the dark part.
Maybe you don't need to be so complicated, but you can refer to it.
tile2

from 2d-extras.

timminkov avatar timminkov commented on July 27, 2024

That rule tile doesn't have any of your dark tiles on it.

from 2d-extras.

johnsoncodehk avatar johnsoncodehk commented on July 27, 2024

Sorry, I misunderstood what you mean.
You must currently implement it using two RuleTile.

from 2d-extras.

johnsoncodehk avatar johnsoncodehk commented on July 27, 2024

Just a suggestion, if draw the gray edge on the outer tile, the whole thing will be very simple.

from 2d-extras.

ChuanXin-Unity avatar ChuanXin-Unity commented on July 27, 2024

Hi, did johnsoncodehk's suggestions help?

from 2d-extras.

timminkov avatar timminkov commented on July 27, 2024

No, they didn't.

from 2d-extras.

ChuanXin-Unity avatar ChuanXin-Unity commented on July 27, 2024

It sounds like you need a RuleTile which takes into consideration tiles which are two cells away or if a neighboring tile is an edge.

from 2d-extras.

timminkov avatar timminkov commented on July 27, 2024

Yes - Is there any way to do that through the API (specifically the edge part). The two cells away is something I wrote but doesn't really work very well for some edge cases. I can live with two rule tiles, but it's simply not possible for the two tiles to interact with one another (in a way where it knows facts about the other tile's rules).

For example, here's what it looks like with two rule tiles:
image

The issue is that the outer side is assuming it's a single row, when it should be thinking it's just the edge.

from 2d-extras.

timminkov avatar timminkov commented on July 27, 2024

If I change the following line:
case TilingRule.Neighbor.This: return tile == m_Self;
to:
case TilingRule.Neighbor.This: return tile == m_Self || tile != null;

I get behavior that I can somewhat work around (using two rule tiles). It'd still be really nice to be able to encapsulate all of this inside a single rule tile.

from 2d-extras.

alijaya avatar alijaya commented on July 27, 2024

Hey you can use Override Rule Tile to fix the problem with this problem

Yes - Is there any way to do that through the API (specifically the edge part). The two cells away is something I wrote but doesn't really work very well for some edge cases. I can live with two rule tiles, but it's simply not possible for the two tiles to interact with one another (in a way where it knows facts about the other tile's rules).

For example, here's what it looks like with two rule tiles:
image

The issue is that the outer side is assuming it's a single row, when it should be thinking it's just the edge.

from 2d-extras.

Tencryn avatar Tencryn commented on July 27, 2024

Has there been any update to this?

I'm creating a rule where the tile's sprite changes depending on what the neighbours tile positions have on another tilemap so I'm in need of getting the neighboring tile position inside of RuleMatch.

from 2d-extras.

chalmersgit avatar chalmersgit commented on July 27, 2024

I also have this issue and was hoping there'd be a solution out there. I'm surprised to see there isn't. It seems like a pretty common thing to do. My current workflow involves two rule tiles to get this effect, which is very tedious as it requires me to "repaint" all the interiors of the tilemap with the darker shade.

from 2d-extras.

chalmersgit avatar chalmersgit commented on July 27, 2024

I ended up getting a working solution. But it required writing a lot of conditionals (neighbor Sprite checks) - there were quite a few edge cases. I won't share the code since it's very ugly (maybe later I'll clean it up), but I can post some details here when/if I get time.

from 2d-extras.

chalmersgit avatar chalmersgit commented on July 27, 2024

Unity's recent "Extend Neighbors" rule tile allows you to check multiple tiles over ("2 away" or more), which effectively allows us to fix this issue.

I went ahead and made the rules and got it working. It's tedious, as I needed to duplicate the same tile result under multiple different rules (often 5 sets of rules to catch all the edge cases for a single sprite - which I needed to do 4 times for each wall, and then a few more times for corners).

I think it would be more elegant if the rules included a way of doing "or" style checks (similar to what is found in the "Advanced Rule Tile" asset on the asset store - which currently only supports 3x3 Rule Tiles, but it at least has the concept of an "or" rule which I think would make this current process less tedious).

Regardless, the issue should be resolved now.

from 2d-extras.

johnsoncodehk avatar johnsoncodehk commented on July 27, 2024

@chalmersgit Nice hear that it is useful to you, but it is not new, it is a feature from one year ago XD: #140

Maybe you can try Sibling Rule Tile from here: https://github.com/johnsoncodehk/rule-tile-extras
It is a simple but supports Extend Neighbors implementation.

from 2d-extras.

chalmersgit avatar chalmersgit commented on July 27, 2024

@johnsoncodehk yeah true haha. Just felt kinda new given the age of this thread and how recent I found it :p

Yeah I tried that siblings one. It has an issue (at least I couldn't figure out) that stopped me from using it. The problem is that the "sibling" is a TileBase type. But when you draw from your palette, the tiles I believe are from the rule type type, not specific to the tile you selected in the sibling GUI.

So the sibling rule only worked if I drag+dropped that specific tile into the palette. So effectively it was useless.

In concept, if the siblings script worked as I had hoped, it would fix this issue. Please let me know if this is possible. That would save a lot of time.

from 2d-extras.

johnsoncodehk avatar johnsoncodehk commented on July 27, 2024

@chalmersgit this is a design limitations, some related discussion here: #67 (comment)

I really want to solve it, but it is "close source". :(

from 2d-extras.

chalmersgit avatar chalmersgit commented on July 27, 2024

@johnsoncodehk ah ok. Thanks for sharing.

I wonder what the intended use case for the sibling was then.

To be clear, in referring to "siblings 1":
https://docs.unity3d.com/Packages/[email protected]/manual/CustomRulesForRuleTile.html

Siblings 2 makes complete sense (making two sets of rule tiles interact with one another), but siblings 1 doesn't practically work with rules+palette.

from 2d-extras.

johnsoncodehk avatar johnsoncodehk commented on July 27, 2024

@chalmersgit this is no a good example from here... #38

the problem is, we know RuleTile can only refresh by RuleTile, so we should do:

public class MyTile : RuleTile<MyTile.Neighbor> {

    public List<RuleTile> sibings = new List<RuleTile>(); // <-- not allow TileBase

    public class Neighbor : RuleTile.TilingRule.Neighbor {
        public const int Sibing = 3;
    }

    public override bool RuleMatch(int neighbor, TileBase other) {

        // should support RuleOverrideTile
        if (other is RuleOverrideTile) other = (other as RuleOverrideTile).m_InstanceTile;

        switch (neighbor) {
            case Neighbor.Sibing: return sibings.Contains(other);
        }

        return base.RuleMatch(neighbor, other);
    }
}

from 2d-extras.

chalmersgit avatar chalmersgit commented on July 27, 2024

@johnsoncodehk interesting. I'll check it this evening and report back.

from 2d-extras.

johnsoncodehk avatar johnsoncodehk commented on July 27, 2024

@chalmersgit You need to add the two Siblings Tile 1 to each other to get the same behavior as Siblings Tile 2, so yes it is not practical, just for as an example.

from 2d-extras.

Triangle4 avatar Triangle4 commented on July 27, 2024

If you have incompatible rules, say for example if your fill tile does not have all 8 connections as green arrows, inner corners will not work. But if you properly set up that fill tile it will work! :)
Make sure your fill tile has 8 green arrows :)

from 2d-extras.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.