This tutorial shows a way to create the most basic game mechanics of Minecraft: blocks that can be broken to drop items and a first person player who can pick up the dropped items.
Developed with
Unity Version 5.1.0f3 PersonalMonoDevelop-Unity Version 4.0.1.OS X Yosimite Version 10.10.3 (14D136)
Should work the same in Windows just with the usual OS interface differences.
- Preliminaries
- Basic Objects and Mechanics
- First Person Character
- Build the Game
- Pickup Mechanic
- Sound Effects
- Terrain
- Optional Stuff
Create a 3D project and select the default layout in the editor.
-
Click to start a new project. (The following is what you should see when you start Unity. If, on the other hand, you already started Unity and have an existing project open, select
New Project...under theFilemenu.)Name the project.
3D should be highlighted.
Click the create the project.
-
Select the default layout.
Here we build the ground, the block prefab, and the item drop prefab.
You can think of the following as a quick and dirty substitute for a layer of bedrock.
-
Hierarchy | Create | 3D Object | PlaneIn the
Hierarchy View, click theCreatedropdown, select3D Objectand thenPlane. -
Inspector | Transform | Scale ( 16, 1, 16)Scale the plane in the
xandzdirections for plenty of room to play on. TheInspectorshows the components of the game object that is selected in theHierarchy View, so make sure thePlanegame object is selected in theHierarchy Viewbefore modifying theTransformcomponent. -
Inspector | Transform | Position ( 0, -0.5, 0)Lower the plane by half a unit. Doing this leaves space for unit cubes centered at
y=0so they will be on top of the plane.
We will now make a block that disappears when clicked on.
-
Hierarchy | Create | 3D Object | CubeCreate a
Cubegame object. -
In the
Inspector, renameCubetoBlock.Select the
Cubegame object in theHierarchy Viewfirst.Click on
Cubein the field at the very top of theInspector View.Change it to
Block.Note that we can name it whatever we want or even leave it with the default name. We just have to be consistent with what we call it thereafter. Since cubes in Minecraft are called “blocks”, it makes sense to call them that in this project.
-
Drag the
Blockgame object from theHierarchy Viewinto theAssetsfolder of theProject View.This makes it a “prefab”. Prefabs can be added to the game multiple times resulting in multiple game objects that are clones of the prefab. Then changes to the prefab apply to all of those game objects. This is very useful to avoid having to modify lots of game objects just to make a simple change. Another reason it is useful to make prefabs is because they can be “instantiated” from scripts dynamically at run time. We will eventually want to do this in order to produce a procedurally generated terrain of blocks.
-
Drag a few
Blockprefabs into the scene. -
In the
Inspectorfor each block, manually assign their position coordinates to be integers and make them all havey=0in particular.Observe that Unity automatically numbers the game objects generated from prefabs.
-
File | Save SceneSelect
FileandSave Scene.We will only have the one scene, so no need for a very purposeful name. Let's just name it
Scene.Now a scene asset named
Scenewill appear in theAssetsfolder of theProject View. -
File | Save ProjectSelect
FileandSave Project.The project already has a name from when we created it, so there will not be a prompt for naming it.
-
In the
Assetsfolder of theProject View, right-click and selectCreate | C# Script -
Rename it to
MineBlock.Its default name is
NewBehavior. Just type over that to change it toMineBlock.Now double-click the
MineBlockC# asset. That will cause the script to be loaded in Mono.There is a
Startfunction and anUpdatefunction. They are empty to start with. We could write code in them, but we won't for now. We can also add other functions. We will add another function soon.It is important to realize first and foremost, however, that this script needs to be “attached” to a game object (or multiple game objects). Let's go ahead and attach it to our block prefab before delving into actual coding in the script.
-
Go back to Unity and select the
Blockprefab.Now click and drag the
MineBlockscript asset over to theAdd Componentbutton in theInspector Viewfor theBlockprefab and drop it there.The
MineBlockscript will be added as a component to theBlockprefab.Note that the
Add Componentbutton activates a menu through which we could have added the script as well. (There are usually multiple different ways of accomplishing the same thing.) -
Go back to Mono and add the following
OnMouseDownfunction to theMineBlockscript.Here's the code for you to copy-and-paste if necessary:
void OnMouseDown() { Destroy( gameObject); }However, it is recommended that you type the code yourself to help you learn the patterns.
-
Save the script in Mono.
-
Go back to Unity and run the game by clicking on the play button.

After clicking play, the buttons will be colored blue signifying that the game is playing.

While the game is running, click on some of the blocks and watch them
disappear. They disappear because of the `Destroy` statement in the
`OnMouseDown` function of the `MineBlock` script that is attached to the
block game objects via the `Block` prefab. Whenever the mouse button is
clicked with the mouse cursor hovering over a block, the `OnMouseDown`
function of that block executes and thus the `Destroy(gameObject)`
statement executes. Note that `gameObject` refers to the game object to
which the script that contains the function that's executing is attached.
Click the play button again to stop the game.
**WARNING:** If you fail to stop the game before going on to make changes
to the game, your changes will be lost when the game is stopped. You
*must* stop the game before making changes that you want to keep. Note
that it can sometimes be useful to make temporary changes to the game
while it is running just for the purpose of diagnostics and
experimentation, but in any case you should always be alert to whether the
game is running or not before making changes.
- Save the scene and the project.
In the next section we are going to add a new game object to the scene.
To keep the scene view clean in preparation for that, we will now hide the
original Block game object that we used to make the Block prefab. Also,
eventually, we will be placing multitudes of blocks from a script at run time
in some systematic way and will want to remove all of the hand-placed blocks
from the initial scene. For now, we will leave the other few blocks that were
added to the scene via the prefab just to have something there in the
meantime. We do want to hide the original one, though, because it occupies
the special origin location that other new game objects will occupy by default.
(Alternatively, we could just move it out of the way, but we are going to
want to hide it eventually anyway so let's just do it now.)
-
In the
Hierarchy View, select theBlockgame object. -
In the
Inspector View, uncheck the checkbox next to the game object's name field.That game object should no longer appear in the scene. It is still listed in the
Hierarchy Viewalthough dimmed.
In Minecraft, when a block is “mined” it can drop a resource which appears as a smaller version of the block floating in the space that the original block had occupied. This section shows how to create a dropped block prefab and cause it to be instantiated in place of blocks whenever blocks are destroyed.
-
Hierarchy | Create | 3D Object | CubeCreate another
Cubegame object. -
Rename it
DroppedBlock. -
Inspector | Transform | Scale (0.5,0.5,0.5)Make it smaller.
-
Inspector | Transform | Rotate (15,0,5)Rotate it.
Feel free to adjust the scale and rotation as desired. To make it look like a dropped item, it just needs to be smaller and tilted.
-
Make a prefab from the
DroppedBlockgame object by dragging it into theAssetsfolder of theProject View. -
Select the source
DroppedBlockGame Object and hide it. -
Go to Mono and edit the
MineBlockscript by adding this linepublic GameObject droppedBlockPrefab;before the Start function:
-
Go back to Unity and select the
Blockprefab.Look at the
Inspector Viewand see theDropped Block Prefabfield in theMine Block (Script)component.That field was put there automatically by the Unity editor after we declared the
droppedBlockPrefabvariable in theMineBlockscript.Now drag the
DroppedBlockprefab into thatDropped Block Prefabfield.This will cause the
droppedBlockPrefabvariable in theMineBlockscript to be initialized to theDroppedBlockprefab when the game runs. It is in this way that our script will have access to that prefab. -
Finally, add this line
Instantiate( droppedBlockPrefab, transform.position, droppedBlockPrefab.transform.rotation);to the
OnMouseDownfunction of theMineBlockscript right before theDestroystatement.This causes the
DroppedBlockprefab to be “instantiated” as a game object at the same position as the block that was clicked and with the rotation that we specified in theInspectorfor theDroppedBlockprefab. -
Save the script.
-
Go back to Unity and save the scene and project.
-
Play the game.
See that when you click a
Blockgame object, aDroppedBlockgame object appears in its place. -
Stop the game.
This section adds a first person character to the scene so that the player can look around and move around in a way similar to Minecraft.
Beware: The first person character asset is provided by Unity in the
Standard Assets package, so Standard Assets must be installed. If they are
not, the Import Package menu in the very first step below will not contain
the shown options. In that case, go to the Asset Store:
and download/import Standard Assets from there instead.
-
Assets | Import Package | CharactersIf you do not see the shown options in your
Import Packagemenu, see the note above. You will need to install/import them from theAsset Store. -
Click the "None" button to uncheck all of the options.
-
Click the checkbox next to
FirstPersonCharacter.Now just the
FirstPersonCharacterasset is selected. -
Click the
Importbutton.Notice the new
StandardAssetsfolder inside yourAssetsfolder of theProject View.You will also notice an error message in the Unity status bar. If you click the
Consoletab next to theProjecttab, you will see other messages, too. There are a couple of dependencies that we need to import before we can use theFirstPersonCharacterstandard asset. -
Assets | Import Package | CrossPlatformInputAnd now there is a new folder named
Editorinside theAssetsfolder of theProject View. -
Assets | Import Package | UtilityNo additional new folders will appear at the top level of the
Assetsfolder this time, but you'll see that the error messages have disappeared now.
-
Under the
Assetsfolder in theProject View, expandStandardAssets,Characters,FirstPersonCharacter, and then selectPrefabs.Notice the
FPSControllerprefab. That's what we are going to use. -
Drag the
FPSControllerprefab into the scene.Drop it somewhere near the current camera.
-
Remove the old camera which is called
Main Camera.The
FPSControllerprefab comes with its own camera built in. -
Adjust the
ycoordinate of theFPSControllerposition so that it is completely above the plane, e.g.,y=2.It's okay if it starts higher than the plane. It will fall to the surface when the game begins.
-
Save the scene and project.
-
Run the game.
Notice that the camera follows the cursor as expected for a first person character. Also, you can use the
WASDkeys to make the player walk and theSPACEbar to make it jump. -
Stop the game.
-
Adjust the scale of the
FPSControllerto(0.5,0.9,0.5).This will make it possible for the character to fit through one block wide and two block high openings (eventually).
-
Save.
The way the player interacts with the scene will be more natural if the cursor is always in the center of the screen (like the crosshairs of Minecraft).
-
Select the
Assetsfolder in theProject Viewand create a newC# Script. -
Rename the new script to
MouseLock. -
Select the FPSController game object.
-
Scroll down in the
Inspector Viewuntil theAdd Componentbutton is visible. -
Drag the
MouseLockasset onto theAdd Componentbutton of theInspectorfor theFPSController.Now the
Mouse Lock (Script)component should appear in the list of components for theFPSController. -
Double-click the
MouseLockC# asset in theProject Viewto open it in Mono.Notice that Mono now has two tabs, one for the
Mineblockscript that we edited previously (and will return to later) and one for the newMouseLockscript that we will edit now. -
To lock the mouse cursor when the game begins, put this line
Cursor.lockState = CursorLockMode.Locked;in the
Startfunction. -
To unlock the mouse cursor when the user presses the
ESCkey, put these linesif( Input.GetKeyDown("escape")) { Cursor.lockState = CursorLockMode.None; }in the
Updatefunction. -
Save the script.
-
Go back to Unity and save the scene and the project.
-
Run the game.
If you're lucky, the mouse cursor will lock in the middle of the
Game Viewuntil you hit theESCkey.The mouse lock mechanism can be a bit flakey in the
Game View. Sometimes it doesn't work right. To see it work reliably, we might need to build the game as a native application. -
Stop the game.
In my experience, if the cursor lock doesn't work the first time the game is run, stopping it and then running it again will make it work, so try running it again at this point. (And then stop it before proceeding.)
-
File | Build Settings...From the
Filemenu, selectBuild Settings.... -
PC, Mac & Linux Standalone.From the
Platformlist, selectPC, Mac & Linux Standalone. -
Target PlatformSelect your operating system from the
Target Platformmenu. -
Click the
Build And Runbutton. -
Name the application something like
MakingMinecraft. -
Click
Save. -
Select your desired resolution from the
Configurationdialog that pops up. -
Check the
Windowedcheck box.This will make the application run inside a window rather than in full screen. (Optionally, you can leave that checkbox unchecked to run in full screen mode, but it might be tricky to escape out of the game when it is running that way.)
-
Play!Click the
Play!button and enjoy playing the game as a native application.When finished playing, press
ESCto unlock the cursor and then close the application. -
Back in Unity, close the
Build Settingswindow.
When the player runs into a dropped block, the dropped block game object should disappear as the player “picks up” the item.
-
Select the
DroppedBlockprefab in theAssetsfolder of theProject View. -
In the
Inspector View, check theIs Triggercheck box of theBox Collidercomponent. -
In the
Assetsfolder, create a new C# Script. -
Rename it to
PickUp. -
Select the
DroppedBlockprefab again. -
Drag the
PickUpscript over to theAdd Componentbutton in theInspectorfor theDroppedBlockprefab.Then the
Pick Up (Script)component should appear in the list of components in theInspectorfor theDroppedBlockprefab. -
Save the scene and project.
-
Double-click the
PickUpscript to open it in Mono.Now you will see three tabs in Mono with the one for the
PickUpscript in front. -
Add the following
OnTriggerEnterfunctionvoid OnTriggerEnter() { Destroy( gameObject); }after the
Updatefunction like this: -
Save the script.
-
Back in Unity, run the game.
Click on a block to make it drop a dropped block item and then run your character into the dropped block. It should disappear.
-
Stop the game.
Breaking blocks and collecting dropped items is much more satisfying with sound effects!
-
Download the following two
wavfiles:Save them in the
Assetsfolder.Do that with both files:
dig_grass1.wavandpop.wav. Then you will see both of those files in theAssetsfolder on your harddrive.They will also appear in the
Assetsfolder inside the Unity editor.
-
In the
MineBlockscript in Mono, add this linepublic AudioClip mineSound;at the top of the
MineBlockclass: -
Save the
MineBlockscript in Mono. -
Go back to Unity. Select the Block prefab from the
Assetsfolder and notice theMine Soundfield in theMine Block (Script)component in theInspector. -
Drag the
dig_grass1asset into that field. -
Go back to Mono and add this line
AudioSource.PlayClipAtPoint( mineSound, transform.position);inside the
OnMouseDownfunction before theDestroystatement. -
Save.
-
Go back to Unity and save the scene and project.
-
Play the game.
If you have audio on your computer, you should now hear the familiar sound of a dirt block breaking when you click on a block.
-
Stop the game.
Challenge: As an exercise, see if you can now add the sound effect for picking up dropped blocks without looking at the following instructions.
-
In the
PickUpscript in Mono, add this linepublic AudioClip pickupSound;at the top of the
PickUpclass: -
Save.
-
Back in Unity, select the
DroppedBlockprefab and see thePickup Soundfield in thePickUp (Script)component in theInspector. -
Drag the
popasset into that field. -
Go back to Mono and add this line
AudioSource.PlayClipAtPoint( pickupSound, transform.position);in the
OnTriggerEnterfunction before theDestroystatement: -
Save.
-
Go back to Unity and save the scene and project.
-
Play the game.
After breaking a block to make it drop a dropped block, when you run your character into the dropped block you should hear the popping sound of the item being collected.
-
Stop the game.
The walking/stepping sound effects that come as part of the FPSController may
be too loud relative to the sound effects for breaking and picking up blocks.
Let's turn the FPSController sound effects down a little.
-
Select the
FPSControllergame object in theHeirarchy View. -
In the
Inspector View, adjust theVolumeslider in theAudio Sourcecomponenent.About half volume feels right to me, but adjust to suit yourself.
-
Save the scene and project.
-
Play the game.
-
Stop the game.
-
If unsatisfied with the volume balance, go back to step 2, otherwise continue to the next section.
Now that the basic breaking and collecting mechanics are in place, let's generate an actual terrain rather than a scattering of hand-placed blocks.
-
Create a new C# Script called
GenTerrain. -
Select the
Planegame object. -
Add the
GenTerrainscript as a componenet on thePlanegame object. -
Double click the
GenTerrainscript to open it in Mono. -
Add this line
public GameObject block;at the top of the
GenTerrainclass just before theStartfunction. -
Save.
-
Go back to Unity and see the
Blockfield in theGenTerraincomponent in theInspectorfor thePlanegame object. -
Drag the
Blockprefab into that field. -
Back in Mono, add these lines
int i, j, k; int nk; int n = 32; int h = 8; for( j=-n; j<=n; j++) { for( i=-n; i<=n; i++) { nk = (int)( Mathf.Floor( h*( 1 + Mathf.Sin( 2*Mathf.PI*i/n) * Mathf.Sin( 2*Mathf.PI*j/n) ))); for( k=0; k<nk; k++) { Instantiate( block, new Vector3( i, k, j), Quaternion.identity); } } }to the
Startfunction in theGenTerrainclass: -
Save.
-
Back in Unity, select the
FPSControllergame objectand adjust its
Positionso that the player starts in the middle of the world and up high.
-
Delete the manually placed blocks.
-
Save the scene and project.
-
Play the game.
-
Stop the game.
The following list of tasks can be done in any order and independently of the others. They are listed roughly in order of how much time they should probably take.
-
If you wish, you may turn off shadows for the
Blockand/orDroppedBlockprefabs.In the
Mesh Renderercomponent, you can toggle both whether the object casts shadows and whether the object receives shadows.
-
Put this line
transform.RotateAround( transform.position, Vector3.up, 100*Time.deltaTime);in the
Updatefunction of thePickUpclass:The first argument
transform.positionspecifies the center of the rotation. The second argumentVector3.upspecifies the axis of rotation. The third argument, a multiple ofTime.deltaTimespecifies the speed of the rotation. Adjust that multiple100to suit.
-
Right click in the
Assetsfolder and select toCreateaMaterialasset.It will be named
New Materialby default.Rename it to
BlockMaterial. -
Click the white color box toward the top of the
Inspectorfor theBlockMaterial. -
Choose a color.
-
Close the
Colorselector. -
Select the
Blockprefab in theAssetsfolder. -
Click the little triangle to expand the
Materialsproperty of theMesh Renderercomponent.See the
Element 0field. -
Drag the
BlockMaterialasset into that field -
Save the scene and project.
-
Play the game.
The blocks should now appear in whatever color you selected for the material.
-
Stop the game.
Exercise: Complete this task on your own. Make the game play the pop.wav sound when the player picks up a dropped block.
-
Create | UI | TextCreate a
UITextgame object in theHiearchy View. It will appear as a child of aCanvasobject which get automatically created for this purpose.There is also an
EventSystemgame object that is created automatically at this point which we will ignore for now. -
Set an
Anchor Preset.Select the
Anchor Presetmenu in theInspectorfor theTextgame object.Hold down the
Altkey. See how the annotations change to signify position.Select a desired position. I propose the bottom middle since that is where the Minecraft hotbar is displayed.
-
Change the contents of the
Textfield fromNew Textto0. -
Increase the font size a bit:
-
Center the text by clicking the center
Alignmentbutton in theParagraphsection. -
Go to Mono and select the
PickUpscript tab. -
Add this
usingdirectiveusing UnityEngine.UI;at the top of the file:
This will allow us to access the
Textcomponent of theTextgame object. -
Add this private static variable declaration
private static int numCollected = 0;and this private variable declaration
private Text numCollectedText;at the beginning of the
PickUpclass: -
Put this line
numCollectedText = GameObject.Find("Text").GetComponent<Text>();in the Start function:
-
Finally, put these lines
numCollected++; numCollectedText.text = numCollected.ToString();in the
OnTriggerEnterfunction: -
Save.
-
Go back to Unity and save the scene and project.
-
Play the game.
See the counter increment whenever you pick up a dropped block.
-
Stop the game.
We will replace the cursor pointer with crosshairs and allow for relocking after unlocking.
This task involves first making an image of crosshairs.
The following instructions are for GIMP,
the GNU Image Manipulation Program, which is
a free image editing application similar in functionality to Photoshop.
Feel free to produce the image in whatever image editing application you prefer
or even just find an image of crosshairs online.
(The image file format can be PNG or JPG. Maybe it can be other formats,
too, but I'm not sure.)
-
Run GIMP and create a new image.
Adjust the size to something fairly small and probably square is best. For the tutorial, we'll do a 16×16 image.
Click
Okayto create the new image.In the zoom dropdown menu select 800%.
That way we can edit the image pixels easily.
-
Select the
Pencil Toolfrom theToolboxwindow.Make sure that under
Tool OptionstheModeisNormaland theBrushis1. Pixeland theSizeis1.00. -
Draw horizontal and vertical lines for crosshairs.
Maybe decorate them a bit.
Feel free to draw your crosshairs however you like. They don't have to look the same as this.
-
Make the white background of the crosshairs transparent.
Select
Color To Alpha...from theColorsmenu.It should default to white as the color to convert to
Alpha, i.e., make transparent, so just clickOkay. -
Export the image to a
PNGfile.Expand the
Select File Typemenu.Expanded, it will show a list of file types to select from:
Select
PNG image.Now name the file
crosshairs.png.bytes.Select the
Assetsfolder of your project to save it in and then click theExportbutton.A
PNGfile with a.bytesextension on the file name is very unusual! Unity wants it that way, but GIMP is skeptical. You will need to confirm that you do want to go with that unusual name.You will be presented with another dialog window containing various options.
Just click the
Exportbutton to accept the defaults. -
Go to Unity and notice the new
crosshairs.pngasset in theAssetsfolder. -
Go to the
MouseLockscript in Mono and add these linespublic TextAsset crossHairsRaw; private Texture2D crossHairs;at the top of the
MouseLockclass: -
Put these lines
crossHairs = new Texture2D(16,16); crossHairs.LoadImage(crossHairsRaw.bytes); Cursor.SetCursor( crossHairs, new Vector2(8,8), CursorMode.Auto);in the
Startfunction of theMouseLockclass after the line that sets the cursor lock state:If you created a crosshairs image that is bigger than 16×16, you'll need to adjust the numbers for the size of the
Texture2Dobject and theVector2argument in theSetCursorfunction call. TheVector2object specifies which point inside the image should be used as the cursor point. For a crosshairs shaped cursor it makes sense for it to be in the middle of the cursor image. -
Put this line
Cursor.SetCursor( null, Vector2.zero, CursorMode.Auto);inside the
ifstatement of theUpdatefunction after the line that unlocks the cursor:That sets the cursor back to the default.
Vector2.zeromeans coordinates(0,0)which are at the top left corner of the cursor image which corresponds to the tip of the point of the default cursor. -
Save.
-
Now go back to Unity and select the
FPSControllerin theHierarchy View.Scroll down in the
Inspector Viewfor theFPSControllerand notice theCross Hairs Rawfield in theMouse Lock (Script)component. -
Drag the
crosshairs.pngasset into thatCross Hairs Rawfield of theMouse Lock (Script)component. -
Save the scene and project.
-
Play the game.
The cursor should change to the crosshairs shape.
-
Stop the game.
You might have to stop and restart the game in order to get it to work. Also, when running the game inside the unity editor, the cursor many not change back from the crosshairs cursor when you press
ESC, or at least not until you move the cursor outside of theGame View.
-
Mouse click to lock cursor. Add
else ifclauseelse if( Input.GetMouseButtonDown(0)) { Cursor.lockState = CursorLockMode.Locked; Cursor.SetCursor( crossHairs, new Vector2(8,8), CursorMode.Auto); }after
ifstatement in theUpdatefunction:As usual, this might not work flawlessly when running the game in the Unity editor. Try doing a
File | Build & Run.
We will use the Unity GL graphics library.
-
Create a new C# script.
-
Call it
WireFrame. -
Attach it to the
FirstPersonCharactergame object. The GL functions are typically called from a script attached to the camera, and our camera is in theFirstPersonCharacter. (See the Unity GL documentation for more information) -
Double-click the
WireFramescript asset to open it in Mono and add the following linespublic Material wireMaterial; public GameObject targetBlock;at the top of the class:
The
wireMaterialobject will be used for draw lines with GL. ThetargetBlockobject will be the block which lines are to be drawn around. -
Save.
-
Go back to Unity and create a new Material asset.
Name it
WireMaterial.Change it to black.
-
Select the
FirstPersonCharacterobject and drag theWireMaterialasset into the corresponding field of theWireFramescript. -
With the
FirstPersonCharacterstill selected, drag theBlockprefab into theTarget Blockfield of theWireFramescript.Note that this is just temporary. In later steps, we will code the
targetBlockto be assigned dynamically at run time based on which block the player is looking at. -
Open the
MineBlockscript in Mono and add the following linepublic GameObject fpsController;at the top of the class:
-
Add this line
fpsController = GameObject.Find("FirstPersonCharacter");to the
Startfunction: -
Add functions
OnMouseEnterandOnMouseExitvoid OnMouseEnter() { } void OnMouseExit() { }at the bottom of the class after the
OnMouseDownfunction: -
Add this line
fpsController.GetComponent<WireFrame>().targetBlock = gameObject;to the
OnMouseEnterfunction:This assigns the
Blockgame object that the player is pointing at to become thetargetBlockin theWireFramescript. Now we need to code theWireFramescript to actually draw a wireframe around that block. (There is a loose end to the mechanism inMineBlockthat we will take care of later. If the player looks away from a block but not at another block, the last block the player was looking at will remain highlighted with a wireframe. But let's not worry about that until theWireFramescript is actually drawing something.) -
Back in the
WireFramescript add this functionvoid OnPostRender() { }at the end of the class:
-
Add these lines
if( targetBlock) { GL.PushMatrix(); wireMaterial.SetPass(0); GL.Begin(GL.LINES); // // Left to right lines // TODO // // Up and down lines // TODO // // Front to back lines // TODO // GL.End(); GL.PopMatrix(); }to the
OnPostRenderfunction:There are three sets of four lines that need to be drawn around the cube. There is one set of four edges on a cube for each of the three directions in 3D space.
-
The way a GL line works is by specifying the starting point and ending point of the line with two consecutive calls to
GL.Vertex.The four lines in the right to left direction can be specified relative to the
targetBlock.transform.positionlike this:GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.left + 0.51f*Vector3.forward + 0.51f*Vector3.up); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.right + 0.51f*Vector3.forward + 0.51f*Vector3.up); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.left + 0.51f*Vector3.back + 0.51f*Vector3.up); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.right + 0.51f*Vector3.back + 0.51f*Vector3.up); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.left + 0.51f*Vector3.forward + 0.51f*Vector3.down); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.right + 0.51f*Vector3.forward + 0.51f*Vector3.down); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.left + 0.51f*Vector3.back + 0.51f*Vector3.down); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.right + 0.51f*Vector3.back + 0.51f*Vector3.down);The factor of
0.51is to make the lines hover a slight bit out from the actual edges of the cube (just like in Minecraft, as you may have noticed).The four lines going up and down can be specified like this:
GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.left + 0.51f*Vector3.forward + 0.51f*Vector3.up); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.left + 0.51f*Vector3.forward + 0.51f*Vector3.down); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.left + 0.51f*Vector3.back + 0.51f*Vector3.up); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.left + 0.51f*Vector3.back + 0.51f*Vector3.down); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.right + 0.51f*Vector3.forward + 0.51f*Vector3.up); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.right + 0.51f*Vector3.forward + 0.51f*Vector3.down); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.right + 0.51f*Vector3.back + 0.51f*Vector3.up); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.right + 0.51f*Vector3.back + 0.51f*Vector3.down);And the four lines along the front to back edges of the cube can be specified like this:
GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.left + 0.51f*Vector3.forward + 0.51f*Vector3.up); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.left + 0.51f*Vector3.back + 0.51f*Vector3.up); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.left + 0.51f*Vector3.forward + 0.51f*Vector3.down); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.left + 0.51f*Vector3.back + 0.51f*Vector3.down); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.right + 0.51f*Vector3.forward + 0.51f*Vector3.up); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.right + 0.51f*Vector3.back + 0.51f*Vector3.up); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.right + 0.51f*Vector3.forward + 0.51f*Vector3.down); GL.Vertex( targetBlock.transform.position + 0.51f*Vector3.right + 0.51f*Vector3.back + 0.51f*Vector3.down);Replacing each respective
TODOin theOnPostRenderfunction with the above lines of code results in this:The
ifstatement checks to be suretargetBlockexists before attempting to wire frame it. This prevents Unity from becoming confused bytargetBlock.transformafter the player clicks and breaks the block that they are looking at. It doesn't make sense to access the transform of a game object that no longer exists. -
Finally, let's tie up the loose end mentioned above. Currently, if the player moves the cursor off of a block and into the sky or plane or something other than another block, that last block that the player was looking at remains highlighted with a wire frame.
Add this line
public bool drawWireFrame;to the top of the
MineBlockclass: -
Add this line
drawWireFrame = false;to the
Startfunction: -
Set
drawWireFrametotrueinOnMouseEnterand set it tofalseinOnMouseExit. -
Now, in the
WireFramescript, augment the condition in theifstatement as follows:if( targetBlock && targetBlock.GetComponent<MineBlock>().drawWireFrame)
- TODO

















































































































































































































