Sunday 28 February 2016

Virtual Joypad

This is a tutorial on how to create a virtual joypad for mobile controls. In this example, I will use it to move around a spaceship in the scene.

I used a nice skybox from here and the spaceship model is from the Unity project "Space Shooter" (found here).

This is my own version of virtual joypad, chances are there are more efficient ways to do it, however, this is what I came up with.

Let's start by dragging in the ship model in the scene and place it at origin and rotate it on its X axis by -90. We don't have to worry about it now as we are going to use only later on once the joypad is ready.

To make the visual joypad, create a Canvas and place 2 Images in it, one child of he other one. I called one Joypad (parent image)and the other one FrontKnob (child image). In the Source Image box, select the Knob sprite for both UI elements, which should be available with every Unity project (Fig 1). I rescaled the 2 images so they look like a joypad, like in Fig 2.

Fig 1

Fig 2

The Joypad image is anchored and positioned to the bottom left corner of the canvas. Its child image is anchored and positioned to the center.

Now, the Joypad script. Create a new C# script and assign it to the FrontKnob image.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class Joypad : MonoBehaviour, IDragHandler,IEndDragHandler {

 public Image parentImage;
 public float returningSpeed;

 float parentWidth;
 float maxDistance;

 Vector3 startingPosition;
 Vector3 vectorGenerated;

 bool isDraging = false;

 void Start () {

  parentWidth = parentImage.rectTransform.rect.width;
  startingPosition = transform.position;
  maxDistance = parentWidth / 2;  
 }

 void Update () {  
 
  vectorGenerated = transform.position - startingPosition;

  if (!isDraging)
   transform.position = Vector3.MoveTowards (transform.position, startingPosition, returningSpeed * Time.deltaTime); 
 }

 public void OnEndDrag (PointerEventData eventData)
 {
  isDraging = false;
 }

 public void OnDrag (PointerEventData eventData)
 {
  isDraging = true;
  Vector3 vectorToMouse = Input.mousePosition - startingPosition;

  Ray r = new Ray (startingPosition, vectorToMouse.normalized);

  Physics.Raycast (r);

  if (vectorToMouse.magnitude < maxDistance)
   transform.position = r.GetPoint (vectorToMouse.magnitude);
  else
   transform.position = r.GetPoint (maxDistance);
   
 }

 public float GetRelativeMagnitude()
 {
  float d = vectorGenerated.magnitude / maxDistance;
  return Mathf.Abs (d);
 }

 public Vector3 GetDirection()
 {
  return vectorGenerated.normalized;
 }
}

First thing we notice, is the I included the UnityEngine.EventSystem on line 4. This is necessary as we are going to implement 2 interfaces needed for the dragging mechanics. We can see these at the beginning of the class, after the Monobehaviour keyword we have IDragHandler and IEndDragHandler . This will force us to implement the methods OnEndDrag(...) and OnDrag(...).

In the Start() method, I beging by getting the width of the parent image, which is a public parameter, so I can quickly assign it in the inspector. I use this to determine the maximum distance when dragging our knob (the variable maxDistance). I could have very well just use a predefined float variable. Also, I store the initial position of the FrontKnob image.

In the Update(), I continuously calculate the vector the is originated from the starting position of the knob to its current position. This is use to calculate the distance of the knob from the center and the direction. We can see right away on line 61 the to get the direction I simply return the normalized version of this vector.

On line 31 I check whether the isDraging variable is set. If not, I will move the knob back to its starting position.

The first interface implementation we see is OnEndDrag(...). This is a listener that is called whenever we stop dragging our object (in our case, the FrontKnob image). When his method is called, we simply set the isDraging variable to false.

On line 40 is where everything happens. With the method OnDrag(...), an interface implementation, we can detect  when the object is being dragged around. First thing we do, is to set the isDraging to true. After that, we create a vector with origins at the starting position of the knob and points towards the mouse position on the screen.

Then, I create a ray with the same origins and direction of the just created vector and I cast it.

To position the knob while it's being dragged, I used raycasting. When I raycast, I checked the lengthof the vectorToMouse vector (line 49). If this distance is within the range, I detect the point on the ray at that particular distance and place the knob. Otherwise, I place it at its maximum distance allowed.

With this technique, we can keep dragging the knob around even when the mouse is way beyond the maximum distance range, however, the knob will only travel as far as the maxDistance float variable dictates.

The method on line 56 returns the so called relative distance. Basically, this is a value between 0 and 1: 0 when the knob is at the starting position, 1 when is at its maximum distance allowed. This value can now be used just like the float value we obtain when using Input.GetAxis(...).

This is pretty much all we need for the joypad.

Let's see now the PlayerMovement script:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class PlayerMovement : MonoBehaviour {

 public float speed = 10;

 float acc;
 Vector3 dir;

 GameObject joypad;
 Joypad pad;
 Rigidbody rb;

 // Use this for initialization
 void Start () {

  joypad = GameObject.FindGameObjectWithTag ("Joypad");
  pad = joypad.GetComponentInChildren<Joypad> ();
  rb = GetComponent<Rigidbody> (); 
 }
 
 // Update is called once per frame
 void Update () {

  acc = pad.GetRelativeMagnitude ();
  dir = pad.GetDirection ();

  Vector3 newPos = transform.position + (dir * acc * speed * Time.deltaTime);

  rb.MovePosition (newPos); 
 }
}

Pretty simple!

The pad parameter is the Joypad script we just analysed. Calling the 2 methods of this script GetRelativeMagnitude() and GetDirection(), we can have the acceleration and direction for our ship.

All we have to do is to move its rigibody accordingly (line 26 - 28).

Bear in mind that the direction obtained by the Joypad script works for X and Y axis, which is why we rotated our ship on the X axis at the beginning. By doing so, the ship follows the X and Y direction given by the joypad. If, for example, you were using a top view camera, your ship would be moving along the X an Z axis, and all you have to do is to create a new vector for movement.

Also, this example is done with mouse input, so you can try it out in the example scene. It would work exactly the same using touch input for mobile devices.

Example scene here.

Thursday 25 February 2016

Avatar Mask

From the Unity website, an avatar mask allow you to isolate parts of a model's anatomy, allowing the rest to ignore an animation.

In this example, I will take our character model (with animations found here) and get it to aim with his rifle.

To achieve that, I will create an avatar mask which will only affect arms and the head of the model, leaving the rest off it to be animated by the underlying animation. Please note that this example will only work with humanoid types models.

First thing, let's take our model into the scene, and remember to change it's animation type to humanoid. (Fig 1).

Fig 1

For basic movement I will use the same animator controller and scripts used in the Third Person Camera post, so I'm not going to re-explain that part. I reused the script called PlayerMovementImp, found on that post. Also, make a copy of that controller. I removed the parameters we do not need and I added a Boolean called Aim.  (Fig 2)

Fig 2
Do not forget to add a Rigidbody and  CapsuleCollider to our character, so we can move I around with the script.

If you saw the Third Person Camera post, the character is animated with its arm resting when idle, and moving accordingly when walking or running. We will override the arms movement using the mask.

Then, drag in the rifle model. to place it correctly, put the rifle object as a child of the player. More specifically, navigate through all the children of the player model until you find an object called Right_WP. Place the rifle as a child of this object at 0,0,0. (Fig 3).

Fig 3

At this point we can create an avatar mask.

Right click in the project folder, select Create -> AvatarMask.

I gave it the very original name PlayerMask.

Select now the avatar mask just created, open the Humanoid tab, and deselect (by clicking on) the legs, foot IK, the little "circle" you see below the character and the  chest. These body parts should turn red, like in Fig 3.

Fig 4

By doing this, any animation played over this mask will only affect the arms and the head of our model. The red coloured parts are disabled and they will be ignored by that animation, and they will be only affected by the animation in the Base Layer.

Let's click now on the animator controller. Go on the Layer tab, click on the little + icon to create a new layer and let's call it Aim Layer. The settings icon on the right will allow us to select the avatar mask we created. Also, give the variable Weight a value of 1and set the Blending to Override. (Fig 4).

Fig 5

The Weight will determine how much of the animation played in this layer we are going to see. If we leave it to 0, we will see nothing at all, the only animation played will be the one in the Base Layer. You will see in the example scene the effects of this parameter.

By choosing Override, the animation on the Aim Layer will completely override the one from the Base Layer, without any blending.

Select now the Aim Layer. We need to drag in 2 animations: one with the player having the arms resting while holding the rifle and the other one with the arms in aiming position.

Navigate to the folder Military_Rifle_01_Free_v2 -> FBX -> Animation, and drag in the animator the 2 clips called MIL2_M3_W2_Stand_Relaxed_Idle and MIL2_M3_W2_Walk_Aim_F_Loop.  Set the idle one as default.

Remember that we do not care about the legs movement, we simply want the arms movement.

Also, these 2 animations are contained in a FBX object, and we have to change, once again, the animation type to humanoid, for both of them.

From the MIL2_M3_W2_Stand_Relaxed_Idle state in the animator, create a transition to the other animation. Uncheck the HasExitTime box and set the conditions that Aim must be true. Do the same thing the other way, only with an opposite condition. You animator should look like the one in Fig 6.

Fig 6


Now, all we have to do is to feed the animator with the Boolean value for Aim.

In the player movement script, add these few line of code somewhere in the FixedUpdate(), where the rest of the movement take place:



1
2
3
bool aim = Input.GetMouseButton (1);

anim.SetBool ("Aim", aim);

Now we can move the player around just like in the other post. Whenever we hold the right mouse button, the player will go in aiming position.

As you will see in the example scene, the rest of the body moves according to the Base Layer animations, moving the character around just as before. When aiming, only the arms and the head will be affected. If you drag the Weight to 0, the arms will be moved by the animation played in the Base Layer, and they will animate according to the state the character is in.

Example scene here.

Wednesday 17 February 2016

State machine using inheritance

In this post I want to show you how I like to go about creating a state machine. A state machine is usually used (or at least, I use it) for things like the game states (pause, playing, gameover,ecc) or AI for NPCs, like different enemy states (patrolling, chasing, shooting...).

This is a fairly standard method and we can achieve the same thing using interfaces. If you want to know how you can use interfaces to do this, I suggest you to take a look at this tutorial found on the Unity official website.

In this example I will show you some code of an hypothetical game controller which can run 3 states: playing, pause and gameover.

First thing, the State class:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public abstract class State {

 protected string stateName;

 public abstract void OnStateEnter ();

 public abstract void UpdateState ();

 public abstract void OnStateExit ();

 public string getStateName()
 {
  return stateName;
 }

}

The State class is an abstract class, which means we will not be able to create instances of it. This is because all the states we are going to write are going to be derived from this base class, which is only intented to be used as a parent and we will not need objects of its type.

The string variable stateName is simply used to identify the state we are in in the console.

The 3 main methods used are also abstract methods. This implies that the classes which derive from this class MUST implement the methods body, which, in more complex projects, will most definitely behave in different ways.

Now that we have the base class ready, we can go on and write the 3 classes for our 3 states.

The pause state:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class GameController_PauseState : State {

 GameObject obj;

 public GameController_PauseState(GameObject g,string name)
 {
  stateName = name;
  obj = g;
 }

 public override void OnStateEnter ()
 {
  Debug.Log (obj.name + " enetered " + stateName); 
 }

 public override void OnStateExit()
 {
  Debug.Log (obj.name + " exited " + stateName);
 }

 public override void UpdateState ()
 {
  Debug.Log (obj.name + " is running " + stateName);
 }


}

The playing state:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class GameController_PlayingState : State {

 GameObject obj;

 public GameController_PlayingState(GameObject g,string name)
 {
  stateName = name;
  obj = g;
 }

 public override void OnStateEnter ()
 {
  Debug.Log (obj.name + " enetered " + stateName);
 
 }

 public override void OnStateExit()
 {
  Debug.Log (obj.name + " exited " + stateName);
 }

 public override void UpdateState ()
 {
  Debug.Log (obj.name + " is running " + stateName);
 }
}

The game over state:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class GameController_GameOverState : State {

 GameObject obj;

 public GameController_GameOverState(GameObject g,string name)
 {
  stateName = name;
  obj = g;
 }

 public override void OnStateEnter ()
 {
  Debug.Log (obj.name + " enetered " + stateName);

 }

 public override void OnStateExit()
 {
  Debug.Log (obj.name + " exited " + stateName);
 }

 public override void UpdateState ()
 {
  Debug.Log (obj.name + " is running " + stateName);
 }

}

You will notice that these three classes very much look alike, and that is because for this simple example these three states don't do much more than displaying the name of the state that is acutally running. In a real game development environment you will want these classes to perform specific actions: for example, in the OnStateEnter() of the GameController_PlayingState class you will want to enable all the movement and input detection, whereas in the GameController_GameOverState you will do the exact opposite.

For each state I declared a GameObject variable, which is a reference to the game object which all these states are going to be part of. In our case, a GameController object. I could have very well put that variable in the State class.

The constructor is the same for each class, which simply gets passed the state name and the object reference.

Then, the three abstract methods are overridden. It is important to use the override keyword, and that is because an abstract method is implicitly a virtual method. If you omit the override keyword the compiler will start screaming at you.

Now the three state classes are written we can create the actual monobehaviour object script, which I called GameController.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class GameController : MonoBehaviour {

 State currentState = null;

 GameController_PauseState pauseState;
 GameController_GameOverState gameoverState;
 GameController_PlayingState playingState;

 void Start () {

  pauseState = new GameController_PauseState(this.gameObject,"Pause State");
  gameoverState = new GameController_GameOverState(this.gameObject,"GameOver State");
  playingState = new GameController_PlayingState(this.gameObject,"Playing State");

  setState (playingState);
 
 } 

 void Update () { 

  currentState.UpdateState (); 
 }

 public void setState(State newState)
 {
  if(currentState!=null)
   currentState.OnStateExit();

  currentState = newState;

  currentState.OnStateEnter ();
 }

 GameController_GameOverState getGameOverState()
 {
  return gameoverState;
 }

 GameController_PauseState getPauseState()
 {
  return pauseState;
 }

 GameController_PlayingState getPlayingState()
 {
  return playingState;
 }
}

Here we can see the beauty of inheritance and polymorphism.

We create a State type variable and we set it to null. Remember, we cannot instanciate objects of type State, but we can create variables of that type.

Then I create the 3 members of three different state types and, in the Start() method, I initialize them calling their respective constructor.

Next, the setState(...) method: this method accepts a State type variable which represents the states we wish to transit to. In its body, we first ensure the current state variable is not null, which is definitely going to be when the game starts as it has only been initialized to null.

Otherwise, if we are transiting from another state, the OnStateExit() of that particular state will be called.
After that, we simply assign the new state to the current state variable and call the OnStateEnter().

In the Update(), we simply call the UpdateState() method, which will run for which ever state object is contained in the currentState member.

This method is of course a public method so it can be called by other game objects in order to change the game state: for example, imagine your player being killed by an enemy while in the playing state. At this point you want to switch to the GameOver state and display a game over screen. From the player script you can call setState(...) and pass it in its own variable gameoverState using the getGameOverState() method.

This is a pretty decent and organized way to create a state machine, which can be used for different purposes.


Friday 12 February 2016

Custom inspector

Creating a custom inspector allows for quicker and more agile development. In this example, I will show you how I created a simple "laser" object which can work in three different modes. I then modified the inspector for the object so I can select from it the mode I wish to use and only the variables relevant to that particular mode will show up, so as to avoid to mess around with variables that have nothing to do with that specific running mode.

To make it more clear, my "laser column" will have 3 modes: STATIC, inn which the laser beam is simply not moving. When in MOVING mode the laser beam will go up and down, and in the inspector we can tweak a float variable which determines the speed. Finally, the INTERMITTENT mode will cause the beam to go on and off, using 2 float variables to select the timing.

Before I go any further, here's a short video of the project:


I know the videos here a pretty bad quality, I will upload them on YouTube later on so I can get a better resolution. For the moment, I apologize for the "not exactly HD" quality of the content.

To achieve this, we need 2 scripts: one for the actual laser object, in which we write the behavior of the laser beam, and another one for modifying the inspector of that script.

My laser object consists of two cubes, scaled so they look like two columns. One of them has a child object, which I called "LaserPoint", which has 2 components attached: a line renderer (our beam) and the LaserPoint script. The 2 cubes are then put as child of a parent empty object, so they can be moved around as one single object. (Fig 1).

Fig 1


This is the LaserPoint script:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
public class LaserPoint : MonoBehaviour {

 public enum LaserTypes
 {
  STATIC,
  MOVING,
  INTERMITTENT
 }

 public LaserTypes laserType;

 private float maxHeight ;
 private float minHeight;

 LineRenderer lineRend;

 Ray ray;
 RaycastHit hit;
 Vector3 otherPoint;

 public float movingSpeed;

 public float time_off;
 public float time_on;

 float timer;
 float heightToReach;
 bool on;

 // Use this for initialization
 void Awake () {

  lineRend = GetComponent<LineRenderer> ();

  ray = new Ray (transform.position, -transform.right);

  timer = 0;

  minHeight = transform.position.y - 0.8f;
  maxHeight = transform.position.y + 0.8f;
 
 }
 
 // Update is called once per frame
 void Update () {

  switch (laserType) {
   
  case LaserPoint.LaserTypes.STATIC:   
   DrawLaserBeam ();
   break;
   
  case LaserPoint.LaserTypes.MOVING:
   MovingBehaviour();
   break;
   
  case LaserPoint.LaserTypes.INTERMITTENT:
   IntermittentBehaviour();
   break;
  }
 
 }

 void MovingBehaviour()
 {

 if (transform.position.y <= minHeight)
   heightToReach = maxHeight;
  else if(transform.position.y >= maxHeight)
   heightToReach = minHeight; 
  
  transform.position = Vector3.MoveTowards(transform.position,new Vector3(transform.position.x,heightToReach,transform.position.z),movingSpeed*Time.deltaTime);
  DrawLaserBeam ();

 }

 void IntermittentBehaviour()
 {
  timer += Time.deltaTime;

  if (timer >= time_on && on) {
   timer = 0;
   on = false;
  }

  if (timer >= time_off && !on) {
   timer = 0;
   on = true;
  }

  if (on)
   DrawLaserBeam ();
  else
   lineRend.enabled = false;
 }

 void DrawLaserBeam()
 {
  if (!lineRend.enabled)
   lineRend.enabled = true;

  ray = new Ray (transform.position, -transform.right);
  if (Physics.Raycast (ray, out hit, 50)) {
   // Debug.Log("Laser hitting: " + hit.collider.name);
   
   lineRend.SetPosition(0,transform.position);
   lineRend.SetPosition(1,hit.point);
   
   
  }
 }
}

I'm not going to go into the details of this script as this is not what this post is bout, but I will give you a general guideline. I assume that you are familiar with enumerations, raycasting, line renderer and other basic features.After declaring all the variables I need, in the Update() method I simply check the LaserType variable to check which mode has been selected and I call the relative method.

In the MovingBehavoir() I take the LaserPoint object (which has this script attached) and I just move it up and down according to the variables maxHeight and minHeight, and I draw the beam at each call.

The IntermittentBehaviour() method uses the float variable time to create a simple timer which is used to determine the seconds for which the LineRenderer will be on and off.

In the Update() we can see that for the STATIC mode I just draw the beam and nothing else happens.

When it comes to actually drawing the laser in the DrawLaserBeam() function, first thing I do is to enable the LineRenderer component. Then I cast a ray towards the right, knowing that the other column (the cube object) is going to be there, and I set the position of the 2 points of the line renderer. I do not check for any layer when casting the ray, so if any other object will go between the columns and crossing the laser beam, we will see the beam itself "hitting" that object, as the second point of the line renderer (hit.point on line 108) will be on the object obstructing the beam. (Fig 2).

Fig 2

Now, the other script. The custom inspector for the LaserPoint script will allow me to choose the mode, thanks to the enumerations, and only the variables relevant to that mode will be displayed, so it becomes "less confusing" when placing laser objects in the scene.

One important thing to remember, every time we write a custom inspector script we need to place the script inside the Editor folder.

I called the script Laser_CI, and this is it:



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[CustomEditor(typeof(LaserPoint))]
public class Laser_CI : Editor {
 
 public override void OnInspectorGUI ()
 {
  LaserPoint myTarget = (LaserPoint)target;

  myTarget.laserType = (LaserPoint.LaserTypes)EditorGUILayout.EnumPopup ("Operating mode", myTarget.laserType);

  switch (myTarget.laserType) {

  case LaserPoint.LaserTypes.STATIC:

   EditorGUILayout.HelpBox("Static type",MessageType.Info);
   break;

  case LaserPoint.LaserTypes.MOVING:

   myTarget.movingSpeed = EditorGUILayout.FloatField("Moving Speed",myTarget.movingSpeed);
   EditorGUILayout.HelpBox("Moving type",MessageType.Info);
   break;

  case LaserPoint.LaserTypes.INTERMITTENT:
   myTarget.time_on = EditorGUILayout.FloatField("Seconds on",myTarget.time_on);
   myTarget.time_off = EditorGUILayout.FloatField("Seconds off",myTarget.time_off);
   EditorGUILayout.HelpBox("Intermittent type",MessageType.Info);
   break;
  }

 }

}

First thing we notice on line 1 is the CustomEditor(...) instruction, which basically tell the engine what script we are customizing. Also, this class will need to inherit from Editor rather than from MonoBehavior. All we need to do now is to override the function OnInspectorGUI(), which is the default function used to draw all the public variables of the scripts we attach to game objects.

If, for example, we were to leave this function overridden but empty, the LaserPoint script attached to the LaserPoint object would look like this:


Notice how the script is visible in the inspector, but non of the public variables are drawn, as we simply did not tell the compiler to draw them.

On line 6, I create a LaserPoint type variable called myTarget, which is a reference to the script we are trying to customize. To get the object we use the variable target: this is a default variable used to get a reference of the script we want to create a custom inspector for. However, the target variable is of type Object, therefore we need to cast it to the type we need, which is LaserPoint. At this point we can access all the variables in the LaserPoint script through the myTarget variable.

O line 8, I use the EditorGUILayout.EnumPopup(...) method to get the enumeration drop down menu drawn in the inspector. The String parameter we pass in will be the text displayed for that variable, while the myTarget.laserType parameter is the variable itself. (Fig 3).

Fig 3
Because this is a read method, we need to re-assign the myTarget.laserType variable to it so it stays updated, and it needs to be casted to our enumerations type, which is LaserTypes, as the EditorGUILayout.EnumPopup(...) method returns a general System.enum type of object.

Next, I perform a simple switch according to the mode selected.

If STATIC mode was chosen, in the inspector I simply draw a HelpBox to remind the user what mode they are in. I will be doing this for each mode. (Fig 4).

Fig 4
For the MOVING mode, I will get the float variable to be drawn in the inspector so we can change the speed. The EditorGUILayout.FloatField (..) works like the method we use for the enumeration, passing a String variable for the variable displayed name ad the variable itself fromt the script, which is then re-assigned. (Fig 5).

Fig 5

Finally, I do the same thing for the INTERMITTENT mode, only this time I display the 2 variables used to change the timing.(Fig 6).

Fig 6
This is obviously a very small example, but it shows the potential of using a custom inspector, allow for a better workflow and, simply put, keep things nice and tidy.

Tuesday 9 February 2016

Upload Unity games on Blogger

Here's a quick post on how I upload my example scenes on my blog. This will allow you to export anything to do in Unity onto your blogger website.

First, you need a Dropbox account. Once you have something ready to export in Unity, build the project for "WebPlayer". You will end up with a folder with two files: let's say for example our project is called AwesomeGame, the two files will be named AwesomeGame.html and AwesomeGame.unity3d.

Next, go to your Dropbox account, log in and upload the "*.unity3d" file (in our fictional example, AwesomeGame.unity3d). Once you click on share, you will get a link that should look something like this:

https://www.dropbox.com/s/w1098asdjlkj3409/AwesomeGame.unity3d?dl=0

You need to edit this link into this:

https://dl.dropboxusercontent.com/s/w1098asdjlkj3409/AwesomeGame.unity3d

Change the left hand side of the link and rim off the  "?dl=0" on the right hand side.

Then, open your "AwesomeGame.html" with notepad and look for this line:

u.initPlugin(jQuery("#unityPlayer")[0], "AwesomeGame.unity3d").

Replace the link you just edited inside the brackets, like this:


u.initPlugin(jQuery("#unityPlayer")[0], "https://dl.dropboxusercontent.com/s/w1098asdjlkj3409/AwesomeGame.unity3d").

At this point, you can upload to Dropbox you AwesomeGame.html file that you just modified. Once uploaded, get the sharing link and do the same thing you did for he first file.

From this:

https://www.dropbox.com/s/w1098asdjlkj3409/AwesomeGame.html?dl=0

To this:

https://dl.dropboxusercontent.com/s/w1098asdjlkj3409/AwesomeGame.html

This last link is the one you will use as active link that will redirect users to the game page.

That is all. ow you can upload games on blogger anytime and very easily.

Sunday 7 February 2016

Third person camera

I would like to show you how I came up with the movement of the camera for the previous post. I couldn't come up with any particularly fancy way to do it and I didn't want to check tutorials on how to do it either, I kind of wanted to achieve that "by myself", really just for the sake of it. So I went with the most basic approach: trigonometry, using sine and cosine.

Also, I will show how the player movement is related to the camera, so when we press the "up" key (or the "w"), the character will move forward, and by that I mean, away from the camera.

This is the camera script:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public class CameraMovement : MonoBehaviour {

 public Transform target;

 public float speed;
 public float zoomSpeed;

 public float angularSpeed = 50;
 public float camDistance = 10;

 public float angle = 0;
 public float xPos;
 public float yPos;
 public float zPos;

 // Use this for initialization
 void Start () {
 
 }
 
 // Update is called once per frame
 void Update () {

 

  if (Mathf.Abs(Input.GetAxis ("Mouse ScrollWheel")) > 0.01f)
   camDistance -= Input.GetAxis ("Mouse ScrollWheel") * zoomSpeed;

  camDistance = Mathf.Clamp (camDistance, 3, 40);

  angle -= Input.GetAxis ("Mouse X") * angularSpeed * Time.deltaTime;

  yPos -= Input.GetAxis ("Mouse Y") * speed/10;
 

  if (angle > 360)
   angle = 0;
  if (angle < 0)
   angle = 360;

  yPos = Mathf.Clamp (yPos, 1, 10);

  zPos = target.position.z + Mathf.Sin (Mathf.Deg2Rad * angle) * camDistance;
  xPos = target.position.x + Mathf.Cos (Mathf.Deg2Rad *angle) * camDistance;

  Vector3 cameraPosition = new Vector3 (xPos, yPos, zPos); 

  if(interpolation)
   transform.position = Vector3.Lerp (transform.position,cameraPosition, speed * Time.deltaTime);
  else
  transform.position =  cameraPosition;
 
 
 }

 void LateUpdate()
 {

  transform.LookAt (target.position);


 }
}

After declaring all the variables I need, I start by checking the mouse scrollwheel for the zoom (Line 26). This basically does nothing but moving the camera towards the player or away from it. To void going through the player, I clamp the zoom value (Line 29).

The variable angle is changed according to the mouse x movement on line 31, while the camera X position is governed by the Y movement of the mouse (line 33). Then I proceed to calculate the position of the camera with respect to the player: for the Z position, I start from the Z position of the target (an empty game object child of the player character) and I add the sine of the variable angle, multiplied by the cameraDistance, which, as we are using trigonometry, is our radius. I do the same thing for the X position, only this time I use the cosine of the angle.  When it comes to moving the camera I have 2 options for simple transform or interpolation, you will see it in the example scene.

By doing this, the camera rotates around the player according to the angle given. Finally, after the camera movement is done, I simply call the LookAt() function in the late update.

Now, the player script:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
public class PlayerMovementImp : MonoBehaviour {

 public float turnSmoothing = 15f;
 public float speedDampTime = 0.1f;

 private Animator anim;
 bool run;

 void Awake()
 {
  anim = GetComponent<Animator> ();
 }

 void FixedUpdate()
 {
  float hor = Input.GetAxis ("Horizontal");
  float ver = Input.GetAxis ("Vertical");

   run = Input.GetKey (KeyCode.Space);

  Move (hor, ver,run);
 }


 public void Move(float h, float v,bool run)
 {
  if (h != 0f || v != 0f) {

      Rotate (h, v);
      if(!run)
       anim.SetFloat ("Speed", 0.5f, speedDampTime, Time.deltaTime);
      if(run)
       anim.SetFloat ("Speed", 1f, speedDampTime, Time.deltaTime);
    } else { 
   anim.SetFloat ("Speed", 0f);
    }


 }

 void Rotate(float h, float v)
 {
  Vector3 cam = new Vector3 (Camera.main.transform.position.x, transform.position.y, Camera.main.transform.position.z);
  Vector3 playerToCam = cam - transform.position;
  playerToCam.Normalize (); 

  Vector3 finalVector = -playerToCam * v + Camera.main.transform.right *h;

  finalVector.Normalize ();

  Vector3 targetDirection = new Vector3 (h, 0f, v);
  Quaternion targetRotation = Quaternion.LookRotation (finalVector, Vector3.up);
  Quaternion newRotation = Quaternion.Lerp (GetComponent<Rigidbody>().rotation, targetRotation, turnSmoothing * Time.deltaTime);
  GetComponent<Rigidbody>().MoveRotation (newRotation);

 }

 public Animator getAnim()
  {
   return anim;
  }


 public bool getRun()
 {
  return run;
 }
}

You should be familiar with the functions used in the Awake() and the FixedUpdate().

In the Move() function I just detect whether the player has pressed any of the movement keys and I pass values to the animator (Line 25 to 39). I also called the Rotate() function, which is really where everything happens.

First, I create a Vector3, which represents the camera position but with the Y position as that of the player character, so it will rotate only on the Y axes. Then, I calculate the vector that goes from the player model too the just create camera position position, and I normalize it, so that is going to be the direction.

Next, I calculate our final Vector, which is the direction towards which the player will rotate to. I used -playerToCam, as we want the player to move in the opposite direction of the camera, multiplied y the vertical input float to give it a magnitude and then I added the camera right vector multiplied by the Input horizontal float. When the player press the right key, the direction of the character will be the right vector of the camera, therefore, we will see the character going to the right. When the left key is pressed, the direction will be still the right vector but this time multiplied by -1, causing the character to go the opposite direction of right....which is left. So, the player left and right movement are always calculated in respect of the camera forward vector. I hope this is clear enough as explanation :)

Example scene here.

Thursday 4 February 2016

AI & Basic Combat Animation

I set up a small scene in which I wanted to experiment with third person combat and I wanted to share it here to see what you think. I used the same model and animations I've been using for my 3D tutorials, found here, some animations from the standard assets of course and some very cool take down animations which I got here.

The scene is really simple, here is only one enemy patrolling the small area and you can choose to activate or deactivate his sight and hearing, so you can see the AI in action..or not.

I could make a tutorial, with scripts and pictures about it but it would take a ridiculous amount of words and time, however, I will make tutorials for some of the features of this small project, like state machine for artificial intelligence, avatar mask and maybe some shader stuff.

I took advantage of the power of inheritance to write the states of the enemy, you know, patrolling, chasing, searching ecc, that allowed for a quick mapping and programming of each state and transition between one another. The enemy will be able to hear you running and walking and will come and check where the noise comes from, going back to patrolling the area if he doesn't see you. If he does, well, he will just start chasing you and shoot you like mad.

Bot characters use similar animators, however the enemy is driven by a NavMeshAgent component and the animation parameters are changed according to the state the enemy is in: for example, while patrolling I feed a lower value for speed to the animator, so the blend tree will play the walking animation, while when the enemy is chasing you, he will be running.

It is not perfect yet, it tends to rotate weirdly occasionally, and he shader is also misbehaving, a couple of things I have to look into.

The player has pretty standard moving mechanics, I also tried to implement a basic "combat system", which is not a system at all: when the player is behind the enemy and close enough, if they are facing roughly in the same direction the enemy's shader will highlight the enemy's model, signalling to the player that it is in range for an attack. If you left click at that point, the player and the enemy will be set into position and the combat animations will play. It was my first attempt to combat mechanics and I dare to say I'm quiet happy about it.

The scene can be played here.