Thursday, January 28, 2016

New Player AI

sing UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class PlayerController : MonoBehaviour {


public List<GameObject> bullets;
// Use this for initialization
void Start () {

}

private void shoot (Vector3 startPoint, Vector3 direction)
{
GameObject freeBullet;
foreach(GameObject bullet in bullets)
{
if(bullet.GetComponent<bulletAI>().isFree())
{
bullet.GetComponent<bulletAI>().shoot(startPoint, direction);
break;
}
}

}
// Update is called once per frame
void Update () {


float speed = 10 * Time.deltaTime;
Vector3 pos = this.GetComponent<Transform>().position;

Vector3 mousePoint = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10f ));
mousePoint.y = pos.y;

if(Input.GetKeyDown(KeyCode.Mouse0))
{
shoot(pos, mousePoint);
}

if(Input.GetKey(KeyCode.UpArrow))
{
pos.z += speed;
}
if(Input.GetKey(KeyCode.DownArrow))
{
pos.z -=speed;
}
if(Input.GetKey(KeyCode.RightArrow))
{
pos.x += speed;
}
if(Input.GetKey(KeyCode.LeftArrow))
{
pos.x -= speed;
}
this.GetComponent<Transform>().position = pos;


  this.GetComponent<Transform>().LookAt(mousePoint);

}

public void playerHit(Vector3 hitPoint)
{
Vector3 direction = this.GetComponent<Transform>().position - hitPoint;

this.GetComponent<Rigidbody>().velocity = direction.normalized * 20;
AudioSource source = this.GetComponent<AudioSource>();
source.Play();

//Debug.Log ("Hit");
}

BulletAI

Bullet AI

using UnityEngine;
using System.Collections;

public class bulletAI : MonoBehaviour {

private bool inUse;
private float TIME_ALIVE = 1;

private Vector3 disablePos;
private Vector3 direction;
private float timeAlive;

// Use this for initialization
void Start () {
inUse = false;
disablePos = this.GetComponent<Transform>().position;
timeAlive = 0;

}

// Update is called once per frame
void Update () {
if(inUse)
{
Vector3 pos = this.GetComponent<Transform>().position;
pos += direction * Time.deltaTime * 30;
this.GetComponent<Transform>().position = pos;

timeAlive += Time.deltaTime;
if(timeAlive > TIME_ALIVE)
{
timeAlive = 0;
disable ();

}
}
}

void disable()
{
timeAlive = 0;
this.GetComponent<Transform>().position = disablePos;
inUse = false;
}
public bool isFree()
{
return !inUse;
}
public void shoot(Vector3 start, Vector3 target)
{
inUse = true;
this.GetComponent<Transform>().position = start;
direction = target - start;
direction.Normalize();
timeAlive = 0;
}

void OnTriggerEnter(Collider other)
{

disable();
}


}

Wednesday, January 27, 2016

Post 5


Download here the latest unity project.

- We will add a sound to the player when it gets hit by the enemy.
-Add a AudioSource component to the Player (should be under the Audio components section when you press Add Component)
-Look for a sound in the internet or you can get one Here, open a windows folder with the file in it and drag it into Unity on top of the Project panel where the assets are, this will create a sound clip.
-Select the Player object and drag the sound clip to the audio source component where it says "clip".

-Add this to playerHit (in PlayerController script):
                AudioSource source = this.GetComponent<AudioSource>();
source.Play();
-Run unity we will hear the sound when hit by the enemy.

- You can get a  project with a sample maze Here, now run it and you can see how it works.

- Add a script to the camera then open the script and write this:

using UnityEngine;
using System.Collections;

public class CameraAI : MonoBehaviour {

public GameObject player;

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
Vector3 pos = this.GetComponent<Transform>().position;
Vector3 playerPos = player.GetComponent<Transform>().position;
pos.x = playerPos.x;
pos.z = playerPos.z;

this.GetComponent<Transform>().position = pos;



}
}

-To add a better effect we place the camera above player close enough so its hard to tell where to go.
-The camera has to  be rotated to point down.


Tuesday, January 26, 2016

Post 4

-Now we need to add a function in Player that will push the player backwards when touched by the monster. Here is the updated Code:

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {

Vector3 pos = this.GetComponent<Transform>().position;
if(Input.GetKey(KeyCode.UpArrow))
{
pos.z += 0.1f;
}
if(Input.GetKey(KeyCode.DownArrow))
{
pos.z -= 0.1f;
}
if(Input.GetKey(KeyCode.RightArrow))
{
pos.x += 0.1f;
}
if(Input.GetKey(KeyCode.LeftArrow))
{
pos.x -= 0.1f;
}
this.GetComponent<Transform>().position = pos;
}

public void playerHit(Vector3 hitPoint)
{
Vector3 direction = this.GetComponent<Transform>().position - hitPoint;

this.GetComponent<Rigidbody>().velocity = direction.normalized * 20;
//Debug.Log ("Hit");
}
}


- This function (playerHit) is public, so its visible by anyone and can be used by anyone, it returns void so we don't have to return anything, and receives a Vector3 called hitPoint, this is passed by the enemy and its the enemy position at the time it hits the player
-playerHit basically finds the direction is should move the player by using the hitPoint and the player position
-Then gets the Rigidbody component and applie a velocity to it using the direction we calculated and a rate (we use 20, which is a terrible way to do it but for this example it will suffice)

-Run Unity and we should have an enemy chasing the player, cooling down when it hits the player and the player bouncing away from the enemy.

Post 3

-We have to add a script to the enemy as well. We can call it EnemyAI, it looks like this:

using UnityEngine;
using System.Collections;

public class EnemyAI : MonoBehaviour {

public GameObject m_player;
// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {

Vector3 playerPos = m_player.GetComponent<Transform>().position;
Vector3 pos  = this.GetComponent<Transform>().position;
this.GetComponent<Transform>().position = Vector3.MoveTowards(pos, playerPos, 0.05f);
}

}


}

-For starters we added a public GameObject m_player, this object will show up in the script component in unity, so go back to unity.
-Select the enemy and look for the script component there should be a text box labeled m_player.
-Now from the left panel press the left mouse button on Player and don't let it go so you can drag the Player to that text box labelled m_player, drop the Player on it and now the enemy script can use the Player object (this is called "having a reference" of the player object).
-We can get the position of the player by using m_player.

-For this script we needed to make the enemy follow the user.
-In this case we use a function already supplied by Vector3 called MoveTowards, we pass three pieces of data, the position of the player, the position of the enemy and a "speed" value and in return we get a new position for the enemy which makes the enemy get closer to the player

-Now if we run this in Unity we will notice that the Enemy chases the player with no pause, and because of the physics, the enemy and the player roll around.

-To stop the rolling we are going to lock the rotation in the RigidBody component
-Select the player
-In the left panel look for the RigidBody Component and check the x,y,z boxes for rotation.
-Do the same for the Enemy.
-If you run unity now you will see that the enemy and player do not roll anymore.

-Now for the issue with the user not getting a rest when the enemy reaches him, in most games when the player gets hit they get a chance to recover otherwise they will get hit constantly and die, which can be frustrating. So to give the player a change to recover we can give the enemy a cooldown time, here is the updated code:

using UnityEngine;
using System.Collections;

public class EnemyAI : MonoBehaviour {

public GameObject m_player;
private float waitTime;
// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
if(waitTime >= 0)
{
waitTime -= Time.deltaTime;
//Debug.Log ("time " + waitTime);
}
else
{

Vector3 playerPos = m_player.GetComponent<Transform>().position;
Vector3 pos  = this.GetComponent<Transform>().position;
this.GetComponent<Transform>().position = Vector3.MoveTowards(pos, playerPos, 0.05f);
}

}

void OnTriggerEnter(Collider other)
{
waitTime = 0.5f;
m_player.GetComponent<PlayerController>().playerHit(this.GetComponent<Transform>().position);
}

}

- What we did here is add a waitTime variable that is private (so only the enemy can see it and use it)
- WaitTime is the cool down time, if this time is more than 0 then the enemy is cooling down, so we added a condition "if (waitTime >=0)" with this condition we make sure that if the waitTime is greater than 0 we take the elapsed time out of it (elapsed time can be found in the Time object its called deltaTime)
- If the time is 0 or less we will start moving the object (this is in the "else" area)

-OnTriggerEnter is a function called when something enters the area around and close to the enemy, if this happens we will update the wait time to be half a second so the enemy cools down for half a second and stays put.
-We also call a function in Player called playerHit, which will make the player bounce back when attacked. I will go into details on that in the next post.

-Now to get OnTriggerEnter to actually work we need to add a sphere collider to the enemy.
-Select Enemy and Add Component look for sphere collider and add it.
-In the components panel, in the sphere collider section there should be a "Is Trigger" check box, check it. Check in it activates the OnTriggerEnter Function in the EnemyAI script when another object with a rigid body enters it.

-We will have an error now since payerHit is not in Player yet.

Post 2

-Last classes we added a control script to our Player.
-To do this we selected the Player and in the right panel added a component, we added a new script, and we named it PlayerController.
-After opening it in MonoDevelop we added some code to read te input and move the player:

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {

Vector3 pos = this.GetComponent<Transform>().position;
if(Input.GetKey(KeyCode.UpArrow))
{
pos.z += 0.1f;
}
if(Input.GetKey(KeyCode.DownArrow))
{
pos.z -= 0.1f;
}
if(Input.GetKey(KeyCode.RightArrow))
{
pos.x += 0.1f;
}
if(Input.GetKey(KeyCode.LeftArrow))
{
pos.x -= 0.1f;
}
this.GetComponent<Transform>().position = pos;
}
}

- Some information about this script:
  • Start and Update are what we call functions, functions are like containers that hold code for some specific function, functions can be called many times from different parts of the code, making them great for taking away redundant code and encapsulating functionality.
  • "void" is what the function must return, which means nothing for Update and Start, functions could return numbers, letters, objects, addresses, and more.
  • The "()" is where we put in data we want to pass to the function, in this case Start and Update don't need any data so the "()" has nothing in between.
  • We use GetComponent to get components from that object, components are what we see in the right panel. In the case of this.GetComponent<Transform>() we are getting the Transform component, this component contains position, rotation and scale of the object.
  • We get the object's position and keep it in pos (which is a 3d vector with x,y,z coordinates, Vector3)
  • with Input.GetKey(KeyCode.UpArrow)) we get the state of the up arrow, if the user is pressing it or not. Input is called an "Object" this object exists for us to get information about any input, it can be keys, mouse, joysticks, screen presses, etc.
  • So once we get the position, and know what the user is doing we update the position coordinate affected and put it back into the component:
    • this.GetComponent<Transform>().position = pos;
  • Once we run the game in unity we should be able to move the player around.


Thursday, January 14, 2016

January 14



Things learned:

-Start Unity3d
-The left panel is called Hierarchy and contains the objects created so far.
-We should rename objects created to stay organized
-We can delete objects from the Hierarchy and if we double click an object it will zoom into it in the scene.
-The default right side panel, called Inspector, contains information about the objects in the scene.
-Each object contains components that change their appearance, state and behaviour.
-We translated, and scaled the floor, player and enemy using the Transform component.
-We learned to add a physics->RigidBody component to player and enemy so they have gravity and interact with each other and the floor.
-We learned to use the view widget  to get side, top, etc views and change from perspective to orthogonal views.

-The bottom panel shows the assets.
-Created a Material asset by right clicking in the assets panel.
-We added a Material to and object by dragging the material from the assets panel to the object.
-We saved the scene to keep our work.
-We started the game by using the Play button at the top of the UI as well as stopping the game with the same button.
-Changes done when the play button is active will be reversed once the game is stopped.
-We added a script to the player and ended trying to open the file in Monodevelop.