Setting material in Unity in run time issue - unity3d

When I change material in runtime with this it does not work
expoSceneLarge.GetComponent<Renderer>().materials[0] = availableMaterials[selectedMaterialIndex];
however using this
expoSceneLarge.GetComponent<Renderer>().material = availableMaterials[selectedMaterialIndex];
material is being changed in run time.
What confuses me is that material, according to Unity return the first element in materials attached to renderer, so why materials[0] does not work?

Found a solution.
I has to create new array of materials, change the once I was interested in and the assign whole array to mesh renderer. Here is a a full code for future reference.
var newMaterials = new Material[_expoMaterials.Count()];
for(int i = 0; i < newMaterials.Count(); i++)
{
// i = 1 for floor
if(i == 1)
{
newMaterials[i] = availableMaterials[selectedMaterialIndex];
}
else
{
newMaterials[i] = _expoMaterials[i];
}
}
expoSceneLarge.GetComponent<MeshRenderer>().materials = newMaterials;

Related

Why does the scale value of the object change?

I'm trying to learn the Unity game engine. I'm trying to develop a mechanic. Objects are created from the object pool in a fixed location. However, when I make them child object of a different object and finish the process and deactivate them, the scale values ​​of the reconstructed objects change. Why is this happening?
private IEnumerator Create_Green_Pizzas(List<Transform> pizzas)
{
int pizzaCount = 0;
while (pizzaCount < pizzas.Count)
{
currentColumn++;
if (currentColumn >= columnCount)
{
currentRow++;
currentColumn = 0;
}
if (currentRow >= rowCount)
{
pizzaLevel++;
currentRow = 0;
currentColumn = 0;
}
for (int i = 0; i < pizzas.Count; i++)
{
if (!pizzas[i].gameObject.activeInHierarchy)
{
pizzas[i].gameObject.SetActive(true);
pizzas[i].parent = pizzasParent;
pizzas[i].rotation = transform.rotation;
pizzas[i].position = initialSlotPosition + new Vector3(((pizzas[i].lossyScale.x) * currentColumn), (pizzaLevel * pizzas[i].lossyScale.y), ((-pizzas[i].lossyScale.z) * currentRow));
pizzas[i].GetComponent<MeshRenderer>().material.color = Color.green;
_player.collectableGreenPizzas.Add(pizzas[i]);
pizzaCount++;
yield return new WaitForSeconds(0.5f);
break;
}
}
}
}
Setting gameobject's the parent might be the cause, so instead of:
pizzas[i].parent = pizzasParent;
try instead:
pizzas[i].SetParent(pizzasParent, true);
You can find more info about this method Here
If a GameObject has a parent, they become part of the parent's referential, their transform is now a local transform that depends on the parent's transform.
This means that if a child transform has a scale of (1, 1, 1), has the same scale as its parent.
Here's a small clip that illustrates this, two sphere that are the same size while they both have a different scale.
However you can force the GameObject to preserve its coordinates and scale using this line :
child.SetParent(parent, true);

How can i convert FBX embedded texture to TArray<uint8> Data?

I want to make a function that returns the textures built into FBX as 'TArray[uint8]' or UTexture2D using Assimp library. This is my code.
void UAIScene::GetTexture2D(bool& IsValid, UTexture2D*& ReturnedTexture)
{
IsValid = false;
UTexture2D* LoadedT2D = NULL;
TArray<uint8> RawFileData;
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
aiString texture_file;
scene->mMaterials[0]->Get(AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0), texture_file);
if (const aiTexture* texture = scene->GetEmbeddedTexture(texture_file.C_Str())) {
//Here Is Problem
RawFileData = *(TArray<uint8>*) & (texture->pcData[0]);
TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(ImageWrapperModule.DetectImageFormat(RawFileData.GetData(), RawFileData.Num()));
if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(RawFileData.GetData(), RawFileData.Num()))
{
TArray<uint8> UncompressedBRGA;
if (ImageWrapper->GetRaw(ERGBFormat::BGRA, (int32)8, UncompressedBRGA))
{
LoadedT2D = UTexture2D::CreateTransient(ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), PF_B8G8R8A8);
if (!LoadedT2D)
{
IsValid = false;
}
void* TextureData = LoadedT2D->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
FMemory::Memcpy(TextureData, UncompressedBRGA.GetData(), UncompressedBRGA.Num());
LoadedT2D->PlatformData->Mips[0].BulkData.Unlock();
LoadedT2D->UpdateResource();
}
}
ReturnedTexture = LoadedT2D;
IsValid = true;
}
else {
}
}
But Assimp's raw image file doesn't cast to TArray. Where do I have to fix to change Assimp's aiTexel to TArray?
This comment is my attempt.
//TextureBinary = *Cast<TArray<uint8>>(texture->pcData);
If I get the documentation for TArray right you need to copy the data with memcpy. You need the starting address of the embedded texture, the start-pointer of the TArray instance by GetData() or something similar and the size for the embedded texture which shall get copyied:
memcpy(RawFileData.GetData(), static_cast<void*>(&LoadedT2D), texSize);
Just make sure that the buffer-size for the TArray instance is big enough. Hope that helps.

unity custom editor with arrays

I'm in the process of creating a game and the scripts are getting pretty big. For more clarity I want to work with the custom editor. But I have problems with types like classes, gameobjects and especially arrays.
As you can hopefully see in my picture, it is very easy to make basic types like string and float etc visible. But how does it work with an array ? and especially if the array is still a class or a rigidbody or a gameobject ? I need if possible a good explanation or direct solution. I would be very grateful for your help
enter image description here
Note: If your just looking to beautify/improve your inspector, rather than doing it as an actual project/experience, your better off looking for plugins.
The Custom-Editor API that Unity provides are a bunch of Tools, not a House. You will end up pouring a lot of effort into making your inspector 'look neater'.
If you just want to create a game, use plugins to decorate your inspector.
MyBox is one of the Plugins I use, and recommend.
Now back to the question
I managed to pull it off by using a combination of EditorGUILayout.Foldout and looping through the array size to create multiple EditorGUILayout.IntField.
// True if the user 'opened' up the array on inspector.
private bool countIntsOpened;
public override void OnInspectorGUI() {
var myTarget = (N_USE)target;
myTarget.myTest.name = EditorGUILayout.TextField("see name", myTarget.myTest.name);
myTarget.myTest.countOnly = EditorGUILayout.FloatField("see float", myTarget.myTest.countOnly);
// Create int array field
myTarget.myTest.countInts = IntArrayField("see int[]", ref countIntsOpened, myTarget.myTest.countInts);
}
public int[] IntArrayField(string label, ref bool open, int[] array) {
// Create a foldout
open = EditorGUILayout.Foldout(open, label);
int newSize = array.Length;
// Show values if foldout was opened.
if (open) {
// Int-field to set array size
newSize = EditorGUILayout.IntField("Size", newSize);
newSize = newSize < 0 ? 0 : newSize;
// Creates a spacing between the input for array-size, and the array values.
EditorGUILayout.Space();
// Resize if user input a new array length
if (newSize != array.Length) {
array = ResizeArray(array, newSize);
}
// Make multiple int-fields based on the length given
for (var i = 0; i < newSize; ++i) {
array[i] = EditorGUILayout.IntField($"Value-{i}", array[i]);
}
}
return array;
}
private static T[] ResizeArray<T>(T[] array, int size) {
T[] newArray = new T[size];
for (var i = 0; i < size; i++) {
if (i < array.Length) {
newArray[i] = array[i];
}
}
return newArray;
}
Not as nice or neat as Unity's default. But gets the job done.
P.S: You can copy-paste your code when asking questions, rather than posting it as an image. It helps a lot.

Leaflet draw delete features with property

Is it possible to delete multiple features from geojson at once by checking property value?
Using for example code below or using Leaflet draw?
function deleteArea() {
var layers = featureGroup.getLayers();
for (var i = 0; i < layers.length; i++) {
if (layers[i].feature.properties.N == 1)
{
"DELETE?" layer[i];
};
}
};
I have big map and some markers have property: feature.properties.N=1. I can delete them using leaflet draw clicking one by one because I changed marker to red for those layers. But it takes some time.. Is it possible to to this at once?
Thank you very much for your time !
Sure you can simply remove the markers from the map / featuregroup with layer.removeFrom(featureGroup)
function deleteArea() {
var layers = featureGroup.getLayers();
for (var i = 0; i < layers.length; i++) {
if (layers[i].feature.properties.N == 1){
layer[i].removeFrom(featureGroup);
};
}
};
PS: I prefer to use Leaflet-Geoman because it is more modern and is still being supported and gets new features

Flash : How to write roll over coding for grid in array which is similar colour movieclips nearby?

Flash AS3:
I just need to know how to check a condition for roll over effect on similar colour movieclips which is near by in a group of random colours movieclips in a grid whereas it is using 2D Array in flash AS3.or
I just need roll over event which i wrote is onBoxOver event function, in that the object which i am targetting is only getting rollover or getting alpha changes. But i need to know how to make rollover for similar colour which are all nearby.
The code which i wrote is below for your reference.
Flash AS3::
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class playGame extends MovieClip
{
public static var totalRowBoxes:Number = 13;
public static var totalColumnBoxes:Number = 12;
public static var rowGap:Number = 30;
public static var columnGap:Number = 30;
public static var totalColorBoxes:Number = 8;
public static var boxCollection:Array = new Array();
public static var boxCollection1:Array = new Array();
public function playGame(theGame:main)
{
// constructor code
addBoxOnStage();
}
private function addBoxOnStage():void
{
var borderCont:Banner = new Banner();
var scoreclipCont:scoreclip = new scoreclip();
addChild(borderCont);
addChild(scoreclipCont);
scoreclipCont.x = 0;
scoreclipCont.y = 0;
createLevel(1);
for (var i:Number = 0; i<totalRowBoxes; i++)
{
boxCollection[i] = new Array(i);
for (var j:Number = 0; j<totalColumnBoxes; j++)
{
var squareCont:square = new square();
squareCont.x = 30 + (i * rowGap);
squareCont.y = 30 + (j * columnGap);
squareCont.name = i + "_" + j;
var boxCollection1:Array = new Array();
boxCollection1[0] = Math.round(Math.random() * 8);
boxCollection1[1] = squareCont;
var boxColour:Number = new Number();
boxColour = boxCollection1[0];
boxCollection[i][j] = boxCollection1[1];
addChild(squareCont);
squareCont.gotoAndStop(boxCollection1[0]);
squareCont.addEventListener(MouseEvent.MOUSE_OVER, onBoxOver); squareCont.addEventListener(MouseEvent.MOUSE_OUT, onBoxOut);
squareCont.addEventListener(MouseEvent.CLICK, onBoxClick);
}
}
}
private function onBoxClick(eve:MouseEvent):void
{
}
private function onBoxOver(eve:MouseEvent):void
{
for (var i:Number=0; i< totalRowBoxes; i++)
{
for (var j:Number=0; j<totalColumnBoxes; j++)
{
eve.target.alpha = 0.3;
// trace(boxCollection[i][j].currentFrame)
trace(eve.target);
}
}
}
private function onBoxOut(eve:MouseEvent):void
{
eve.target.alpha = 1;
}
private function createLevel(lvl):void
{
}
}
}
![My Game screenshot here colourbox][1]
Thanks in Advance. Greatly Appreciable for the reply.
Hi this is the image or screenshot of my project. In that image there are 8 colours randomly arranged. whenever i make mouse position or rollover on any box , the condition should check whether the same colour occurs around the box(eg.top, down, left, right) which i am making rollover.
1.If the same colour occur on the top of the box which i am pointing the cursor , the top box and the box which i am pointing both should get less alpha, else only the pointing box should get less alpha. this is my concept friends. please go through the image and let me know if u have any doubts.
I am still unsure what you mean by 'nearby'. (neighbour tiles? adjacent of similar colour?...)
If 'nearby' means adjacent, you need to read about flood fill algorithms. There is a good wiki article about this. You would use that to crawl through the list of tiles similar enough to trigger the effect you want.
I also don't know what 'similar' colour means in your project. You will need a method to determine weather two colours are similar. There is a stackoverflow question re: similar colour detection. It has a good answer to start you out in your research. look here.