Material property change via code doesn't show - c#

I'm using Unity 2020.3.3f1 (HDRP)
I have a prefab (cube) which has a emissive material on it.
After pressing the mouse button, I want it to increase its Emission intensity by 10.
Problem that I encountered:
The Inspector shows me that the Intensity is infact changing but the Game does not represent these changes (this means it's not getting "brighter" even though the material property says it does).
Now when I increase the amount via the Inspector manually, just by 0.1 even, all of the sudden the changes are now visible.
I think I tried everything now without luck...
How the code looks like in a nutshell:
public Material cubeMaterial;
private float intensity = 10;
if("mouseClick"){
intensity += 100;
cubeMaterial.setFloat("_EmissiveIntensity", intensity);
}

I suppose you are using the default HDRP/Lit shader for your material. If that's so, you can access your cube emission intensity via "_EmissiveColor" shader keyword like this:
cubeMaterial.GetColor("_EmissiveColor");
which returns a Color value.
And you can modify it in a similar way:
cubeMaterial.SetColor("_EmissiveColor", startingEmission * 1.1f);
In general, when working with HDRP material shaders it's always safe to look up the shader keywords, you can do it via navigating to your material in the inspector, clicking the kogwheel and selecting edit shader, which opens the .shader file.

If you intend to modify only this gameObject's material, I recommand you to use MaterialPropertyBlock to modify a property of your material.
If you don't, a new material will be created behind the scene and can lead to memory problems.
To do this, get a reference to the gameObject's renderer, get its property block, modify it and reassign the modified property block.
You can learn more on this documentation
Hope that helped ;)

Related

Is there any way to render an object while standing in it?

I have a first person controller and currently if I walk into a slightly transparent object, it disappears until I walk out of it.
I have a 'water' cube object that is very light blue and transparent, and when I move my camera into third person view then enter the water, my screen turns light blue which is good. In first person mode (which is what I'm trying to figure out), the cube disappears and my screen color remains the same.
I know it has something to do with my camera but even after going through all the features on unity docs and changing a few settings in the inspector, it all remains the same.
Like mentioned in the comments your cube is not visible because the backside of its faces is being culled, meaning they are not rendered. This is not a camera setting but a property of the shader your water cubes material is using.
You could create get a duplicate of the shader your are using where you add Cull Off to change this.
Read about it here.
If you want to go that route you need the source files for your shader. Assuming it is one of the Unity Built in shaders you can get them from the Unity Download archive here for your Unity version.
Clipping the camera trough objects is rarely a desired and you should look at a different way of achieving your effect like using a post-processing volume because the "water" would still be a cube and be drawn behind everything in front of its faces.
For example in a FPS type game this would result in the gun not changing color.

How to render multiple polygons that does XOR operation directly on overlapping regions in godot? [duplicate]

So I'm looking to create an effect of having a bubble around my player which, when he enters a hidden area (hidden by tilemaps) the bubble activates and it essentially has an xray effect. So I can see the background, the ground and all the items inside the area I just can't see the blocks themselves.
So pretty much going from this
To this
And as I go further in the more gets revealed
I have no idea what to even begin searching for this. So any direction would be greatly appreciated
First of all, I want to get something out of the way: Making things appear when they are nearby the player is easy, you use a light and a shader. Making things disappear when they are nearby the player by that approach is impossible in 2D (3D has flags_use_shadow_to_opacity).
This is the plan: We are going to create a texture that will work as mask for what to show and what not to show. Then we will use that texture mask with a shader to make a material that selectively disappears. To create that texture, we are going to use a Viewport, so we can get a ViewportTexture from it.
The Viewport setup is like this:
Viewport
├ ColorRect
└ Sprite
Set the Viewport with the following properties:
Size: give it the window size (the default is 1024 by 600)
Hdr: disable
Disable 3D: enable
Usage: 2D
Update mode: Always
For the Sprite you want a grayscale texture, perhaps with transparency. It will be the shape you want to reveal around the player.
And for the ColorRect you want to set the background color as either black or white. Whatever is the opposite of the color on the Sprite.
Next, you are going to attach a script to the Viewport. It has to deal with two concerns:
Move the Sprite to match the position of the player. That looks like this:
extends Viewport
export var target_path:NodePath
func _process(_delta:float) -> void:
var target := get_node_or_null(target_path) as Node2D
if target == null:
return
$Sprite.position = target.get_viewport().get_canvas_transform().origin
And you are going to set the target_path to reference the player avatar.
In this code target.get_viewport().get_canvas_transform().origin will give us the position of the target node (the player avatar) on the screen. And we are placing the Sprite to match.
Handle window resizes. That looks like this:
func _ready():
# warning-ignore:return_value_discarded
get_tree().get_root().connect("size_changed", self, "_on_size_changed")
func _on_size_changed():
size = get_tree().get_root().size
In this code we connect to the "size_changed" of the root Viewport (the one associated with the Window), and change the size of this Viewport to match.
The next thing is the shader. Go to your TileMap or whatever you want to make disappear and add a shader material. This is the code for it:
shader_type canvas_item;
uniform sampler2D mask;
void fragment()
{
COLOR.rgb = texture(TEXTURE, UV).rgb;
COLOR.a = texture(mask, SCREEN_UV).r;
}
As you can see, the first line will be setting the red, green, and blue channels to match the texture the node already has. But the alpha channel will be set to one of the channels (the red one in this case) of the mask texture.
Note: The above code will make whatever is in the black parts fully invisible, and whatever is in the white parts fully visible. If you want to invert that, change COLOR.a = texture(mask, SCREEN_UV).r; to COLOR.a = 1.0 - texture(mask, SCREEN_UV).r;.
We, of course, need to set that mask texture. After you set that code, there should be a shader param under the shader material called "Mask", set it to a new ViewportTexture and set the Viewport to the one we set before.
And we are done.
I tested this with this texture from publicdomainvectors.org:
Plus some tiles from Kenney. They are all, of course, under public domain.
This is how it looks like:
Experiment with different textures for different results. Also, you can add a shader to the Sprite for extra effect. For example add some ripples, by giving a shader material to the Sprite with code like this one:
shader_type canvas_item;
void fragment()
{
float width = SCREEN_PIXEL_SIZE.x * 16.0;
COLOR = texture(TEXTURE, vec2(UV.x + sin(UV.y * 32.0 + TIME * 2.0) * width, UV.y));
}
So you get this result:
There is an instant when the above animation stutters. That is because I didn't cut the loop perfectly. Not an issue in game. Also the animation has much less frames per second than the game would.
Addendum A couple things I want to add:
You can create a texture by other means. I have a couple other answer where I cover some of it
How can I bake 2D sprites in Godot at runtime? where we use blit_rect. You might also be interested in blit_rect_mask.
Godot repeating breaks script where we are using lockbits.
I wrote a shader that outputs on the alpha channel here. Other options include:
Using BackBufferCopy.
To discard fragments.

Instantiated 2D text doesn't show up in Unity

Excuse me for any grammatical errors. (I know that there are many questions like this here, but I haven't found a solution yet).
I'm trying to instantiate a 2d object with a 2d text, the problem here is that the text is invisible when instantiated. Yes, I know that I have to set a canvas as parent of it but it is still not working...
Code:
Instantiate(levelAsteroid, new Vector3(-7, 2.25f, 0), Quaternion.identity,
GameObject.FindGameObjectWithTag ("Canvas").transform);
Unity hierarchy, when the object is instantiated:
Canvas settings:
Update:
I think I found the problem.
If I just instantiate the object, it works fine, the text is visible, but if I try to change the text from the script, the text becomes corrupt, after that the text won't never show up not even if I put the object in the canvas manually.
FIXED:
The problem seems to be the way I used to change the text..
Before, I used to instantiate the object and change the text from a script attached to the GameController, now I change the text from a script attached to the object that has the text as child.
Before:
(Script attached to the GameController):
public GameObject exampleOfObj;
void instantiateObj(){
object = Instantiate(exampleOfObj, new Vector3(-800, 300f, 0), Quaternion.identity);
object.transform.SetParent (GameObject.FindGameObjectWithTag ("Canvas").transform, false);
objectText.SetText ("Text: " + value);
}
I simply removed the call to the "SetText" method and I have put this into the script that is attached to the object that I'm instantiating.
I found a solution but I don't understand why it was a problem.
It's hard to figure out your issue without additional information. Possible solution is use Transform.SetParent method with worldPositionStays parameter set to false instead of instantiating on parent transform. You can find troubleshooting of similar issues in Unity Documentation. See Instantiating the UI element section.
I did exactly as you did and it is showing the text. My canvas settings are :
Render Mode : Scale Space - Camera (Camera Attached)
UI Scale Mode : Scale With Screen Size
Reference Resolution : 1920 x 1440
Match = 0.5
Also make sure when you put the object in the canvas manually, it is also showing the text.

Can I make all the contents of a GameObject transparent? (Unity3D 2017.3)

I'm making an ARCore app (that shouldn't matter, should it?) that has the model you're placing visible at the center of the screen before you place it. These models can be changed by the user.
The effect I'm trying to get is to have the model that you see before you place it 'ghosted'/translucent. What I would ideally like is having an empty GameObject (right now named GhostWrapper) that is a parent of the Ghost, and have everything inside GhostWrapper be translucent. This is because the Ghost model can change with user input, and the Ghost is then instantiated on the plane when the users wants to place it:
public void SetPlaceableModel(GameObject newModel)
{
PlaceableModel = newModel;
var pos = (Ghost != null) ? Ghost.transform.position : FirstPersonCamera.ScreenToWorldPoint(new Vector3(Screen.width / 2f, Screen.height / 2f, -100f));
var rot = (Ghost != null) ? Ghost.transform.rotation : Quaternion.identity;
Destroy(Ghost);
Ghost = Instantiate(PlaceableModel, pos, rot, GhostWrapper.transform);
}
I haven't been able to get the GhostWrapper to work, so the below is what I've tried to do directly to the Ghost, but I would prefer if I can have, essentially, the GhostWrapper cause everything inside it to appear to be translucent (it doesn't have to force its children to be transparent, but make them look like it).
I have Google'd it quite a bit, and have tried the ways suggested in the top results but almost all seem to be a variation of "get the MeshRenderer and set its .material.color to a transparent", and that doesn't seem to be working. I've also tried setting the material on my model to use different shaders and setting the colour alpha way down, but none of that seems to be working (all the answers I've seen appear to be from 2009-2014, so maybe they're just out-of-date?). I've also tried what the Unity documentation says to no avail.
I've thought about having the GhostWrapper be an actual box model that contains the Ghost and manipulating it to make the items inside appear transparent, but since the models can be vastly different shapes/sizes, and the user can move close to them, they could just move inside the box and it would lose the effect.
Can anyone help me with this?
Note: the models I'm using have the Unit/Texture shader. I am very open to changing that if I can get it to work, but I have changed it to several others, including using Standard and changing the Render Mode to Fade and Transparent. Still no luck.
You cannot modify the transparency of the Unit/Texture shader because there is no property in that shader that allows you to do so. One way to do this with the Unit/Texture shader is to get the base texture property, modify it with one of the Texture2D.SetPixelXXX functions and set the alpha to whatever you want. This is slow and unnecessary. Go this route only if you must use the Unit/Texture shader.
Use the Standard shader for this. Below are the steps when using the Standard shader.
1.Change the material Shader to Standard
2.Change the material's Rendering Mode to Fade
You can also do this from code with:
void changeMaterialModeToFadeMode(Renderer rd)
{
rd.material.SetFloat("_Mode", 2);
rd.material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
rd.material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
rd.material.SetInt("_ZWrite", 0);
rd.material.DisableKeyword("_ALPHATEST_ON");
rd.material.EnableKeyword("_ALPHABLEND_ON");
rd.material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
rd.material.renderQueue = 3000;
}
3.Finally, this is how to change the alpha:
GameObject ghost = ....;
Renderer ghostRenderer = ghost.GetComponent<Renderer>();
//Get current Color
Color meshColor = ghostRenderer.material.color;
//Set Alpha
const float alpha = 0.5f;
meshColor.a = alpha;
//Apply the new color to the material
ghostRenderer.material.color = meshColor;

Is there a way to make an object half opaque?

Is there a way to make an object half opaque? I tried this:
renderer.material.color = new Color(255f, 255f, 255f, 0.5f);
But it just makes the item white and the textures are no longer showing.
I have tried using Transparent/Bumped Specular but that makes the object too transparent, even when I don't want the object transparent at the time.
What I am trying to accomplish is to make it transparent to look like the player is inactive during a character selection screen. When the player presses A they will go to full opaque and then can select their player.
Editor Mode:
Play Mode:
So there are a couple things that I'd like to point out to you on this. First off, Unity's Color class is based on values from 0 to 1. So you have 255f in your RGB's, this is giving you what you expect now, but really it's just setting them to 1 in the constructor. So if you want colors in the future do:
new Color(rValue/255f, gValue/255f, bValue/255f, aValue/255f);
Just wanted to point that out while you were here.
So to your actual question, what you're doing with that line of code is you're saying, take the material attached to this object and make it completely white (if i'm wrong with 1,1,1 being white, someone please comment) and half transparent. But that doesn't apply to the object itself, that only applies to the material attached.
So if you want to modify the platform to be transparent, my recommendation is store both the transparent and non-transparent materials that you want on the script where you're changing which one is being used. Then in the code, instead of changing colors, change what material the renderer is using instead.
Hope this helps.

Categories