- Home /
What's wrong with this script?
#pragma strict
@MenuItem ("Terrain/Set Detail Layers")
static function SetDetailLayers () {
var splatmap : Texture2D = Selection.activeObject as Texture2D;
if (splatmap == null) {
EditorUtility.DisplayDialog("No texture selected", "Please select a texture", "Cancel");
return;
}
var wi = splatmap.width;
if (splatmap.height != wi) {
EditorUtility.DisplayDialog("Wrong size", "Splatmap width and height must be the same", "Cancel");
return;
}
if (Mathf.ClosestPowerOfTwo(wi) != wi) {
EditorUtility.DisplayDialog("Wrong size", "Splatmap width and height must be a power of two", "Cancel");
return;
}
var terrain = Terrain.activeTerrain.terrainData;
var w : int = terrain.detailWidth;
var h : int = terrain.detailHeight;
var i : int = 0;
var splatmapData : int[,] = terrain.GetDetailLayer(0,0,w,h,0);
var mapColors : Color[] = splatmap.GetPixels();
var grayScales : float[] = new float[mapColors.length];
for(i=0;i<mapColors.length;i++){
grayScales[i] = mapColors[i].grayscale;
}
Debug.Log(grayScales);
//var splatDetail : int[,] = grayScales;
//Debug.Log(splatDetail);
var x : int = 0;
var y : int = 0;
for (y = 0; y < w; y++) {
for (x = 0; x < w; x++) {
splatmapData[x,y] = grayScales[y];
}
}
terrain.SetDetailLayer(0, 0, 0, splatmapData);
}
Edit your post, select the code, hit the 010/101 button to format it, and indicate line 30, what error is it giving?
Answer by Mizuho · Jul 25, 2012 at 09:51 AM
I don't see how it's a problem with nulls. The obvious problem is that he's trying to set a int[,]
multi-dimensional array using a Color[]
array. I'm sorry, whoever wrote this code, but int[,] != Color[]
. Simple as that.
This is your culprit:
var mapColors : Color[] = splatmap.GetPixels();
var splatDetail : int[,] = mapColors;
I'm not sure how exactly you intended to convert that over (I assume it was int[width,height]
?), but just dropping in mapColors
isn't going to work. You'll need to cycle through all the Color
s and put them into that splatDetail yourself.
On another note, Debug.Log(splatDetail);
isn't going to give you much other than null
or the System.Type
for multi-dimensional int
arrays.
his non-strict version of the code he had posted was complaining of a null reference exception
the point is that I can convert Color to int[,,], but if I want to use a grayscale texture to paint detail layers, how can I do that? I tried with splatmap.GetPixels().grayscale, but this doesn't work :(
You need to get a specific pixel and get the grayscale value of that. Unless JS has convenience syntax that allows you to call a property on all contents of an array, that code isn't going to work.
This however should do:
float greyScale = splatmap.GetPixel(x, z).grayscale;
For each pixel, but it might be more efficient to get the color[] array back and walk it as I suggested below.
pragma strict
This is recommended in the Unity docs. I don't have this problem in C# :oD
I believe strict is also faster:
http://docs.unity3d.com/Documentation/ScriptReference/index.Performance_Optimization.html
Answer by Bovine · Jul 24, 2012 at 09:12 PM
Some variable on line 30 of your code is null.
Possibly splatmapData or terrain, but it's hard to say.
I suggest you add a breakpoint and then walk over the code to see what the null variable is - or count the lines in the script :o)
UPDATE:
Since you've changed the code in your example above to a strict version and the error has changed, it seems clear that you are trying to set a multi-dimensional array from a single dimensional array.
I have moved my comment up and deleted the comment:
Your Color array has one dimension and your splatDetail has two - Unity cannot convert one to the other. What happened to the grayscale property?
You'll have to walk your one dimensional Color array manually:
splatmapData[x,y] = mapColors[x + y * w].grayscale;
Perhaps? or Similar depending the order of rows and columns returned by GetPixels(). Presuming this is the right width?
http://docs.unity3d.com/Documentation/ScriptReference/Texture2D.GetPixels.html
well, splatDetail is null, but I don't really undertand why...
if splatDetail is null, then mapColors.grayscale must also be null.
I know you didn't - I can't be more clear than that. The why is largely for you to understand by exa$$anonymous$$ing the code in the debugger. I was just trying to get you started, oh well.
ok, so I found the problem is in the "mapColors.grayscale;" but I don't know why...
Answer by Seth-Bergman · Jul 25, 2012 at 10:11 AM
have you tried separating the two? Once mapColors is filled, cycle through it and grab the grayscale values..
var mapColors : Color[] = splatmap.GetPixels();
var grayScales : float[] = new float[mapColors.length];
for(var i=0;i<mapColors.length;i++){
grayScales[i] = mapColors[i].grayscale;
}
then you would walk through it:
var counter = 0;
for(var j=0;j<splatmap.height;j++){
for(var k=0;k<splatmap.width;k++){
splatMapData[k,j] = (grayscales[counter] * 10) as int;
counter++;
}
}
or something similar..
EDIT:
if you're using this to call SetDetailLayer, though, then you need an int array, so instead maybe:
for(var j=0;j<splatmap.height;j++){
for(var k=0;k<splatmap.width;k++){
splatMapData[k,j] = parseInt(grayscales[counter] * 10);
counter++;
}
}
doesn't work, because in that manner u just pick out floats from the color array, while if I set directly grayscale to the Color[] it says me that grayscale is not a component of Color[]
oh my mistake, it would need to be a separate array, I'll fix it... ok fixed, not clear whether this is actually your current issue, but this creates an array of the grayscales from the color array
as suggested before, you would then need to walk through it to re-allot it to a 2d array of course
edited for that too..
what is it you are trying to change? Either way, looks like SetDetail$$anonymous$$aps takes an int[,].. which tells the number of details at that coordinate. is that what you want?
Answer by cod · Jul 25, 2012 at 01:43 PM
Here's the complete script
#pragma strict
@MenuItem ("Terrain/Set Detail Layers")
static function SetDetailLayers () {
var splatmap : Texture2D = Selection.activeObject as Texture2D;
if (splatmap == null) {
EditorUtility.DisplayDialog("No texture selected", "Please select a texture", "Cancel");
return;
}
var wi = splatmap.width;
if (splatmap.height != wi) {
EditorUtility.DisplayDialog("Wrong size", "Splatmap width and height must be the same", "Cancel");
return;
}
if (Mathf.ClosestPowerOfTwo(wi) != wi) {
EditorUtility.DisplayDialog("Wrong size", "Splatmap width and height must be a power of two", "Cancel");
return;
}
var terrain = Terrain.activeTerrain.terrainData;
var w : int = terrain.detailWidth;
var h : int = terrain.detailHeight;
var i : int = 0;
var splatmapData : int[,] = terrain.GetDetailLayer(0,0,w,h,0);
var mapColors : Color[] = splatmap.GetPixels();
var grayScales : float[] = new float[mapColors.length];
for(i=0;i<mapColors.length;i++){
grayScales[i] = mapColors[i].grayscale;
}
var j : int = 0;
var k : int = 0;
var counter : int = 0;
for(j=0; j<splatmap.height;j++){
for(k=0; k
Your answer
Follow this Question
Related Questions
How to smooth out the values? 1 Answer
Texture 2D array to GUI.Window rows iOS 0 Answers
loading a folder of textures to an array 0 Answers
PackTextures Horizontally? (1 Row) or Alternative Method 1 Answer
Binding Key to first item in array 0 Answers