Showing posts with label Editor. Show all posts
Showing posts with label Editor. Show all posts

Friday, 18 April 2014

Unity Gizmos

I've been using Unity 3D for months now and I somehow missed Gizmos as a concept.  I had seen the camera and speaker icons in the editor view but I think I had just assumed they were built in symbols used for built in objects and I had a blind spot towards them.

I now know better.  You can easily create your own icons which can be included in the scene.  I started using them when I wanted to make spawn points visible in the scene.



It is very easy to attach your icon to any object in a scene and that icon displays over the object.




That works well if you want to mark otherwise invisible points in your scene.  An example of this might be waypoints for AI controlled characters.

I prefer to create the Gizmos in code.  This adds them to the Gizmos list in the game view.



Creating the Icon

This can be done in any image editor and just needs whatever shape you want with a transparent background.

The image can be any size if you intend to use the default automatic scaling method.  For good quality I use anything between 512 and 1024 pixels high or wide images.  If you don't use the automatic scaling the image in the 3D scene, at those sizes, is quite small.

I used Inkscape to create the following image.



The important bit to know before you can use the image in your code is that it must be in the special Gizmos folder in Unity.

There can only be one Gizmos folder and it must be in the root of the Assets folder.



If you try to put your icon anywhere else, it will not work as a Gizmo in code.

Using the Icon for Your Object

Well if you can write any Unity code this is the simplest possible.  Just add the following in the code for your object or create a small script with this in.



/// http://docs.unity3d.com/
///        Documentation/ScriptReference/Gizmos.html
void OnDrawGizmos()
{
    // The icon image must be in the 
    // special folder called 'Gizmos'
    // There can only be one Gizmos 
    // folder in the root of Assets.
    Gizmos.DrawIcon (transform.position, 
                     "PersonIcon.png", 
                     true);
}



That's it, you now have a Gizmo shown wherever you position that object.


Saturday, 29 March 2014

Unity Inspector Tool Tips and more

When I started working with Unity 3D I looked up adding tool tips to properties in the inspector.  All the results of the searches came with a lot of code and no downloadable simple examples.

I did not spend much time on the subject because I was looking for a quick answer.  I was also probably using the wrong search criterion.



Further along I had a more important requirement that I thought was worth coding because it would save me making mistakes when setting up scenes.  As a consequence, I have leaned enough, very quickly, to create a simple but effective tool tip option for the properties, visible in the inspector.



I don't know if it is because I am using the latest version 4.3 of Unity but my solution does not need much code.  Many of the samples I looked at had huge switch or if statement blocks to allow for different property types.  I was able to use a built in method that replicated the default behaviour and allowed me to add the tool tip.




public class ToolTip : PropertyAttribute
{
    public string TipText = "";

    /// Display text when the mouse is over the label.
    public ToolTip(string message)
    {
 TipText = message;
    }
}





using UnityEditor;
using UnityEngine;
using System;

/// Display a tool tip when the mouse is over the label.
[CustomPropertyDrawer(typeof(ToolTip))]
public class ToolTipDrawer : PropertyDrawer
{
    private ToolTip source { get { return ((ToolTip)attribute); } }

 /// The height returned here must be appropriate for the property
 /// being dawn.
 public override float GetPropertyHeight (SerializedProperty property,
                                          GUIContent label) 
 {
  return GetOriginalHeight (property, label);
 }

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
  // Must reset the tip otherwise all labels get the same tooltip displayed!
  string previousTip = label.tooltip;
  if (!string.IsNullOrEmpty (source.TipText))
  {
   label.tooltip = source.TipText;
  }

  // Display the default fields for this property
  EditorGUI.PropertyField (position, property, label, true);

  // Must reset the tip otherwise all labels get the same tooltip displayed!
  label.tooltip = previousTip;
 }

 /// Returns the height of the default control.
 /// 
 /// This can be reused by other property drawers.
 public static float GetOriginalHeight (SerializedProperty prop,
                                        GUIContent label) 
 {
  const float spacing = 3f;
  
  float baseSize = EditorStyles.label.lineHeight;
  
  // Most types only use one line so they work with the base but a few are 
  // multiline and need more work.
  float extraLines = 0f;
  if (prop.propertyType == SerializedPropertyType.Bounds)
  {
   extraLines = EditorStyles.label.lineHeight * 2.2f;
   baseSize = baseSize + extraLines + spacing;
  }
  else if (prop.propertyType == SerializedPropertyType.Rect)
  {
   extraLines = EditorStyles.label.lineHeight * 1f;
   baseSize = baseSize + extraLines + spacing;
  }
  
  return baseSize + spacing;
 }
}



That's it, not much code.

If you don't want to copy and paste, I've included the tool tip code and the code for other property attributes in to a GitHub project called Unity3D Utility Kit.

Download the Utility Kit from:
https://github.com/ThatJCB/Unity3DUtilityKit

The kit includes a test scene to show the usage of the attributes and to prove that they work.

At the moment the property attributes included are:
- A box to display a helpful message, which was my first idea before I got tool tips working.



- The tool tip which displays when the mouse hovers over the label.
- A Regular Expression mask for fields, created by  , many thanks.
- An integer slider that also works with float values to keep whole numbers.
- A divider with an optional heading.
- Scene selection list so you can only enter a scene name that has been included in the build list.
There's some work in progress in there as well and I'll probably add more to the list over time.



That last item, for scene selection, was the reason I started looking at the Property Attributes and Drawers in the first place.

I hope the examples will be useful to others.

Thursday, 20 December 2012

Winform Map Editor

Last night I finished my side project of migrating the map editor from being a game screen to being a normal windows application (Winform.)  I've been doing this when I needed a break from 3D modelling. 


At the moment all I have attempted to do is move all the features I had before in to a separate project.  I did find a few minor bug fixes but it is basically the same.

The only major change was to the controls for moving about the map.  It now works more like a 3D modelling programme, in fact the rotate, zoom and move are very similar to Blender.  I have however retained first person keyboard controls for fine adjustments.

I am doing most of the modelling in Blender so the new controls are much more familiar when I bring the models in to the editor.

I have left space to the side and bottom of the main view window to put properties.  I have not coded anything to go there yet but in time I will add something useful.

The editor is still linked to the main game.  It shares some of the rendering code and all of the map loading code.  I compile the editor project in the same solution as the main game.  This means that the map files will always remain compatible.

I find it works well.  The only peculiarity I had was that the game view control from the Microsoft sample is external.  Exceptions thrown in the game view crash the control but the rest of the Winform app continues without error.  The view window goes white with a red cross in it!

I fixed that with a simple try and catch wrapped round my update and draw code:


/// 
/// Redraws the control in response 
/// to a WinForms paint message.
/// 
protected override void OnPaint(PaintEventArgs e)
{
    try
    {
        string beginDrawError = BeginDraw();

        if (string.IsNullOrEmpty(beginDrawError))
        {
            // Slow the game down to no more 
            // than 60 fps (16.667ms per frame)
            if (gameTime.ElapsedUpdateTime > 
                TimeSpan.FromMilliseconds(16))
            {
                // My own version of GameTime
                // based on a stopwatch.
                gameTime.Update();
                // Simulate the update loop in 
                // an XNA game.
                Update(gameTime);
                // Draw the control using the 
                // GraphicsDevice.
                Draw(gameTime);
                EndDraw();
            }
        }
        else
        {
            // If BeginDraw failed, show an error 
            // message using System.Drawing.
            PaintUsingSystemDrawing(e.Graphics, 
                                    beginDrawError);
        }
    }
    catch (Exception ex)
    {
        // Exceptions within external applications do 
        // not automatically break the parent form.
        // These lines trap the exception, display the 
        // error and break the parent code for debugging.
        System.Diagnostics.Debug.WriteLine(
            "Exception in Update or Draw: " + 
            ex.Message + " in " + ex.Source);
        System.Diagnostics.Debug.WriteLine(
            "Stack trace: " + ex.StackTrace);
        throw new Exception(ex.Message);
    }
}

The whole app now crashes and the exception is displayed to help debugging.

In addition to being able to position, models, triggers, waypoints and generate the navigation mesh used by Bots, I have loads of helper overlays within the editor.  Too many to list:


I nearly forgot.  There was a point to moving the editor out of the main game. 

Every time I tried to change the game I had to keep it compatible with the editor.  There was often lots of extra code just so the game remained fast and the editor had features.

When I started looking at adding in the networking code it just got too complicated to do what I wanted and retain compatibility.  That's what kicked off this little side project.

It's how I should have done it in the first place.

Wednesday, 25 July 2012

Diabolical Editor

I noticed the other day that I had not mentioned much about the level editor that I use for Diabolical: The Shooter.  I've spent a lot of time adding features to it so I thought it worth describing.


The editor is used for shaping and colouring the terrain and for positioning the static models on to the map.  With hindsight I should have created a completely separate application but my original design was to be able to quickly play test any level I created so the Editor uses much of the same code as the game and is run from the game's main menu.

That works but there has been a lot of struggling to keep the game code tidy whilst also adding in the Editor methods.  This has resulted in a lot compiler directives of the type '#if EDITOR'.

To be able to use Windows menus I have had to do some messing about.  The WinForm menus are not fully supported in the XNA game loop.  I have an open source test project that shows how I have managed to get the menus to work with some limitations:
http://code.google.com/p/xna-game-menu/



The top level menus and the drop downs have to be coded by hand but they can launch forms created with the Visual Studio GUI.  The menus work fine for the Editor used only by me but I would never use the WinForm menus in an XNA game.

Over time I have added stacks of features, too many to list but just a few are: texture terrain with up to four layers, adjust the height of the terrain with various helpers such as flatten, noise, slope etc.  use a round cursor, a rectangular cursor, add structures, waypoints, triggers, static particle and sound effects and so on...


The whole terrain is based on a height map using a regular grid.  This makes finding heights relatively quick.  The grid only has one value, the height at each corner.  The limitation of this is that it cannot do vertical faces only slopes.  For the vertical cliff faces seen in some of these screen shots I have created 3D models.


To position the cursor I project a line from the view and calculate where it intersects the terrain.  At first the cursor always followed the view but I found this difficult to see what I was doing so now the cursor stays still unless I hold down the Ctrl key.

I am not sure if my method for finding the point on the terrain to position the cursor is efficient but it is fine for this editor.  I step along the line projected from the view, testing the height at each point.  The step being just under one grid width to ensure every grid is tested.  As soon as the end point of the line goes underground I know that somewhere between the last step and this step it intersects with the ground.  I then back step in smaller and smaller segments to get a nearly accurate point of impact.  I only need to know which grid I'm in.



I use the top left corner of the grid in which the line intersects the terrain as the centre position of the cursor.  For some modes I offset this by half a grid in others I stay with the corner point.

I can size the terrain cursor using a simple popup form.  Whatever action I carry out is done for every point under the cursor.  The positions are all easily calculated using simple maths.



The terrain cursor and the many helper shapes I draw are just simple lines drawn in 3D space.  The cursor samples the terrain height at the ends of each line and sets the heights a fraction above the terrain.  This means the cursor follows the contours of the terrain.


There has been a lot of work over the years getting to this stage with many features I have not mentioned yet.  If I knew then what I know now I would probably use an existing editor and spend the time writing an importer rather than adding all these features to my editor.  Having said that, I've learnt a lot and I do enjoy knowing that I did all this.

To complete the picture, this is a list of all the features of the game engine:
  • Walk round a 3D world
  • - first person controls
  • - over the shoulder view of yourself (more fiddly than it sounds)
  • - resolution 1024x576 (for better performance on the Xbox 360)
  • - jump
  • - spectate
  • - two player split screen
  • Animated
  • - blend animations
  • - merge in arm movement to follow which way the player is looking
  • - hold attachments that move with whatever they are attached to
  • - shared animation files (and a way to get them in to the pipeline.)
  • Physics
  • - collide with characters and structures
  • - projectile impacts
  • - projectile trajectories (thrown grenades)
  • Terrain and game editor (development only)
  • - change heights
  • - change textures
  • Add and remove (only in the development editor):
  • - models
  • - triggers
  • - particle effects
  • - goals
  • - trigger goal success
  • - trigger add a new goal
  • - trigger spawn player
  • - trigger spawn non-players
  • - trigger particle effects
  • - waypoints for AI pathfinding
  • - spawnpoints
  • - weapon or equipment pickups
  • Lighting
  • - single shadow casting light
  • - three effect lights
  • - shadows (not a trivial task, many many months spent on this)
  • Full menu system
  • - select which map to play
  • - customise the player character with hats etc.
  • - load and save character choices
  • - change music and effect volumes
  • - in game pause menu, resume or exit
  • - display goals outstanding and completed
  • Combat system
  • - select weapons
  • - shoot weapons
  • - throw grenades
  • - melee (elbow bash while holding a gun)
  • - projectile trails
  • - impact damage decals (instanced)
  • - impact effects, debris and smoke
  • - explosions
  • - muzzle flash
  • - sound effects
  • - drop weapons
  • - pickup weapons
  • - pickup ammunition
  • Head Up Display (HUD)
  • - weapon sights
  • - sniper sights
  • - zoom in
  • - display ammo as used
  • - compass
  • - radar showing friend and enemy positions if close
  • Non-Player Artificial Intelligence (AI)
  • - pathfinding (A* using navigation rooms)
  • - select a target if in range
  • - shoot at a target
  • - move to better cover to shoot from
  • and I'm sure there's more...

Sunday, 20 May 2012

Game Testing

My wife's mum and brother came round for breakfast this morning and I could not resist showing Matthew, my brother-in-law, progress on the game. 

I should point out that Diabolical is designed to be the type of game Matt and I like to play.  We have been playing coop shooters together for many years.  When we lived next door to each other and prior to Internet gaming being popular, we had a network cable strung between our houses to play anything we could that had some form of network game.

Back to today.  I was very pleased that not only was my code in a fit state to test on the Xbox 360 but we had great fun shooting at each other.  As my current test level only has one alien Bot at the moment the coop bit only lasted a few seconds.  After that we just kept shooting each other, dying and selecting to respawn.



Split screen play meant that hiding was not possible but the rather sparse test map has more than one path to everywhere so while one was distracted with chatting the other one of us would take advantage.

It was fun and everything worked without a crash or a glitch.  It was a shame I haven't got further with the maps but next time I hope to have a finished or near finish level.

For some time now I have been creating models, buying models and starting to put them in to a form I can use in a game level.

It's taken me a bit longer because when I changed the game to run the update in a separate thread it broke the level editor!



I've now fixed the editor and slightly improved it so I can get back on with building the maps.

Sunday, 1 May 2011

Lighting Improved

I have been busy over the last month completely re-writing the HLSL effect shaders. The new version has improved lighting with 3 directional lights phong specular lighting to make models look shiny and better shadow resolution.

I tried to improve performance which I think I have done but as I have added features I have used up any gains I made.

I have written a lighting form for my editor so I can change all the lighting values and see the effect on the map immediately.




The biggest improvement to the shaders has been removing some artifacts caused by interior faces of models casting shadows on the wrong surfaces.

I have learnt a lot about lighting and some more about modelling. I also know that I have to re-make some of my models to sort out the effect caused by faces sharing vertices.

Tuesday, 15 March 2011

The Level Editor Continues

Every time I try to create a level I find a few new features that I need to add to the editor.  I then have to temporarily stop work on the level to implement them!




This weekend I added a way to line up one object in the scene with any other.  I have also just added a set of 3D axes in the corner of the screen so that I can tell which way any structure is facing.


Now I need to change the keyboard input to make it more obvious which way the structures will move.  At the moment I use the first person controls to move the objects about the scene but this is confusing when applied to an object in front of you.

Monday, 12 July 2010

Model Editor

Since completing the shadow mapping I've added normal mapping to the shader and started to look at adding more models to the level.

I purchased some spaceship models from 3DRT.com which are in a style that suits the game.

To get them to work in the game I have to add collision bounds to them. In my case all the bounds in the game are based on spheres. I have a function that divides the model up in to larger and then smaller spheres.

That works well but does not care if a sphere overhangs an edge. In the case of square buildings this does not cause any noticable problems. These space ships have overhanging wings.

While testing them I kept getting stuck where I should not have got stuck. I had to write an editor for my bounds creation function so that I can remove bounding spheres that unnecessarily get in the way.



Most of the code I needed to do this was already in the game. I find this a lot now. Most of what I have to change or add is just a variation of something I've already written so the game is moving on more quickly now.

In the above picture you can see the small spheres clusterred round one part of the model. The whole model is coverred with those spheres but to make collision detection quicker those spheres are included in a larger sphere. The small group shown above are the smaller spheres in just one of the larger spheres.

Just in case its not obvious, those spheres are never visible in game. I had to deliberately add the line drawn circles to visualise them while editing. A long time ago I added a shapes class to the game that is only used by the editor to represent frustums, bounding spheres, bullet trajectories and anything else where I needed to visualise the result of some function or other. Over time I have a lot of options that I can overlay on the view.

Thursday, 15 April 2010

Named the game

Over the weekend the game got a name. 'Diabolical: The Shooter'.

It's not easy to tell from the current screenshots that this will be a Science Fiction game, so I thought it worth describing the game concept.

It's set in a future where humans have travelled between stars and set up outposts and cities on remote worlds, where we have encountered a small number of other intelligent races.

The premise of this game is that human nature does not change. We still work and fight to get more of what we want. On the outer reaches there are few governments and corporations have a free hand to do business as they please. Humans, however, were not the first race to travel through space. There was a long dead ancient civilization spread through the galaxy. Anything to do with that ancient civilisation can easily be sold to the highest bidder and there is strong competition to get artifacts.

Back to what I've been doing...
I was intending to do the artwork myself but after spending far more time than I could spare to create one small object. I decided that if the game is ever to be finished to the quality I would like, then I need to get an artist to create the key assets.

I have found some off the shelf models for some characters and most of the scenery but the game needs to be unique so I commissioned a 3D model a week ago and the result is back. It is exactly what I was after. I need to do some more work before I will present it.

My main focus at the moment is map design, although I get side tracked when I need to add new features to the level editor. Things like a model to represent the spawn points or a grid to help position structures.


I've also improved the random noise and terrain smoothing functions and added a rectangular cursor which is useful for man made shapes like roads.


The circular one is best for hills and natural terrain.