All posts by admin

Animation test, finally!

So in the last post I covered the easy model creation pipeline I was working on. Since then, I solved the final piece of that puzzle which is to automatically generate the rig. All of that is rather boring so I’ll save it for another day. Today, I want to show the point of all that, which is to animate! I got two animations setup, east idle and east run. Check it out!

I’ll fill out the north, south and west (maybe mirror east?) and then post some more videos.

Easy model creation

In the skeletal animation experiment I created the model by hand, placing one polygon per pixel using an image plane as a template and then manually setting the UVs to match up with the sprite. That was way to tedious and definitely not scalable. I wrote a handy little python function that will take a sprite as input and do all the work for me :-). Check it!

I think I’ll still need to create the “rig” manually. There will be one unique rig per direction, with east/west potentially just being a mirror. After I create one decent quality animation set and I automate the rigging process then I am confident that this will be my pipeline.

Skeletal animation experiment

One of the next things I want to figure out is how I’ll handle the character animations. I’ve been using the tiny dungeon sprites from Oryx Design Lab, and I had been thinking that skeletal animation might help bring them to life in an interesting way. I didn’t quite know how I would do this so I did some research and there are a ton of options to try out, from Creature to Spine2D, to Maya, and even Unity itself supports animation from within the editor. Here is my first test:

I brought the 16×16 sprite into Maya and slapped it onto an image plane, scaling it up 100 times until each pixel was 1 grid unit, and then I made a 1×1 polygon plane for each pixel. I ended up using a planar projection and using the sprite as a texture, but I think it may be more efficient to either use vertex colors or a tiny 1D texture that has the 8 colors the sprite has in it.

This animation is just a simple waving idle, so I want to do another test with more action like a run or an attack. I like where it is going so I want to see if I can take it to the limit as well, with FX and everything. Then I want to see if I can streamline the setup process by automating the manual steps I did to turn the pixels into polygons. Cheers!

Movement and dodging experiment

The game has reached a mini-milestone. All of the parts I need to test movement and dodging projectiles are finished. Like many Roguelike games, each move is a turn and all characters take turns simultaneously, but at different rates. What I wanted to test here is the turn based movement of the Player and the continuous movement of projectiles. The combination of these requires the Player to move in order to dodge.
I’ll be throwing builds into my public Dropbox folder if anyone wants to playtest and give feedback. Next up are the damage system and I want to try another experiment, which is the use of skeletal animation.

Yet unnamed Roguelike

While my wife was at GDC I began work on a Roguelike game in Unity.  I have limited time, so progress has been slow but steady.  I’m currently using art from Oryx Design Lab (http://ift.tt/1iD1s45). I’m close to the point where I can playtest the most basic mechanics.  I’ve definitely suffered from the ‘start a lot of projects that don’t get finished’ problem in the past and I am hoping that keeping a devlog will help push me to ship this game by making my progress public.
Honestly I don’t have a super strong ‘seed’ that everything is growing from.  I am definitely figuring things out as I go.  My current thinking is that the game will have these elements
  1. Movement is turn based like most roguelikes
  2. Projectile movement is continuous, so you’ll have to move to dodge them
  3. I’ll have a pixelated art style, probably 16×16 for most characters and environment tiles, however the characters will use skeletal animation
  4. It will be the inverse of Rogue Legacy in that, you venture outside of a castle into a new environment after each death
  5. There will be weather and survival elements like Unreal World, but less so.  
  6. Your progress is measured in how many days you survive, like in Neo Scavenger
I don’t know much more than that right now.  I’m very close to being able to test #2 from above
This blurb and this image are what sparked the whole thing:
Game takes place across a series of ‘single screen’ battles, al la OG Zelda.
As you move to the edge of the screen, the camera lerps to the next screen
     crazy town idea–it is multiplayer, you get matchmade with players in the next screen
Turn based, roguelike style movement of characters
Projectiles can be dodged in real-time
reverse of rogue legacy–where instead of going into a randomly generated castle, you exit your home into the randomly generated forest
     you only get to keep what you bring back?
     you only get to keep ‘special’ items a la enchanted cave 2
Here is my current todo list
Stay tuned for more updates!

Unity3d Extension methods example

Extension methods are awesome for extending the functionality of existing classes. What is really cool is that if you use an IDE that supports autocompletion, your extension methods will show up when using the classes you extend.

For this example, let’s suppose that you want to extend Unity’s AnimationClip to support the idea of adding an “OnAnimationEnd” event. When the animation clip ends, a callback will be called.

using UnityEngine;

public static class AnimationClipExtensions
{
    public static void AddOnAnimationEndEvent (this AnimationClip animationClip, string onAnimationEndCallbackName)
    {
        AddOnAnimationEndEvent (animationClip, onAnimationEndCallbackName, 0, 0.0f, "", null);
    }

    public static void AddOnAnimationEndEvent (this AnimationClip animationClip, string onAnimationEndCallbackName, int intParameter)
    {
        AddOnAnimationEndEvent (animationClip, onAnimationEndCallbackName, intParameter, 0.0f, "", null);
    }

    public static void AddOnAnimationEndEvent (this AnimationClip animationClip, string onAnimationEndCallbackName, float floatParameter)
    {
        AddOnAnimationEndEvent (animationClip, onAnimationEndCallbackName, 0, floatParameter, "", null);
    }

    public static void AddOnAnimationEndEvent (this AnimationClip animationClip, string onAnimationEndCallbackName, string stringParameter)
    {
        AddOnAnimationEndEvent (animationClip, onAnimationEndCallbackName, 0, 0.0f, stringParameter, null);
    }

    public static void AddOnAnimationEndEvent (this AnimationClip animationClip, string onAnimationEndCallbackName, Object objectReferenceParameter)
    {
        AddOnAnimationEndEvent (animationClip, onAnimationEndCallbackName, 0, 0.0f, "", objectReferenceParameter);
    }

    private static void AddOnAnimationEndEvent (this AnimationClip animationClip, string onAnimationEndCallbackName, int intParameter, float floatParameter, string stringParameter, Object objectReferenceParameter)
    {
        AnimationEvent animEvent = new AnimationEvent ();
        animEvent.time = animationClip.length;
        animEvent.functionName = onAnimationEndCallbackName;
        animEvent.intParameter = intParameter;
        animEvent.floatParameter = floatParameter;
        animEvent.stringParameter = stringParameter;
        animEvent.objectReferenceParameter = objectReferenceParameter;
        animEvent.messageOptions = SendMessageOptions.DontRequireReceiver;
        animationClip.AddEvent (animEvent);
    }
}

Now that we have a few extension methods, let’s test it out. Create a new component and fill in the animation clip in the inspector

using UnityEngine;
using System.Collections;

public class ExtensionMethodTest : MonoBehaviour
{
    public AnimationClip testClip;

    void Start ()
    {
        testClip.AddOnAnimationEndEvent("TestOnAnimationEndEvent");
        testClip.name= "TestClip";
        animation.Play("TestClip");
    }

    void Update ()
    {

    }

    void TestOnAnimationEndEvent()
    {
        Debug.Log("TestOnAnimationEndEvent() was called.");
    }
}

Unity3D AssetPostprocessor Example

In Unity3D, you’ll often find yourself repeating a lot of simple tasks on prefabs if you make changes to the source content after you’ve placed instances of the prefab in the editor; stuff like turning off the renderer for some meshes, or adding colliders and scripted components. Unity provides a mechanism to automate much of this work with the AssetPostProcessor class.

In your Maya scenes, every mesh, bone, etc are all GameObjects in Unity. When you save your Maya scenes, it triggers them to be re-imported in Unity and when that happens, the AssetPostProcessor’s OnPostprocessGameObjectWithUserProperties() method will get called once for every GameObject in the Maya scene. If any of those GameObjects have custom attributes added to them, each attribute will have its attribute name and attribute value in the arrays passed into OnPostprocessGameObjectWithUserProperties.

Ok. So what is all this code? The examples I have seen usually have something like this inside the OnPostprocessGameObjectWithUserProperties method:

if (userPropertyName == "AddMeshCollider")
{
    ...
}
else if (userPropertyName == "AddSphereCollider")
{
    ...
}

There is nothing wrong with that code, but my preference is to separate out the logic that handles what to do for each user property into its own class, and never touch the OnPostprocessGameObjectWithUserProperties method again.

To do that, we can use the Attribute class and C# reflection. We’ll create an ImportTaskAttribute that takes a name in its constructor. That name will correspond to the user property name (the custom attribute name in Maya.)

All classes that are marked up with that attribute will get collected by an ImportTaskCollector class which we’ll use to fetch them and then call their Execute method to do the work.

using System.Linq;
using UnityEngine;
using UnityEditor;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

This is the ImportTaskAttributeClass. The TaskName property will hold the name matching the user property.

[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class ImportTaskAttribute : Attribute
{
    public string TaskName;
    
    public ImportTaskAttribute(string taskName)
    {
        TaskName = taskName;
    }
}

This interface is the contract for all of the import tasks. And the concrete class below is what we’ll inherit from.

public interface IPostProcessGameObjectWithUserPropertiesTask
{
    GameObject ImportedGameObject {get; set;}
    string UserPropertyName {get; set;}
    object UserPropertyValue {get; set;}
    
    bool ExecuteTask();
    void PostExecuteTask();
}

public class PostProcessGameObjectWithUserPropertiesTask : IPostProcessGameObjectWithUserPropertiesTask
{
    public GameObject ImportedGameObject {get; set;}
    public string UserPropertyName {get; set;}
    public object UserPropertyValue {get; set;}
    public object UserData {get; set;}
    
    public virtual bool ExecuteTask() { return false; }

    public virtual void PostExecuteTask() {}
}

This is the ImportTaskCollector. Its job is to find all classes marked up with the ImportTaskAttribute.

public sealed class ImportTaskCollector
{
    private Dictionary<string, object> _importTasks = new Dictionary<string, object>();
    
    public ImportTaskCollector()
    {
        Assembly assembly = typeof(IPostProcessGameObjectWithUserPropertiesTask).Assembly;
        Type target = typeof(IPostProcessGameObjectWithUserPropertiesTask);        
        var importTaskTypes = assembly.GetTypes()
                            .Where(type => target.IsAssignableFrom(type));

        foreach (Type importTaskType in importTaskTypes)
        {   
            if (importTaskType.IsAbstract || importTaskType.IsGenericType)
            {
                continue;
            }
 
            var importTaskInstance = Activator.CreateInstance(importTaskType);
            var importTaskTypeAttributes = Attribute.GetCustomAttributes(importTaskType);

            var importTaskTypeAttribute = importTaskTypeAttributes
                .SingleOrDefault(attr => attr as ImportTaskAttribute != null) as ImportTaskAttribute;
            
            if (importTaskTypeAttribute != null)
            {
                _importTasks.Add(importTaskTypeAttribute.TaskName, importTaskInstance); 	
            }
        }
    }
    
    public IPostProcessGameObjectWithUserPropertiesTask GetTask(string taskName)
    {
        if (_importTasks.ContainsKey(taskName))
        {
            return _importTasks[taskName] as IPostProcessGameObjectWithUserPropertiesTask; 
        }
        else
        {
            return null;
        }
    }
}

Finally, this is our custom AssetPostprocessor.

public class AssetImport : AssetPostprocessor
{
    private readonly ImportTaskCollector _importTaskCollector;
    
    public AssetImport()
    {
        _importTaskCollector = new ImportTaskCollector();
    }
    
    void OnPostprocessGameObjectWithUserProperties(GameObject g, String[] userPropertyNames, System.Object[] userPropertyValues)
    {
        for (int propertyPairIndex = 0; propertyPairIndex < userPropertyNames.Length; propertyPairIndex++)
        {
            var userPropertyName = userPropertyNames[propertyPairIndex];
            var userPropertyValue = userPropertyValues[propertyPairIndex];
            
            IPostProcessGameObjectWithUserPropertiesTask importTask = _importTaskCollector.GetTask(userPropertyName);
            
            if (importTask != null)
            {
                importTask.ImportedGameObject = g;
                importTask.UserPropertyName = userPropertyName;
                importTask.UserPropertyValue = userPropertyName;
                
                if (importTask.ExecuteTask())
                {
                    importTask.PostExecuteTask();
                }
            }
        }
    }
}

Ok, with all of that in place, here is an example of how you would use it:

[ImportTaskAttribute("AddMeshCollider")]
public class AddMeshColliderTask : PostProcessGameObjectWithUserPropertiesTask
{
    public bool ExecuteTask()
    {
        ImportedGameObject.AddComponent<MeshCollider>();
        return true;
    }
}

Then, if you add an attribute named “AddMeshCollider” to any mesh in your maya scene, your task will get run for that game object and a MeshCollider will be added.

But we can do better. We can make a generic AddComponentTask where the generic type parameter is the Component we want to add.

public class AddComponentTask<T> : PostProcessGameObjectWithUserPropertiesTask where T : Component
{
    public override bool ExecuteTask()
    {
        UserData = ImportedGameObject.AddComponent<T>();    

        return UserData != null;
    }
}

[ImportTask("AddMeshCollider")]
public class AddMeshColliderTask : AddComponentTask<MeshCollider>
{
	// Nothing to do, ExecuteTask() gets called on AddComponentTask<T>
	// and T is MeshCollider in this case.
}

Now, what if we wanted to add a CapsuleCollider and then set the height and radius from within Maya? The UserData property holds the component we just added, and now that code lives in the AddComponenTask‘s Execute method. We don’t want to keep duplicating the code for adding a component, so this is where the PostExecute method comes into play.

[ImportTask("AddCapsuleCollider")]
public class AddCapsuleColliderTask : AddComponentTask<CapsuleCollider>
{
	public override void PostExecuteTask()
	{
		var capsule = UserData as CapsuleCollider;
		var capsuleData = UserPropertyValue as Vector2?;
			
		if (capsule != null && capsuleData.HasValue)
		{
			capsule.height = capsuleData.Value.x;
			capsule.radius = capsuleData.Value.y;
		}
	}
}

As always, if you’ve got any questions, shoot me an email at jspataro@gmail.com

Simple game object / component system : part 1

In the engine I’m coding, I got to the part where I needed to write what is commonly called the game object system or game object model. Typically in games, there are a variety of object types; rocket launchers, giant orcs, starving pelicans, and of course, crates. The game object model provides an architecture by which all of these objects can be created, destroyed, updated, looked up, and so on.

Before I got started, I clicked through some old gdc slide decks, and thumbed through some of the books in my technical library. What I found was that there were quite a few ways to go when it comes to game object models, but there were two prevalent models: a game object was either started as an abstract base class that was sub-classed and extended to make a concrete object type, or was a simple object that wasn’t sub-classed at all, and concrete object types were built out of a variety of component classes that each represented different behavior.

After shipping a few games, I have been exposed to a couple different game object models, but nothing that departs from either of the paradigms mentioned above. Ultimately though, for my own engine I wanted to replicate some aspects of the way Unity3D works. The workflow in the editor is so streamlined and it really is easy to get things up and running.

The features I wanted in my game object model were:

  • Data declaration through script
    • Similar to Torque3D’s datablocks
    • A template or blueprint for an object’s component list, which gets instanced
    • Instances are placed in a map editor
    • The template gets sent across the network only once
  • Both scripted and native c++ components
  • Messages sent/received/handled in script or native code
  • Game object itself is very lightweight, maybe just a guid and a transform
    • Game objects can be extended in script with key/value pairs of properties

Once I started the work, I thought it would be a good opportunity for a series of posts.

Let’s start with the code that defines a game object:
gameobject.h

#pragma once

#include <ObjBase.h> // GUID
#include "eastl/list.h"

class c_component;
class c_transform_component;


// A game object is an object that can be placed in our game world
// each created game object has a unique identifier
// game objects can have components attached to themselves.
// by default, all game objects have a transform component attached
// the transform is the only component the gameobject 'knows' about.
class c_gameobject
{
public:
    c_gameobject(); 
   ~c_gameobject();	

    // game objects get updated every tick
    // inside our game object update we will give attached components
    // a chance to update.
    void update(double dt);

    // game objects expose a templated add_component method so that 
    // our game object doesn't need to know what kind of components 
    // exist.
    template <class t_component> 
    t_component* add_component();

    // our get_component method is also templated, again so that 
    // our game object doesn't need to know what kind of components
    // exist
    template <class t_component> 
    t_component* get_component();	
	
    // internally, our game object will keep a list of the components
    // that are attached.  You can use any flavor of list.
    // I recently switched from rolling my own generic containers to
    // using eastl.  
    typedef eastl::list<c_component*> 
    t_component_list;
	
    const t_component_list* get_components() const 
    {
        return &m_component_list;
    }
	
    // all game objects in our world need to be uniquely identifiable
    // for this purpose, I am using a guid.  You can use any mechanism
    // that guarantees the game object will be unique.
    inline GUID get_guid() const 
    {
        return m_guid;
    }	
	
    // here are a couple of operators used for comparing one game object
    // against another for equality.
    bool operator ==(const c_gameobject& rhs) const;
    bool operator !=(const c_gameobject& rhs) const;

protected:
	
private:
    // this could pobably be public, but using get_component
    // calls this anyways, so it would be redundant for users to
    // ask has_component and then call get_component
    // therefore get_component just returns NULL if the component
    // type in question is not attached.
    template <class t_component> 
    bool has_component();

    GUID m_guid;
    t_component_list m_component_list;

    // we need not necessarily store this, but it's more efficient
    // speed wise to just access it this way rather than calling
    // get_component internally, and even if we were doing it that way
    // we would be asking for a c_transform_component then, so it's
    // better to just store it imo.	
    c_transform_component* m_transform;
};

// our templated methods need to go inside the .h file.

// in c# you can do stuff like class MyClass<T> where T : SomeClass
// I would love to know how I can ensure that t_component is derived
// from c_component
// if anyone knows how to do that, shoot me an email: jspataro@gmail.com
template <class t_component>
t_component* c_gameobject::add_component()
{
    // interesting.
    // I didn't want all the overhead of a singleton for this
    // what this is, is a place where components register themselves
    // as a unique id (guid) and a creation function pointer
    // the creation function just needs to return a pointer to the
    // new component
    // so the component registry is just a hash table where guids
    // map to creator functions.
    extern t_component_registry g_component_registry;

    // for now, only one of any type of component can be attached
    // to a game object. Later on when we add scripted components
    // we'll allow more than one of those to be attached.
    // this is meant to prevent two transforms/renderers, etc.
    // from being attached because what would that mean aynways?
    // And, what would be the best way to resolve that abiguity?
    t_component* found_component= get_component<t_component>();

    if (found_component)
    {
        // so we already had a component of this type attached
        // just return it.
        return found_component;
    }

    // get the creator function from our hash table using the component's
    // guid as the key.
    // you can use whatever flavor of hashtable or map you prefer.
    const component_creator* creator= g_component_registry.get_value(t_component::type());

    // we don't know what kind of component we are creating until 
    // later, so our creator functions actually give back a pointer
    // which is cast to a c_component (the superclass of all components)
    c_component* new_component = NULL;

    // I'm not checking this against validity because internally, my hashtable
    // will barf if asked for a key that doesn't exist.
    new_component= (*creator)();

    // actually creating the component, however, could fail
    // if we were out of memory, for example...	
    if (new_component)
    {
        // components know which game object they are attached to
        new_component->gameobject= this;
		
        m_component_list.push_back(new_component);

        // finally, we want to give back the pointer cast to the
        // actual component type we are creating/attaching.
        return static_cast<t_component*>(new_component);
    }

    return NULL;
}

// walk the list of components
// check their type against the type we are looking for
// return a pointer to the component if found
// otherwise, return NULL
template <class t_component>
t_component* c_gameobject::get_component()
{
    t_component *result= NULL;	
	
    eastl::list<c_component*>::iterator component_iterator= m_component_list.begin();

    for ( ; component_iterator != m_component_list.end(); ++component_iterator)
    {
        // the eastl list is holding pointers to components, so the first check
        // where we dereferece the iterator is actually checking to see if the 
        // pointer to the component is not NULL
        if ((*component_iterator) && (*component_iterator)->get_instance_type() == t_component::type())
        {
            // we always cast to the pointer type we're looking for
            result= static_cast<t_component*>((*component_iterator));
            break;
        }		
    }

    return result;
}

// walk the component list
// check their type against the type we are looking for
// return true if found, otherwise false
template <class t_component>
bool c_gameobject::has_component()
{
    bool result= false;

    eastl::list<c_component*>::iterator component_iterator= m_component_list.begin();

    for ( ; component_iterator != m_component_list.end(); ++component_iterator)
    {
        if ((*component_iterator) && (*component_iterator)->get_instance_type() == t_component::type())
        {
            result= true;
            break;
        }
    }

    return result;
}

and gameobject.cpp

#include "gameobject.h"
#include "component.h"
#include "transform.h"

c_gameobject::c_gameobject() 
{
    // game objects are just a unique identifier
    // and a transform
    CoCreateGuid(&m_guid);	

    // all game objects have at least a transform.
    m_transform= add_component<c_transform_component>();
}

// iterate over each component and call its destruct method
c_gameobject::~c_gameobject()
{
    eastl::list<c_component*>::iterator component_iterator= m_component_list.begin();
	
    while (!m_component_list.empty())
    {
        if ((*component_iterator))
        {
            (*component_iterator)->destruct();
        }

        if (++component_iterator == m_component_list.end())
        {
            m_component_list.clear();
        }
    }
}

bool c_gameobject::operator ==(const c_gameobject& rhs) const 
{
    // which one of these is the right way?

    // this one uses memcmp, AND, if I want to return a bool, 
    // this gets converted from an int...which isn't super efficient
    //return (guid == rhs.get_guid());

    // I not certain that any object's data1 values would ever be 
    // identical if they were different objects...
    return (m_guid.Data1 == rhs.get_guid().Data1);
}

bool c_gameobject::operator !=(const c_gameobject& rhs) const
{
    return (m_guid.Data1 != rhs.get_guid().Data1);
}

void c_gameobject::update(double dt)
{
    eastl::list<c_component*>::iterator component_iterator= m_component_list.begin();

    for ( ; component_iterator != m_component_list.end(); ++component_iterator)
    {
        (*component_iterator)->update(dt);		
    }
}

In the next part, we’ll tackle components

template template parameters example

In this example you’ll learn how to use template template parameters. ¬†We’ll use the template template parameter to specify the memory allocation policy of some imaginary ‘manager’ class that games often have.

We’ll pretend that we have some kind of texture manager that is responsible for the life of a texture class. We’ll be using a template parameter to specify which allocation policy the manager will
use.


// The only requirement for our memory allocation policy is to have a static 
// function that returns a pointer to the type we are creating. Each policy
// should have an identically named function. Here we are calling ours 
// 'construct'.
template <class t_constructed>
struct s_allocation_policy_operator_new
{
    // this "constructor" takes no parameters,
    // but we could also make versions that do...
    static t_constructed* construct()
    {
        return new t_constructed;
    }
}

// here is another allocation policy using malloc
template <class t_constructed>
struct s_allocation_policy_malloc
{
    static t_constructed* construct()
    {
        return (t_constructed*)malloc(sizeof(t_constructed));        
    }
}

// now for the fun part:
// here we are going to do a couple of interesting things, first note how we
// inherit our manager class from a template parameter. Interesting!
// This is how we can later specify which allocation policy to use.
template <template <class t_constructed> class t_allocation_policy>
class c_texture_manager : public t_allocation_policy
{
...

public:
    // here the c_texture isn't a template parameter because we are
    // pretending that our manager always manages c_texture objects.
    // but c_texture could easily be an abstract base class for all of
    // the various types of textures
    // you might think that t_constructed is meant to fill this role within
    // the definition of c_texture_manager, but actually t_constructed here isn't
    // a part of c_texture_manager's definition at all and could be omitted, but
    // it IS a parameter to t_allocation_policy.
    c_texture* create_texture();
}

...

// and here is the implementation of create_texture.
// you can see how c_texture fills in the template parameter t_constructed
// for t_creation_policy
template <template <class t_constructed> class t_creation_policy>
c_texture* c_texture_manager<t_creation_policy>::create_texture()
{
    // here we call the allocation policy's static construct function.
    return t_creation_policy<c_texture>::construct();
}

// finally, here's how the client code would look.
// this texture manager uses the new operator.
typedef c_texture_manager<s_allocation_policy_operator_new> t_texture_manager;

// or, we could specify a different allocation policy.
// this one would use malloc
typedef c_texture_manager<s_allocation_policy_malloc> t_texture_manager;

...

extern t_texture_manager g_texture_manager;

...

c_texture* new_texture= g_texture_manager.create_texture();

Perhaps when you start your game project you haven’t yet written your memory manager and you start off using a policy that allocates objects using the global new operator, with this pattern we can easily later switch out new and use a custom memory manager.

have fun!