I have 64x64 texture of tree :
but output gives me this (black messed object is my tree)
If i drag sprite into editor, its rendered as meant to be(with new gameobject created). But im accesing it through script :
public Sprite treesIcon;
SpriteRenderer sr;
TileTypeHandler typeHandler;
void Start () {
sr = GetComponent<SpriteRenderer>();
}
void Update () {
switch(typeHandler.tileType) /// nevermind enum, its edited
{
case TileType.Woods:
{
sr.sprite = treesIcon;
break;
}
}
}
point is to dynamically change textures.
Can anyone explain me this behaviour? Is there somethin I am missing about sprites and textures? How can i fix it?
The result looks like the SpriteRenderer is using the wrong shader, change the Material to Sprites-Default, and it should work.
Would you have colored images, you immediately would see that there is something wrong, because they would also appear black.
Related
Here is the code I use to attach textures at runtime:
private void ApplyTextureSet(GameObject go, TextureSet textSet)
{
SkinnedMeshRenderer skinnedMeshRenderer = go.GetComponentInChildren<SkinnedMeshRenderer>();
skinnedMeshRenderer.material.color = Color.white;
if(textSet.albedoMap)
skinnedMeshRenderer.material.SetTexture("_BaseMap", textSet.albedoMap);
if (textSet.metalicMap)
{
skinnedMeshRenderer.material.EnableKeyword ("_METALLICGLOSSMAP");
skinnedMeshRenderer.material.SetTexture("_MetallicGlossMap", textSet.metalicMap);
}
if (textSet.normalMap)
{
skinnedMeshRenderer.material.EnableKeyword("_NORMALMAP");
skinnedMeshRenderer.material.SetTexture("_BumpMap", textSet.normalMap);
}
if (textSet.ambientOcullsionMap)
{
skinnedMeshRenderer.material.EnableKeyword("_OCCLUSIONMAP");
skinnedMeshRenderer.material.SetTexture("_OcclusionMap", textSet.ambientOcullsionMap);
}
if (textSet.emissionMap)
{
skinnedMeshRenderer.material.EnableKeyword("_EMISSION");
skinnedMeshRenderer.material.SetTexture("_EmissionColor", textSet.emissionMap);
}
}
This applies textures. Take a look:
Now when I click on the material. The look changes, please check this out:
As you can see on the second picture after I clicked on the material the look of the body changed. I am not sure does it change something around the Ambient Occlusion or it changes the smoothness/glossiness of the gameobject.
My question is why the look changes when I only open the material and how can I make so that in runtime it attaches the textures to the material so that once I click on the material all stays the same?
private Color solveColor;
void Start()
{
Color[] colors = { Color.cyan, Color.red, Color.green, new Color(245, 195, 29), Color.yellow, Color.magenta };
int lengthOfColors = colors.Length;
int solveColor = UnityEngine.Random.Range(0, lengthOfColors);
}
private void start()
{
GetComponent<MeshRenderer>().material.color = solveColor;
}
private void FixedUpdate()
{
// Set the balls speed when it should travel
if (isTraveling) {
rb.velocity = travelDirection * speed;
}
// Paint the ground
Collider[] hitColliders = Physics.OverlapSphere(transform.position - (Vector3.up/2), .05f);
int i = 0;
while (i < hitColliders.Length)
{
GroundPiece ground = hitColliders[i].transform.GetComponent<GroundPiece>();
if (ground && !ground.isColored)
{
ground.Colored(solveColor);
}
The above code is supposed to pick one color from the colors array and assign it to both the ball and balls painting ability (whenever the ball collides with the ground it changes its color) however the paint the ball leaves is always black and the ball itself is always orange (pretty sure the ball color is coming from its default). I can't figure out why this is happening any help is very appreciated.
Thank you for your time
In the code you provided, nowhere do you set the material color of the ball again aside from Start. If you want to have the particles behind the ball leave different colors, you will need to instantiate a new instance of the material. The reason for this is because materials in Unity are default shared between all instances of that particular material.
All of this info and a bit more can be found on the Material docs page.
As you have a fixed size of colors you are using, I would instead create 6 new materials and make an array of materials instead. Now, instead of randomly picking a color, pick a material and assign it to the ball or your new instanced painting ability. I am also confused as to why you are placing your array of colors inside of your Start function. It would be localized to that function only then. You also appear to have two Start functions, which is odd. One being the Monobehaviour Start and another start. Unless that is intended, your second start will not be run unless you call it.
Now to get to the solution I was talking about.
// assign these in the inspector to your new materials
[SerializeField] private List<Material> materials = new List<Material>();
private MeshRenderer meshRender;
private void Start()
{
meshRenderer = GetComponent<MeshRenderer>();
// set our first random Material
SetNewMaterialColor();
}
private void SetNewMaterialColor()
{
meshRenderer.material = GrabNewMaterial();
}
private void FixedUpdate()
{
// Set the balls speed when it should travel
if (isTraveling) {
rb.velocity = travelDirection * speed;
}
// Paint the ground
Collider[] hitColliders = Physics.OverlapSphere(transform.position - (Vector3.up/2), .05f);
int i = 0;
while (i < hitColliders.Length)
{
GroundPiece ground = hitColliders[i].transform.GetComponent<GroundPiece>();
if (ground && !ground.isColored)
{
// change this from a color to a material instead
ground.Colored(meshRenderer.material);
// set a new material to your main object
SetNewMaterialColor();
}
}
}
private Material GrabNewMaterial()
{
return materials[UnityEngine.Random.Range(0, materials.Count)];
}
You will need to change your Colored function to take in a Material instead of a Color. If you want the implementation to be more dynamic, you can instead create an instance of your material and set the color dynamically, but as you have a fixed size of colors I do not think you need to do that.
Edit: The one other option which involves creating a new shader would be to utilize [PerRendererData] meaning each object for a property field is rendered individually. I would go with the previous option as either option using shaders or instanced materials is a bit more complex.
You would need to use a MaterialPropertyBlock and can then assign the color when you want. It would look something like
public void SetNewColor()
{
// create a new material property block
MaterialPropertyBlock tmpBlock = new MaterialPropertyBlock();
// grab the current block from our renderer
meshRender.GetPropertyBlock(tmpBlock);
// set our changes to the block
tmpBlock.SetColor("_Color", YourColorHere);
// now apply our changes
tmpRend.SetPropertyBlock(tmpBlock);
}
And you would need to create a new shader that laters the Main Color property by using the PerRendererData attribute.
Properties
{
[PerRendererData]_Color("Main Color", Color) = (1,1,1,1)
...
Also, one other question I have is why you are using Physics.OverlapSphere instead of just an OnCollisionEnter? Or if your game is 2D, then OnCollisionEnter2D and let the physics engine handle how collisions work, then just change the colors when the collision occurs?
Edit: Here are the answer to your questions - let me know if you have more.
In the line "[SerializeField] private List materials = new
List();" which section do I need to replace with the
materials and how?
The line as is is fine. By using [SerializeField] it exposes this list to the editor. You will want to create several new duplicate materials that use your 6 different colors. Instead of setting the colors, you will be setting materials now. What I mean by inspector and editor is you can find the object that has this script on it in Unity, select it (it must be a Prefab or in the scene), then a tab of the Unity editor will populate with information about this object. Find the script portion and find the field materials. There should be a drop-down arrow, click it and set the number to 6 (or however many material swaps you want). Now create 6 new materials with your colors and drag them into the boxes that appeared.
Would it be something like writing "./Materials/Ball 1" in the () for
example?
Nope! You would be assigning this data in the inspector, so the data would be stored in the list without referencing them in code.
And I'm not sure how to assign this to my ball using "[SerializeField]
private GameObject paintObject = null;"
Similarly, this would appear in the inspector. However, remove this line as I misunderstood your original question and accidentally left this in. I assumed that your paint object was a Prefab that you were spawning after the ball bounced, not the ground that you were changing the color of.
I get the error "Argument 1: cannot convert from
'UnityEngine.Material' to 'UnityEngine.Color'"
Yep! So as I mentioned in the comments, your function call to your paint object is most likely currently taking a Color parameter. As I changed your implementation to instead directly set Material, you will need to change how that function signature. Specifically the line:
ground.Colored(meshRenderer.material);
You have some object ground that is of type GroundPiece and has a function called Colored. I assume it currently look something like:
public void Colored(Color color){...}
You want to change this instead to:
public void Colored(Material mat{...}
After changing it, instead of changing the ground's color in this script, you would change its material directly. Let me know if you have more questions.
I want to be able to hover over certain game objects and the object changes material. I cannot figure out why my game object won't change material when I hover over it. I have made sure and added the materials in the inspector. I have tried multiple ways to get it to work but still no luck. I am using unity 2018.4.16. I have tried using different examples and looked at the documentation, but alas I am stuck in the water. Any help would be very appreciated.
public Material startColor;
public Material mouseOverColor;
Renderer rend;
void OnMouseOver()
{
rend.sharedMaterial = mouseOverColor;
}
void OnMouseExit()
{
rend.sharedMaterial = startColor;
}
// Start is called before the first frame update
void Start()
{
rend = GetComponent<Renderer>();
rend.enabled = true;
rend.sharedMaterial = startColor;
}
I ended up finding a solution. I needed to add a "Rigidbody" component and then checking "Is Kinematic" in the inspector as well as adding a "mesh collider" component, and now it works for anyone who is having a similar issue.
I am making a game for Android using Unity 5.4.0f3 and am having trouble fading out a sprite's color.a value. I have tried animations, but they don't seem to work for me. I have tried using the code from here and here, but those didn't work either. I want the sprite to fade out over about 1 second when it is tapped. I think I need to use a for loop and Mathf.Lerp. Please help.
Edit: Here is an image of the Inspector view of the object I want to fade out.
Sure change sprRender.color, not color.a. Simple code for you, Fadeout worked. Add your advanced.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(SpriteRenderer))]
public class FadeOut : MonoBehaviour {
SpriteRenderer sprRender;
void Start()
{
sprRender = GetComponent<SpriteRenderer>();
}
void Update()
{
sprRender.color -= new Color(0, 0, 0, Time.deltaTime);
}
}
Because Sprite-Default material is NOT modifiable.
Try this instead:
Easiest way:
/* Modify SpriteRenderer.color instead of Material.color */
//Get the renderer via GetComponent or have it cached previously
var renderer = GetComponent<SpriteRenderer>();
renderer.color = new Color(0f, 0f, 0f, 0f); // Do your lerping stuff with this property
If you still want to modify Material
Create a new material in Project tab and name it whatever you
want. Project tab -> Create -> Material.
Assign it a shader like in the below image.
Assign the newly created material to your Sprite Renderer
Material slot. Notice that now you can modify material color from
the inspector. It has not been grayed out any more. You should run
you code again and it should work.
I'm pretty sure this will be an easy fix, but I don't see it.
I want to change the texture on the material a projector is projecting.
This is what I have
using UnityEngine;
using System.Collections;
public class ShowPresentation : MonoBehaviour {
private GameObject SceneProjector;
private Material proj;
public Texture2D NewTexture;
void Start () {
SceneProjector = GameObject.FindGameObjectWithTag("Projector") ;
proj = SceneProjector.GetComponent<Projector>().material;
NewTexture = Resources.LoadAssetAtPath ("Assets/Textures/Wood.tga", typeof(Object)) as Texture2D;
proj.SetTexture("_MainTex", NewTexture);
}
void Update () {
Debug.Log (proj);
Debug.Log(NewTexture);
}
}
Everything used to be at update but even in Start it won't work.
The debug logs show that it can find the material and texture, so it has to be something to do with the settexture
Help would be much appreciated
i dont know what you did but this is the example from unity documentation. you can set it to the script of the object that you want to change its texture.
_BumpMap is the normal map
public Texture bumpMap;
renderer.material.SetTexture("_BumpMap", bumpMap);