• Register

Gamieon is a one-developer part-time studio focused on creating video games for the desktop and mobile platforms. Since 2010 Gamieon has developed and released six games. Including beta distributions, Gamieon's products have netted a combined 300,000 downloads!

  • View media
RSS My Blogs

Recently I downloaded MagicaVoxel which lets you create and modify blocky objects, and bought PicaVoxel which lets you import them into Unity3D projects. The purpose was twofold: to help my friend Highsight develop his first game, and to have access to powerful tools in case I ever wanted to make a voxel art game.

Highsight claimed difficulties with Rigidbody objects flying through the imported voxel objects. Upon looking at how the MeshColliders were built for the voxel objects, I guessed that the issue was with the fact the colliders were paper thin. Seeing that all of the voxel faces were one-sided, I figured that the best way to handle the issue was to create a BoxCollider behind every face.

The script below, when attached to a voxel object, will iterate through all Chunk objects and generate bounding boxes for them on simulation startup:

(Click here to just download it)


using UnityEngine;
using System.Collections;
using PicaVoxel;

/// <summary>
/// Attach this script to a voxel object to generate box colliders for all the chunks therein
/// when the game or simulation begins. The advantage of this over using existing mesh colliders
/// is that these colliders have depth and are therefore less prone to objects going through or
/// other weird collision behavior happening
/// </summary>
public class PicaBoxColliderGenerator : MonoBehaviour 
{
    /// <summary>
    /// The thickness of a box collider. Would be nice to auto-calculate this someday
    /// </summary>
    public float thickness = 0.1f;

    /// <summary>
    /// True if the box colliders should be static
    /// </summary>
    public bool staticColliders = false;

	// Use this for initialization
	void Start () 
    {
        GenerateBoxColliders();
	}

    /// <summary>
    /// Generates box colliders for all child chunks of this object
    /// </summary>
    void GenerateBoxColliders()
    {
        foreach (Chunk c in gameObject.GetComponentsInChildren<Chunk>())
        {
            GenerateBoxColliders(c);
        }
    }

    /// <summary>
    /// Generates box colliders for a single child chunk of this object
    /// </summary>
    /// <param name="chunk">The chunk</param>
    void GenerateBoxColliders(Chunk chunk)
    {
        // MAJOR ASSUMPTION: The object is not static (or else mesh optimization occurs and you'll get an error getting the mesh)

        // First get the mesh information
        MeshFilter meshFilter = chunk.gameObject.GetComponent<MeshFilter>();
        Mesh mesh = meshFilter.sharedMesh;

        // MAJOR ASSUMPTION: Each pair of triangles is a rectangle

        // Now do for all rectangles
        for (int i = 0; i < mesh.triangles.Length; i += 6)
        {
            // Get the vertices of one of the triangles that make this rectangle
            //
            // v2 ------- v1
            //  |          |
            //  |          |
            // v3 -------  *
            //
            Vector3 v1 = mesh.vertices[mesh.triangles[i]];
            Vector3 v2 = mesh.vertices[mesh.triangles[i + 1]];
            Vector3 v3 = mesh.vertices[mesh.triangles[i + 2]];
            
            // Get the two sides of the triangle which also make up two edges of the rectangle
            // connected by the same vertex (v2)
            Vector3 a = v1 - v2;
            Vector3 b = v3 - v2;

            // Get the normalized vector of the rectangle facing inward
            Vector3 n = Vector3.Cross(a.normalized, b.normalized);

            // Get the center of the rectangle by calculating the midpoint of two diagonally opposing points
            Vector3 c = (v1 + v3) * 0.5f;

            // Create an empty object at the center of the rectangle and make it a child of the chunk
            GameObject go = new GameObject("ChunkBoxCollider");
            go.transform.SetParent(chunk.transform);

            // Position the object such that when we eventually add the collider, the "outermost" face of the collider
            // will be in the same plane as the rectangle
            go.transform.localPosition = c + n * thickness * 0.5f;

            // The object should always be facing the rectangle. This is so when we size the box collider,
            // we can be sure of the role that each axe has. Keep in mind that LookAt deals in world coordinates
            // so we need to adjust for the chunk's world rotation
            go.transform.LookAt(go.transform.position + chunk.transform.rotation * n, chunk.transform.rotation * b.normalized);

            // Now create the box collider
            BoxCollider boxCollider = go.AddComponent<BoxCollider>();

            // Size the box collider 
            boxCollider.size = new Vector3(a.magnitude, b.magnitude, thickness);

            // Make the collider static if desired
            go.isStatic = staticColliders;
        }
    }
}


The script has two properties

  • thickness: How thick the colliders should be (0.4 works well)
  • staticColliders: If true, all the colliders will be static

Keep in mind that if your voxel object is static, the script will have problems accessing the mesh data. You can address this by making the object not static.

Because of the time it takes to generate the BoxColliders, you may want to consider writing an Editor script based on PicaBoxColliderGenerator to generate those boxes at design time instead of run time.


Here is how the scene looked with no colliders, and how it looked with box colliders.

scene1

scene2


On testing it with box colliders, I had no issues with Rigidbodies flying through the voxel at reasonable speeds. Highsight found the same to be true as well.

I hope you find this helpful!


Check out my homepage and social feeds

And my projects!

Start a group Groups
Unity Devs

Unity Devs

1,618 members Hobbies & Interests

For all Unity developers and developers-to-be, both beginners and professionals!

Gamieon, Inc.

Gamieon, Inc.

1 member Developer

Gamieon is a one-developer part-time studio focused on creating video games for the desktop and mobile platforms. Since 2010 Gamieon has developed and...

Desura Publishing

Desura Publishing

190 members Entertainment & Press

Desura Publishing group is a group dedicated to all questions regarding game & mod publishing on Desura. Official features and updates on publishing progress...

Desura

Desura

10,151 members Entertainment & Press

Desura is a community driven digital distribution service for gamers, putting the best games, mods and downloadable content from developers at gamers...

Gamieon

Gamieon

4 members Developer

Gamieon is a small independently owned company devoted to developing innovative and high quality video games.

Comments
ArtisanCodesmith
ArtisanCodesmith

I'm new to IndieDB and ModDB and wish to invite a few people (random people picked from the online list lol) to view my game and start generating a few opinions, do you mind taking a quick look? The game is called Arkanius. Thanks, Artisan Codesmith. :)

Reply Good karma Bad karma+2 votes
AlexVSharp
AlexVSharp

Wow, well written. You should include this article in the Unity Dev's group. ;)

Reply Good karma Bad karma+3 votes
Post a comment
Sign in or join with:

Only registered members can share their thoughts. So come on! Join the community today (totally free - or sign in with your social account on the right) and join in the conversation.

Level
Avatar
Avatar
Last Online
Country
United States United States
Gender
Male
Friends
Become friends
Member watch
Follow
Desura
Statistics
Rank
2,199 of 594,717
Time Online
20 hours
Activity Points
1,091
Watchers
5 members
Comments
19
Site visits
2,429
Contact
Contact
Send Message
Homepage
Gamieon.com
ICQ
387263084
Twitter

Latest tweets from @gamieon

#hyperspacepinball for #steam is having an anniversary #sale of 80% off all this week! Store.steampowered.comT.co

Sep 26 2016

Check out my updated portfolio at Gamieon.com ! See released games and prototypes to...collaborate on?… T.co

Sep 24 2016

Watch @Highsight go from zero to #vive pong in barely an hour! T.co

Sep 22 2016

Just posted a new #texasbounty tech demo video with some new features since the last one #indiedev #gamedev Youtube.com

Sep 21 2016

RT @Highsight: Twitch.tv - This week's Indie Insights is starting now! Come give these games your #gamedev feedback.… T.co

Sep 20 2016

Tiltz 2.0 now available for Android and iOS for free! news Slidedb.com @slidedb #indiegaming

Sep 19 2016

New #devblog : Generating BoxColliders for #picavoxel imported objects in #unity3d Gamieon.comT.co

Sep 19 2016

#tiltz is now available for #iosgaming and #androidgaming #mobilegaming ! Youtu.be

Sep 19 2016

And you'll get every penny's worth! T.co

Sep 16 2016

I AM THE #JUGGERBOX #whatthebox

Sep 16 2016

Friends
shaulhadar
shaulhadar Online
Namelessness Online
swiftseraph
swiftseraph Online
Original_Speeder
Original_Speeder Online
hermesdavidms
hermesdavidms Online
NullSoldier
NullSoldier Online