Posts Tagged ‘Unity3D’

Adding Text-To-Texture at Runtime in Unity3D Without Using Render Texture

Friday, August 20th, 2010

I was working on a library in Unity that was using a lot of 3D text and therefore was requiring a lot of draw calls. This got me thinking, since all the pieces of text were on the same orientation plane would there be a way instead to draw all the text to a one texture and render that instead. Another benefit of doing this would be you could then apply text at runtime to a non-flat mesh via a texture. This would allow you to do cool things like personalizing a player’s jersey with the user’s name, localizing complex in-game advertisements, etc. So I decided to look into this. What started as a few experiments turned into not so small project.

Doing research I found a way of achieving this using Render Texture. What you could do was by using either with GUI text or 3D Text place a camera to capture a single frame and render it to a texture. While not completely straightforward or easy it does work and allows quite a bit of flexibility on what you are creating. This method does come with a drawback, it needs Render Texture support. Only Unity Pro supports Render Texture, plus they are not supported on the iPhone (Unity Feature Breakdown).

Since my goal was to create a library that all Unity developers could use, this was not an acceptable solution.

My next idea was to manually draw the text to a texture using SetPixels. While the performance of writing to a texture using SetPixels is less than ideal, I only needed to do this once.
Note: The reason why this is so slow is after calling setPixel(s) you have to call Apply which send the whole texture to the GPU. The Apply method is unfortunately very slow, but is “usable” if you are not needing to call it repeatedly.

I thought developing this using this method shouldn’t be too bad as I knew when you import a font into Unity, Unity automatically creates a texture containing the font. What I didn’t anticipate was that the letters were not in a grid format, but places tightly together. With no runtime access to letter position data, this was not going to work.

Next on my list was Custom Font, a feature where you can “easily” create your own font in Unity. With Custom Font you supply your own font image laid out in a grid. Using this method I could determine where the letters were positioned. I now needed a way create a font image in a grid pattern and get all the Per Character Kerning values from a font.

In digging through the internet I came across a few mentions of something called the Unity Font Mapper. It took me a very long time but I finally tracked down a link to the app: http://loewald.com/unity/unityfontmapper.zip. This Mac application not only generates the font image in a grid pattern, but generates a file containing the Per Character Kerning information.

Once I had a Custom Font working I then discovered there is no programming access to any of its properties (I still use Custom Font as part of my final solution in hopes at some point access will be opened up to those values). This means these values now needed to be entered twice if you want to use the same font for both a Text-to-Texture font and as a regular font.

I now had all the pieces and it was just a matter of putting it all together. While the current version of this code is far from perfect and is missing features like colored text it does exactly what I wanted it to do.

To check out the demo click here.

To get the source (unitypackage) click here.

To get only the TextToTexture class (TextToTexture.cs) click here.

Source Requirements: Unity 2.6

Setup Steps

  1. Create a font image in a grid pattern and collect kerning values (either manually or using the Unity Font Mapper)
  2. Import the font image(texture) into Unity and select ‘Build Alpha From Grayscale’ and set ‘Is Readable’ to true.
  3. Add this texture to a material
  4. Within Unity create a Custom Font. If you aren’t wanting to use this font for anything but Text-to-Texture you can just setup the basics and ignore the Per Character Kerning values within the Custom Font (these take a long time to enter)
  5. Create a script that calls TextToTexture and passes all the required information (example in source: AddTextToTexture.cs)

Note: I used a Decal material in this demo so the text would appear on top of the primary texture. But you can use any material that you wish.

Real-time Terrain Deformation in Unity3D

Thursday, June 10th, 2010

Real-time Terrain Deformation Screenshot

A few weeks back I got thinking. Would it be possible to have a terrain within Unity deform in real-time? For example if an explosion went off, could it blow a hole in the terrain? I decided this would be a good project to learn the more ‘advanced’ features of Terrains within Unity.

It ended up being more challenging than I predicted, as it was difficult to get the framerate to remain stable while performing these operation. Using a few tricks I ended up getting it to work exactly as I had hoped.

The demo works like this. A script randomly spawns ‘shells’ that fall quickly to the ground. Each shell has an onTrigger collider attached to it. If this collides with a terrain that has a TerrainDeformer component, the shell tells that component its location and the force of the explosion. The shell then instantiate an explosion (supplied by Ben Throop great Detonator framework), and removes itself.

The TerrainDeformer script then translates that position to the correct location relative to it’s terrain and modifies both the heightmap (terrain height) and the alphamap (terrain texture). A bit of math is used to find all the heightmap and alphamap position within the area of the impact circle.

The texture which is used to re-texture the impact area is chosen from the list of terrain textures based on the numerical index value passed into the script (Terrain Deformation Texture Num). In this example it is set to one, so it will re-texture with the second texture in the list.

When creating your own terrains it is necessary for the height of the terrain to be higher than 0 meters so craters can be formed. I recommend a depth of at least 3 meters. This can done by setting the terrain height to something higher than 3 meters, then clicking Terrain->Flatten Heightmap and entering 3 meters.

For performance reasons it is important to keep your terrain size small and more importantly keep your Heightmap Resolution low. In this example it is set to 33.

The current version does have limitations like lack of terrain edge detection and support for multiple terrains. This example is more of proof of concept to show that not only can it be done, but done without much of a performance hit.

Thanks to Calin for creating the dirt texture.

To check out the demo click here.

To get the source (unitypackage) click here.

Source Requirements: Unity 2.6 and the Detonator Framework.

Quickly Adding Custom Editor Scripts To New Projects in Unity3D

Wednesday, June 2nd, 2010

Import Editor Scripts Screenshot

A little annoyance I’ve come across when creating new projects was having to manually add my collection of custom editor scripts each time. Ex: TransformUtilitiesWindow

I found that every time I created a new project I would navigate to my last project and drag all the editor scripts from there into my new project.

I got thinking maybe there is a way to add these scripts to the ‘Import the following packages’ panel when creating a new project. Turns out you can do this fairly easily.

First create an empty Unity project. I called mine EditorScripts. Create a folder within this project and call it ‘Editor’ (editor scripts must be placed in this folder to work). Then drag into this folder all your custom editor scripts. Once complete click Assets->Export Package, and then click the Export button (all your scripts should be checked for them to export). You will then export this package to the ‘Standard Packages’ folder within Unity (Windows: C:\Program Files\Unity\Editor\Standard Package or OS X: /Applications/Unity/Standard Packages – reference link). Once the export is complete, save this project for later use.

Now the next time you create a new project you should see a new item in the ‘Import the following packages’ list (image above).  You can check this package and have those scripts automatically added to your new project.

As you find/create new editor scripts you can go back to the EditorScripts project, added them and re-export the package.

While I personally find this method most helpful for editor scripts, you can use the same process to create reusable and quickly addable packages containing any kind of assets.

So until Unity comes up with a way to share scripts across projects this seems like the easiest and quickest way to add editor scripts that you will need for every project.

Interacting with Animated Blender Models in Unity3D

Wednesday, March 24th, 2010

Interactive Environment Demo Screenshot

My last Unity3D example showed how to interact with a standard Blender model. The TV model in that example had no animations just a separate dial object that I manually rotated in Unity. In this example I wanted to trigger a Blender animation when an object was clicked.

My brother Calin was nice enough to create the required Blender models for me and animated them using an Armature.  For these models he set each animation to 25 frames in length (length of the animation is important to know as it will need to be entered into Unity).

After importing each model into Unity each animation’s  name, frame start and frame end will need to be entered.

Ex: open 0-25, close 26-50

Once a model is added to a GameObject the animation component can be setup. In this example the default animation was set to none and ‘Play Automatically’ was disabled. This way no animation would be played at start up. Each previously entered animation can then be added to the animation list.

Once complete the default collider(s) can be added to the GameObject. Also if needed colliders that will need to follow the animation’s motion can be added to that joint GameObject. (ex: fridge door joint). This way during and after the animation all colliders will be in the correct location.

Finally from within the GameObject containing the model with an animation you can call ‘this.transform.animation.Play(“animationName”);’ to trigger that animation.

While setting up each animation and all the colliders can be a little time consuming once you get the hang of it, it becomes pretty easy.

Thanks again to Calin for creating these models.

To check out the demo click here.

To get the source (unitypackage) click here.

Source Requirements: Unity 2.6, you will only need Unity Pro to use the Render Texture feature used for the TV.

Interacting with Objects Unity3D

Monday, January 4th, 2010

Interactive TV Demo Screenshot

If you missed the first part of this Unity3D series you can read it here.

This example demonstrates how to interact with with objects in Unity.

The mouse cursor was removed and replaced with a cursor in the middle of the screen similar to an FPS. When this cursor is over an object that support interactivity, the cursor changes and the GUI will display a message based on the possible interaction. This is achieved by creating an abstract class called ‘Interactive’ with two abstract functions GetInteractionMessage() and Interact(). All interactive objects will inherit this class and support these two functions.

Within the Update() in the GUI class a Physics.Raycast is done using a ray moving outward from the center of the screen. This returns the first GameObject in which this ray collides. Then it tests to see if this object or a parent of this object has a component of type ‘Interactive’. If type ‘Interactive’ is detected it then can retrieve information about the possible interaction or if the left mouse button is down tell this object to perform an action.

In this example clicking on each TV changes its channel (based on multiple materials) and rotates its dial.

As you may have noticed the TV model has received a significant upgrade. A thanks goes out to Calin Reimer for creating this new model.

Hints and Gotchas:

  • Use an abstract class as the parent class for all interactive objects, this way you won’t have to rewrite the basic interaction code for each object. This method also make detection a lot easier.
  • To create a Ray moving outward from the center of the screen, use the following code: Camera.main.ScreenPointToRay(new Vector3(Screen.width/2,Screen.height/2));
  • Use layers to have certain materials ignore light sources (ie. TV Screen), then use a Self-Illumin shader to brighten this material.
  • If you can get someone else to model for you, do it. It speeds up development :)

To check out the demo click here.

To get the source (unitypackage) click here.

Source Requirements: Unity 2.6, but you will still need Unity Pro to use the Render Texture feature.

Render to Texture Unity3D

Friday, December 11th, 2009

Render Texture TV Demo Screenshot

I’ve been working with Unity for a while now so this article was long overdue. Initial I was planning on doing some entry level stuff, like what is a Rigidbody, adding materials, etc. As more and more good video tutorials began appearing online I decided that I would do something a little more advanced than that. Don’t worry it not much more advanced.

I recently purchasing Unity Pro and have been digging into some Pro only features. One of my favorites so far is Render Textures. Render Textures simply put allows you to render the output of a camera to a texture. More detail on Render Textures can be found here

For this example I modeled a TV in Blender (don’t laugh at the model it is my first) with an empty space for where the screen would be.

Steps in Creating a Working TV That Displays What You See.

  1. Add basic environment objects (ground, skybox, First Person Controller,lights etc)
  2. Import a tv model into Unity and place it within the scene
  3. Create a plane within Unity and position it within the TV model to be used as the TV screen (using Render Texture with planes is easiest).
  4. Right click within the Project panel to create a ‘Render Texture’
  5. Add a second camera as a child to the ‘Main Camera’ within the First Person Controller.
  6. Set the ‘Target Texture’ property of this camera to the newly created Render Texture.
  7. Add this texture to a material
  8. Add this material to the tv screen
  9. Hit play and you should have a working TV

Hints and Gotchas:

  • You will need to rotate the render camera 180 degrees on its z-axis so that it will render the scene the right way up Update: Incorrect, looks like I had my rotations messed up. If the plane you are rendering to is rotated correct the render material will appear the right way up.
  • You will need to use at a least two cameras when using Render Texture because the camera that is rendering to screen can not also render to a texture
  • If you have added a Skybox to your main camera you will need to add this Skybox to the render camera(s).
  • If you have multiple cameras it may be easier to set the Skybox material within Render Settings instead of setting each camera’s skybox individually.

To check out the demo click here

To get the source click here

Source Requirements: You will need need Unity Pro to use the Render Texture feature.

Update: I have released an update version of this demo that includes object interaction. http://blog.almostlogical.com/2010/01/04/interacting-with-objects-unity3d/