Search Unity

Internal_Create can only be called from the main thread. [SOLVED]

Discussion in 'Scripting' started by keenanwoodall, Mar 30, 2015.

  1. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    598
    I saw a few posts on this but couldn't make much sense of them. I'm trying to make a class that provides easy procedural texture making for wood. The class is simply called Wood. The constructor sets all of the private variables and calls a method that does all of the texture generation. Thats where the problem comes in. I've created an instance of the class in another script so that I can test it out. However, I'm getting errors, even in the editor, before clicking play.
    Code (csharp):
    1.  
    2. public static class Texture
    3.     {
    4.         [System.Serializable()]
    5.         public class Wood
    6.         {
    7.             //Public
    8.             public UnityEngine.Texture textureMap;
    9.             public UnityEngine.Texture normalMap;
    10.             //Private
    11.             public int width = 16;
    12.             public int height = 16;
    13.             public int seed = 1;
    14.  
    15.             public float ringRadius = 1f;
    16.             public float mainFrequency = 1f;
    17.             public float mainFrequencyPower = 0.1f;
    18.  
    19.             public float grainFrequency = 16f;
    20.             public int grainOctaves = 4;
    21.             public Vector3 grainScale = new Vector3(1f, 1f, 0.25f);
    22.  
    23.             public Vector3 woodPosition = new Vector3(-3f, 1.5f, 1.5f);
    24.             public Vector3 woodRotation = new Vector3(80, 20, 45);
    25.             public Vector3 woodScale = new Vector3(16, 16, 16);
    26.             public UnityEngine.Texture2D ramp;
    27.  
    28.             //Methods
    29.             public void Update()
    30.             {
    31.                 //Rings of wood
    32.                 var rings = new CoherentNoise.Generation.Patterns.Cylinders(ringRadius);
    33.                 //The wood's grain
    34.                 var grain = new CoherentNoise.Generation.Fractal.PinkNoise(seed);
    35.                 grain.Frequency = grainFrequency;
    36.                 grain.OctaveCount = grainOctaves;
    37.  
    38.                 var scaledGrain = grain.Scale(grainScale.x, grainScale.y, grainScale.z);
    39.            
    40.                 //Combination of the wood rings and grain
    41.                 var wood = 0.25f * scaledGrain + rings + 0.1f;
    42.                 //Add turbulence to the wood
    43.                 var perturbedWood = wood.Turbulence(mainFrequency, mainFrequencyPower, seed);
    44.                 //Grab a slice the wood
    45.                 var slice = perturbedWood.Translate(woodPosition.x, woodPosition.y, woodPosition.z).Rotate(woodRotation.x, woodRotation.y, woodRotation.z).Scale(woodScale.x, woodScale.y, woodScale.z);
    46.  
    47.                 this.textureMap = TextureMaker.RampTexture(width, height, slice, ramp);
    48.                 this.normalMap = TextureMaker.BumpMap(width, height, slice);
    49.             }
    50.             public void UpdateTexture()
    51.             {
    52.                 //Rings of wood
    53.                 var rings = new CoherentNoise.Generation.Patterns.Cylinders(ringRadius);
    54.                 //The wood's grain
    55.                 var grain = new CoherentNoise.Generation.Fractal.PinkNoise(seed);
    56.                 grain.Frequency = grainFrequency;
    57.                 grain.OctaveCount = grainOctaves;
    58.            
    59.                 var scaledGrain = grain.Scale(grainScale.x, grainScale.y, grainScale.z);
    60.            
    61.                 //Combination of the wood rings and grain
    62.                 var wood = 0.25f * scaledGrain + rings + 0.1f;
    63.                 //Add turbulence to the wood
    64.                 var perturbedWood = wood.Turbulence(mainFrequency, mainFrequencyPower, seed);
    65.                 //Grab a slice the wood
    66.                 var slice = perturbedWood.Translate(woodPosition.x, woodPosition.y, woodPosition.z).Rotate(woodRotation.x, woodRotation.y, woodRotation.z).Scale(woodScale.x, woodScale.y, woodScale.z);
    67.  
    68.                 this.textureMap = TextureMaker.RampTexture(width, height, slice, ramp);
    69.             }
    70.             public void UpdateNormal()
    71.             {
    72.                 //Rings of wood
    73.                 var rings = new CoherentNoise.Generation.Patterns.Cylinders(ringRadius);
    74.                 //The wood's grain
    75.                 var grain = new CoherentNoise.Generation.Fractal.PinkNoise(seed);
    76.                 grain.Frequency = grainFrequency;
    77.                 grain.OctaveCount = grainOctaves;
    78.            
    79.                 var scaledGrain = grain.Scale(grainScale.x, grainScale.y, grainScale.z);
    80.            
    81.                 //Combination of the wood rings and grain
    82.                 var wood = 0.25f * scaledGrain + rings + 0.1f;
    83.                 //Add turbulence to the wood
    84.                 var perturbedWood = wood.Turbulence(mainFrequency, mainFrequencyPower, seed);
    85.                 //Grab a slice the wood
    86.                 var slice = perturbedWood.Translate(woodPosition.x, woodPosition.y, woodPosition.z).Rotate(woodRotation.x, woodRotation.y, woodRotation.z).Scale(woodScale.x, woodScale.y, woodScale.z);
    87.            
    88.                 this.normalMap = TextureMaker.BumpMap(width, height, slice);
    89.             }
    90.             //Constructors
    91.             public Wood()
    92.             {
    93.                 Update();
    94.             }
    95.             public Wood(int width, int height, Texture2D ramp, bool createNormal)
    96.             {
    97.                 this.width = width;
    98.                 this.height = height;
    99.                 this.ramp = ramp;
    100.                 if(createNormal)
    101.                     Update();
    102.                 else
    103.                     UpdateTexture();
    104.             }
    105.             public Wood
    106.             (
    107.                 int width,
    108.                 int height,
    109.                 int seed,
    110.                 float ringRadius,
    111.                 float mainFrequency,
    112.                 float mainFrequencyPower,
    113.                 float grainFrequency,
    114.                 int grainOctaves,
    115.                 Vector3 grainScale,
    116.                 Vector3 woodPosition,
    117.                 Vector3 woodRotation,
    118.                 Vector3 woodScale,
    119.                 Texture2D ramp,
    120.                 bool createNormal
    121.             )
    122.             {
    123.                 this.width = width;
    124.                 this.height = height;
    125.                 this.seed = seed;
    126.                 this.ringRadius = ringRadius;
    127.                 this.mainFrequency = mainFrequency;
    128.                 this.mainFrequencyPower = mainFrequencyPower;
    129.                 this.grainFrequency = grainFrequency;
    130.                 this.grainOctaves = grainOctaves;
    131.                 this.grainScale = grainScale;
    132.                 this.woodPosition = woodPosition;
    133.                 this.woodRotation = woodRotation;
    134.                 this.woodScale = woodScale;
    135.                 this.ramp = ramp;
    136.                 if(createNormal)
    137.                     Update();
    138.                 else
    139.                     UpdateTexture();
    140.             }
    141.         }
    142.     }
    143.  
    The error takes me to the line in the Update method:
    Code (csharp):
    1.  
    2. this.textureMap = TextureMaker.RampTexture(width, height, slice, ramp);
    3.  
    It says:

    NullReferenceException: Object reference not set to an instance of an object
    CoherentNoise.Texturing.TextureMaker.RampTexture (Int32 width, Int32 height, CoherentNoise.Generator noise, UnityEngine.Texture2D ramp)
    Procedural+Texture+Wood.Update () (at Assets/Code/Framework/Procedural.cs:71)
    Procedural+Texture+Wood..ctor () (at Assets/Code/Framework/Procedural.cs:117)

    So that this error isn't returned, I tried putting the line(and the one below it) in an if statement
    Code (csharp):
    1.  
    2. if(ramp != null)
    3. {
    4.     this.textureMap = TextureMaker.RampTexture(width, height, slice, ramp);
    5.     this.normalMap = TextureMaker.BumpMap(width, height, slice);
    6. }
    However, when I add the if statement, I get two new errors (which point to the if statement):

    CompareBaseObjectsInternal can only be called from the main thread.
    Constructors and field initializers will be executed from the loading thread when loading a scene.
    Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.

    ArgumentException: CompareBaseObjectsInternal can only be called from the main thread.
    Constructors and field initializers will be executed from the loading thread when loading a scene.
    Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
    UnityEngine.Object.CompareBaseObjects (UnityEngine.Object lhs, UnityEngine.Object rhs) (at C:/buildslave/unity/build/artifacts/EditorGenerated/UnityEngineObject.cs:49)
    UnityEngine.Object.op_Inequality (UnityEngine.Object x, UnityEngine.Object y) (at C:/buildslave/unity/build/artifacts/EditorGenerated/UnityEngineObject.cs:162)
    Procedural+Texture+Wood.Update () (at Assets/Code/Framework/Procedural.cs:71)
    Procedural+Texture+Wood..ctor () (at Assets/Code/Framework/Procedural.cs:120)
     

    Attached Files:

    Last edited: Mar 30, 2015
  2. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    598
    Alright, so somehow this made it work... It's also strangely a lot faster too! Below this code, I'll post the code of the script that is utilizing the class, just in-case someone needs it. Instead of creating two variables to hold the textures, you can call a method that generates and returns the individually. Now you just set your texture equal to the function, as I'm doing in the second script.
    Code (csharp):
    1.  
    2. public static class Texture
    3.     {
    4.         [System.Serializable()]
    5.         public class Wood
    6.         {
    7.             //Public
    8.             [Range(1, 4096)]
    9.             public int width = 16;
    10.             [Range(1, 4096)]
    11.             public int height = 16;
    12.  
    13.             public int seed = 1;
    14.  
    15.             public float ringRadius = 1f;
    16.             public float mainFrequency = 1f;
    17.             public float mainFrequencyPower = 0.1f;
    18.  
    19.             public float grainFrequency = 16f;
    20.             public int grainOctaves = 4;
    21.             public Vector3 grainScale = new Vector3(1f, 1f, 0.25f);
    22.  
    23.             public Vector3 woodPosition = new Vector3(-3f, 1.5f, 1.5f);
    24.             public Vector3 woodRotation = new Vector3(80, 20, 45);
    25.             public Vector3 woodScale = new Vector3(16, 16, 16);
    26.             public UnityEngine.Texture2D ramp;
    27.  
    28.             //Methods
    29.             public UnityEngine.Texture GetTexture()
    30.             {
    31.                 //Rings of wood
    32.                 var rings = new CoherentNoise.Generation.Patterns.Cylinders(ringRadius);
    33.                 //The wood's grain
    34.                 var grain = new CoherentNoise.Generation.Fractal.PinkNoise(seed);
    35.                 grain.Frequency = grainFrequency;
    36.                 grain.OctaveCount = grainOctaves;
    37.              
    38.                 var scaledGrain = grain.Scale(grainScale.x, grainScale.y, grainScale.z);
    39.              
    40.                 //Combination of the wood rings and grain
    41.                 var wood = 0.25f * scaledGrain + rings + 0.1f;
    42.                 //Add turbulence to the wood
    43.                 var perturbedWood = wood.Turbulence(mainFrequency, mainFrequencyPower, seed);
    44.                 //Grab a slice the wood
    45.                 var slice = perturbedWood.Translate(woodPosition.x, woodPosition.y, woodPosition.z).Rotate(woodRotation.x, woodRotation.y, woodRotation.z).Scale(woodScale.x, woodScale.y, woodScale.z);
    46.              
    47.                 return TextureMaker.RampTexture(width, height, slice, ramp);
    48.             }
    49.             public UnityEngine.Texture GetNormal()
    50.             {
    51.                 //Rings of wood
    52.                 var rings = new CoherentNoise.Generation.Patterns.Cylinders(ringRadius);
    53.                 //The wood's grain
    54.                 var grain = new CoherentNoise.Generation.Fractal.PinkNoise(seed);
    55.                 grain.Frequency = grainFrequency;
    56.                 grain.OctaveCount = grainOctaves;
    57.              
    58.                 var scaledGrain = grain.Scale(grainScale.x, grainScale.y, grainScale.z);
    59.              
    60.                 //Combination of the wood rings and grain
    61.                 var wood = 0.25f * scaledGrain + rings + 0.1f;
    62.                 //Add turbulence to the wood
    63.                 var perturbedWood = wood.Turbulence(mainFrequency, mainFrequencyPower, seed);
    64.                 //Grab a slice the wood
    65.                 var slice = perturbedWood.Translate(woodPosition.x, woodPosition.y, woodPosition.z).Rotate(woodRotation.x, woodRotation.y, woodRotation.z).Scale(woodScale.x, woodScale.y, woodScale.z);
    66.              
    67.                 return TextureMaker.BumpMap(width, height, slice);
    68.             }
    69.             //Constructors
    70.             public Wood()
    71.             {
    72.  
    73.             }
    74.             public Wood(int width, int height, Texture2D ramp)
    75.             {
    76.                 this.width = width;
    77.                 this.height = height;
    78.                 this.ramp = ramp;
    79.             }
    80.             public Wood
    81.             (
    82.                 int width,
    83.                 int height,
    84.                 int seed,
    85.                 float ringRadius,
    86.                 float mainFrequency,
    87.                 float mainFrequencyPower,
    88.                 float grainFrequency,
    89.                 int grainOctaves,
    90.                 Vector3 grainScale,
    91.                 Vector3 woodPosition,
    92.                 Vector3 woodRotation,
    93.                 Vector3 woodScale,
    94.                 Texture2D ramp
    95.             )
    96.             {
    97.                 this.width = width;
    98.                 this.height = height;
    99.                 this.seed = seed;
    100.                 this.ringRadius = ringRadius;
    101.                 this.mainFrequency = mainFrequency;
    102.                 this.mainFrequencyPower = mainFrequencyPower;
    103.                 this.grainFrequency = grainFrequency;
    104.                 this.grainOctaves = grainOctaves;
    105.                 this.grainScale = grainScale;
    106.                 this.woodPosition = woodPosition;
    107.                 this.woodRotation = woodRotation;
    108.                 this.woodScale = woodScale;
    109.                 this.ramp = ramp;
    110.             }
    111.         }
    112.     }
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class ProceduralTexture : MonoBehaviour
    6. {
    7.     public Procedural.Texture.Wood wood;
    8.  
    9.     void Start ()
    10.     {
    11.  
    12.     }
    13.     void Update()
    14.     {
    15.         renderer.material.SetTexture("_MainTex", wood.GetTexture());
    16.         //renderer.material.SetTexture("_BumpMap", wood.normalMap);
    17.     }
    18. }
     
    Last edited: Mar 30, 2015