- Home /
[2D] How do most people make levels with proper collision AND textures?
So, when I put down a series of 1x1 "floor" prefabs with a Box Collider 2d, walking across them is a nightmare. My character will get caught and be unable to move constantly. This could probably be alleviated if I used a sphere collider for my character instead of a box collider, but that would make walking off edges not work like they do in traditional 2d platformers.
Or, I can stretch out a floor prefab and just have one big box collider for a walkable segment using the scale value on the transform. This works great! But then the texture is stretched and looks awful. I don't think I'm supposed to make a new prefab with a custom material for every possible length and height of floors, so how do I make the texture/sprite tile when I scale it? Is there a way to create a new material specific to each gameobject without doing so manually?
I only need one of these two things to work, but since neither do, I'm kind of in a bind. How do most people make levels for a 2d platformer?
you can modify the collider size without changing the object's size. just use "Edit Collider" button in inspector
Yes, but then the size of the collider wouldn't match the size/scaling of the texture. I'd end up with a blurry stretched mess, or a floor that's partially invisible.
So I found and slightly edited a script that makes the textures tile by creating instances of the material in the editor as I scale the prefab. This seems to work well, but comes up with an error saying
"Instantiating material due to calling renderer.material during edit mode. This will leak materials into the scene. You most likely want to use renderer.shared$$anonymous$$aterial ins$$anonymous$$d."
The script calls "Resources.UnloadUnusedAssets();" after every time it assigns a new instance of the material, will this still cause a memory leak? Or is it fine? Who knows, but I'm using it until Unity releases a tile editor.
Code was found here, and here it is:
using UnityEngine;
using System.Collections;
[ExecuteInEdit$$anonymous$$ode]
public class TextureTilingController : $$anonymous$$onoBehaviour {
// Give us the texture so that we can scale proportianally the width according to the height variable below
// We will grab it from the meshRenderer
public Texture texture;
public float textureTo$$anonymous$$eshY = 2f; // Use this to contrain texture to a certain size
Vector3 prevScale = Vector3.one;
float prevTextureTo$$anonymous$$eshY = -1f;
// Use this for initialization
void Start () {
this.prevScale = gameObject.transform.lossyScale;
this.prevTextureTo$$anonymous$$eshY = this.textureTo$$anonymous$$eshY;
//this.UpdateTiling();
}
// Update is called once per frame
void Update () {
// If something has changed
if(gameObject.transform.lossyScale != prevScale || !$$anonymous$$athf.Approximately(this.textureTo$$anonymous$$eshY, prevTextureTo$$anonymous$$eshY))
this.UpdateTiling();
// $$anonymous$$aintain previous state variables
this.prevScale = gameObject.transform.lossyScale;
this.prevTextureTo$$anonymous$$eshY = this.textureTo$$anonymous$$eshY;
}
[Context$$anonymous$$enu("UpdateTiling")]
void UpdateTiling()
{
// A Unity plane is 10 units x 10 units
float planeSizeX = 10f;
float planeSizeY = 10f;
// Figure out texture-to-mesh width based on user set texture-to-mesh height
float textureTo$$anonymous$$eshX = ((float)this.texture.width/this.texture.height)*this.textureTo$$anonymous$$eshY;
gameObject.GetComponent<Renderer>().material.mainTextureScale = new Vector2(planeSizeX*gameObject.transform.lossyScale.x/textureTo$$anonymous$$eshX, planeSizeY*gameObject.transform.lossyScale.y/textureTo$$anonymous$$eshY);
Resources.UnloadUnusedAssets();
}
}
Answer by tanoshimi · Jun 12, 2016 at 07:04 AM
I'd recommend never using the scale transform to create variations of a prefab - you'll inevitably stretch the texture. Instead, you should create separate prefabs for, say 1x1, 2x1, 4x1 blocks that have the correct UV coordinates assigned to their vertices, so you can assign the same material to each and it will tile nicely while also only requiring a single collider per platform.
Walking from one box collider to another causes massive problems the majority of the time, so anything less than the whole floor being one collider is unacceptable for now. I'm going to use the solution I found and wrote about in my comment, but thanks for the suggestion!