Closed longtran2904 closed 4 years ago
The shared tilemaps all recreated every time you run the generator. How do you assign the material to the tilemaps? The correct approach would be to add this logic to your custom tilemap layers handler (or to a custom post-processing task). I would probably add a public field to the custom tilemap layers handler with the material that you want to use and then when you initialize the tilemaps I would assign this material to all the tilemap layers.
When i install the URP package it had an automate option to switch all the materials in the project and in the editor it all looked fine but maybe when I built it it suddenly got reseted. How to assign the material through script? In the custom tilemap script there is a function called CreateTilemapGameObject which add and setup the tilemap renderer to each tilemap so i need to assign the material in here right?
OMG i finally managed to make it worked by your way! Thank you so much! You have no ideas how long i spend debugging this! Thank you!
Okay so I've just debugged the material that I assigned it through the inspector and it appears to be null which is weird because I assigned it through the inspector. Why did it null?
Hey! So custom tilemap layers handlers are used for two things - creating the structure of tilemap in room templates and creating the structure in generated levels. I would guess that you have a problem with room templates. The problem is that even though you assign the material to the instance of the handler, you probably do not use that instance when creating a room template.
You probably have something like this:
public class CustomRoomTemplateInitializer : BaseRoomTemplateInitializer
{
protected override void InitializeTilemaps(GameObject tilemapsRoot)
{
// Create an instance of your tilemap layers handler
var tilemapLayersHandler = ScriptableObject.CreateInstance<CustomTilemapsLayerHandler>();
// Initialize tilemaps
tilemapLayersHandler.InitializeTilemaps(tilemapsRoot);
}
}
The problem is that you create a new instance of the CustomTilemapsLayerHandler instead of using the instance with your material. So in order to fix it, you would have to explicitly load the saved instance of the scriptable object. Or maybe a simple solution is to create an empty room template, fix the material manually and then duplicate the room template.
However, as I'm looking into that, there should be an even easier fix. I have something like this for the universal render pipeline:
And you can see that the Default Material Type is set to Lit. With this setting, I don't have to handle materials manually - they are lit by default if I don't change it.
Thanks for replying! That is exactly what I've just thought about! Do I still need to have the line: tilemapRenderer.sharedMaterial = material;
in the CustomTilemapsLayersHandler.cs?
If you have the default value correctly set, then you do not need to set the material manually so I'd expect that the line is no longer needed (it seems to work in my project even without the line).
The problem is when I built the project the material would keep reset it back. This is the problem in the first place. If I added that line, the problem would be gone but the Material field in Tilemap Renderer would become "None (Material)" and if I drew something in the editor mode it would have pink color (because "None (Material)"). So anytime I want to draw something I had to manually assign the material to the Material field in the Tilemap Renderer.
Okay, I know how to fix it. Just put an if check to whether it is null or not. Something like: if (material) { tilemapRenderer.sharedMaterial = material; }
will do the trick.
But I still don't know why when the game wasn't played the material would be null?
Ok, so here is how it works in my project:
I managed to fix that with the following code:
public class CustomTilemapLayersHandler: TilemapLayersHandlerBase
{
public override void InitializeTilemaps(GameObject gameObject)
{
gameObject.AddComponent<Grid>();
// Create the material here
var material = new Material(Shader.Find("Universal Render Pipeline/2D/Sprite-Lit-Default"));
var floorTilemapObject = CreateTilemapGameObject("Floor", gameObject,0, material);
var wallsTilemapObject = CreateTilemapGameObject("Walls", gameObject, 1, material);
var collideableTilemapObject = CreateTilemapGameObject("Collideable", gameObject, 2, material);
}
protected GameObject CreateTilemapGameObject(string name, GameObject parentObject, int sortingOrder, Material material)
{
var tilemapObject = new GameObject(name);
tilemapObject.transform.SetParent(parentObject.transform);
var tilemap = tilemapObject.AddComponent<Tilemap>();
var tilemapRenderer = tilemapObject.AddComponent<TilemapRenderer>();
tilemapRenderer.sortingOrder = sortingOrder;
// Set the material here
tilemapRenderer.material = material;
return tilemapObject;
}
Note that I create a new material with the correct shader and then assign it to all the tilemap renderers. This seems to work even when I build the game.
It will work with your way when you built the project (It worked for me). But if you have a public material variable and assign it through the inspector of the scriptable object, in the editor that variable will become null (The build version would be okay but when you are editing the tile in editor mode it would be null). How you assign your material variable?
This can easily be fixed by having an if statement to check whether it is null or not. But I wonder why it is null even though I assign its value through the inspector?
Hey! So custom tilemap layers handlers are used for two things - creating the structure of tilemap in room templates and creating the structure in generated levels. I would guess that you have a problem with room templates. The problem is that even though you assign the material to the instance of the handler, you probably do not use that instance when creating a room template.
You probably have something like this:
public class CustomRoomTemplateInitializer : BaseRoomTemplateInitializer { protected override void InitializeTilemaps(GameObject tilemapsRoot) { // Create an instance of your tilemap layers handler var tilemapLayersHandler = ScriptableObject.CreateInstance<CustomTilemapsLayerHandler>(); // Initialize tilemaps tilemapLayersHandler.InitializeTilemaps(tilemapsRoot); } }
The problem is that you create a new instance of the CustomTilemapsLayerHandler instead of using the instance with your material. So in order to fix it, you would have to explicitly load the saved instance of the scriptable object. Or maybe a simple solution is to create an empty room template, fix the material manually and then duplicate the room template.
If you use this line var tilemapLayersHandler = ScriptableObject.CreateInstance<CustomTilemapsLayerHandler>();
then it will create a new instance of the "CustomTilemapsLayerHandler". That means that it is not the instance where you have your material set, therefore the material will have the default value - null. Unfortunately, the create room template menu item does not have access to your saved instance of the handler. You would have to somehow manually load it and then you would see your material set.
Okay, so I understand it now. Thanks!
I had a 2d scene with some 2d global lights and free form lights (from the URP package). When i had it in the editor and the game view, it looked perfect but when i built the project suddenly it would remove all the lights (i didn't see any lights). After a few days of debugging i managed to know why it happend. I think that when i build the project all the shared tilemaps' material switched from "Sprite-lit-default" to "Sprites-default" which didn't work with 2d lightings. If i didn't choose the "Intialize Shared Tilemaps" and disable all the room templates rendering and collider it would work perfectly. If i intialize shared tilemaps but didn''t disable the render and collider it would still show the room templates perfectly with all the lightings. So i thought that it must have been because the shared tilemap's material has been reset to default when been built. Why? How to fixed this?