4 Hour Code/Assets
To be fair 1 hour of the above was me banging my head against the wall or the keyboard, I went for my cat but she ran away. The logic for this code is a mix of simple and fustrating. This could be looked at as rudimentry AI, as it is able to follow you and knows when to stop, it also will not venture to far from its home. I am planning on making each planet a "home base" but that can wait for later. I really need to work on my commenting more.
using UnityEngine;
using System.Collections;
public class EnemyShip : MonoBehaviour
{
public float SpeedMax = 10f;
public float SpeedMin = 7f;
public int rotationSpeed = 50;
public int followRange = 75;
public float chaseTime = 5;
public float patrolRaduis = 10;
public float maxPatrolDistance = 100;
public static float moveSpeed;
private Vector3 patrolRaduisV3;
private Transform playerShip; //the enemy's target var moveSpeed = 3; //move speed var rotationSpeed = 3; //speed of turning
private Transform myTransform; //current transform data of this enemy
private Vector3 myStartPosition;
private Vector3 myTarget = new Vector3(0,0,0);
private Vector3 direction = new Vector3(1, 0, 0);
private float startChaseTime;
enum EnemyState
{
Patrol,
Attack,
Chase,
Return
}
EnemyState enemyState;
void Awake()
{
myTransform = transform;//cache transform data for easy access/preformance
enemyState = EnemyState.Patrol;
}
void Start()
{
playerShip = GameObject.FindWithTag("Player").transform; //target the player
moveSpeed = Random.Range(SpeedMin, SpeedMax);
startChaseTime = chaseTime;
myStartPosition = myTransform.position;
myTarget = myTransform.position;
myTarget = new Vector3(myTarget.x, 0, myTarget.z);
}
void FixedUpdate()
{
switch (enemyState)
{
case EnemyState.Patrol:
Patrol();
if (Vector3.Distance(playerShip.transform.position, myTransform.position) < followRange)
{
enemyState = EnemyState.Attack;
}
if (Vector3.Distance(myStartPosition, myTransform.position) > maxPatrolDistance)
{
enemyState = EnemyState.Return;
}
break;
case EnemyState.Attack:
Follow();
if (Vector3.Distance(playerShip.transform.position, myTransform.position) > followRange)
{
enemyState = EnemyState.Chase;
}
break;
case EnemyState.Chase:
Follow();
chaseTime -= Time.deltaTime;
if (chaseTime <= 0)
{
enemyState = EnemyState.Return;
chaseTime = startChaseTime;
}
break;
case EnemyState.Return:
Return();
// Need to convert all the floats to Int other wise the physics engin will not be able to make float = float
if ((int)myTransform.position.x == (int)myStartPosition.x && (int)myTransform.position.z == (int)myStartPosition.z)
{
enemyState = EnemyState.Patrol;
}
break;
}
}
void Patrol()
{
if ((int)myTarget.x == (int)myTransform.position.x && (int)myTarget.z == (int)myTransform.position.z)
{
patrolRaduisV3 = Random.insideUnitSphere * patrolRaduis;
myTarget = patrolRaduisV3 + myTransform.position;
myTarget = new Vector3(myTarget.x, 0, myTarget.z);
}
else
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(myTarget - myTransform.position), rotationSpeed * Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
}
void Follow()
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(playerShip.position - myTransform.position), rotationSpeed * Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
void Return()
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(myStartPosition - myTransform.position), rotationSpeed * Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
}
Saturday, 28 March 2015
Unity 5: The Search for a Shield (ContactPoint)
3 Hours Research
Shields I have learned alot about .shaders and DirectX and OpenGL. In an attempt to make a shield I have learned the basics of shaderlab and CG, as well as other shader languages. Ultimately I the only thing I have really learned is that the old shaderlab codes do not work with unity 4.6/5.
http://wiki.unity3d.com/index.php/Shield
The goal of this was to take and modify this code. To modify you can then take Collisions, which have the method ContactPoint. This calculates the exact point of contact allowing for things to happen at the exact transform of a Collision; as well as the direction.
Example:
foreach (ContactPoint contact in collision.contacts)
{
Object theShip = Resources.Load(EnemiesToCreate[EnemyNumber].name);
enemyShip = (GameObject)Instantiate(theShip);
enemyShip.transform.position = contact.transform;
}
Shields I have learned alot about .shaders and DirectX and OpenGL. In an attempt to make a shield I have learned the basics of shaderlab and CG, as well as other shader languages. Ultimately I the only thing I have really learned is that the old shaderlab codes do not work with unity 4.6/5.
http://wiki.unity3d.com/index.php/Shield
The goal of this was to take and modify this code. To modify you can then take Collisions, which have the method ContactPoint. This calculates the exact point of contact allowing for things to happen at the exact transform of a Collision; as well as the direction.
Example:
foreach (ContactPoint contact in collision.contacts)
{
Object theShip = Resources.Load(EnemiesToCreate[EnemyNumber].name);
enemyShip = (GameObject)Instantiate(theShip);
enemyShip.transform.position = contact.transform;
}
Friday, 27 March 2015
Unity 5: Vector3.Distance
1 Hour Research.
I am trying to make it so enemies will spawn at MIN distance of 100 unites away from the player in any direction. I tried numerous while loops with many playerObject.transform.position + or - 100 bools in it to no avail. Then I found Vector3.Distance. The code I could use for this is:
float distance = Vector3.Distance(enemyShip.transform.position, playerObject.transform.position)
It calculates the total distance from the enemy ship to the player ship. But then I realized that there are nearly an infinite number of floats... So if I were to use:
while (distance < 100f)
{
enemyShip.transform.position = new Vector3(playerObject.transform.position.x + Random.Range(-125, 125), 0, playerObject.transform.position.z + Random.Range(-125, 125));
}
It would go through several million calculations before it found a distance that may be equal to greater than 100.
Back to the drawing board.
Edit****************************
1 Hour Code/Assets
I found a use for Vector3.Distance, when creating a new level this code will take a number of random game objects and spawn them, the if statement makes it so they will not spawn within 100 unity units of the player GameObject. In this case for random objects they all need to have the same names with different numbers, you cannot miss numbers else the code will break.
for (int c = 0; c < NumberOfPlanets; c++)
{
int randomPlanet = Random.Range(1,5);
Object planetClone = Resources.Load("Planet"+randomPlanet) as GameObject;
GameObject planet = (GameObject)Instantiate(planetClone);
planet.transform.position = new Vector3(Random.Range(-500, 500),0,Random.Range(-500, 500));
if ((float)Vector3.Distance(planet.transform.position,player.transform.position) < 100f )
{
planet.transform.position = new Vector3(Random.Range(-500, 500),0,Random.Range(-500, 500));
}
}
I am trying to make it so enemies will spawn at MIN distance of 100 unites away from the player in any direction. I tried numerous while loops with many playerObject.transform.position + or - 100 bools in it to no avail. Then I found Vector3.Distance. The code I could use for this is:
float distance = Vector3.Distance(enemyShip.transform.position, playerObject.transform.position)
It calculates the total distance from the enemy ship to the player ship. But then I realized that there are nearly an infinite number of floats... So if I were to use:
while (distance < 100f)
{
enemyShip.transform.position = new Vector3(playerObject.transform.position.x + Random.Range(-125, 125), 0, playerObject.transform.position.z + Random.Range(-125, 125));
}
It would go through several million calculations before it found a distance that may be equal to greater than 100.
Back to the drawing board.
Edit****************************
1 Hour Code/Assets
I found a use for Vector3.Distance, when creating a new level this code will take a number of random game objects and spawn them, the if statement makes it so they will not spawn within 100 unity units of the player GameObject. In this case for random objects they all need to have the same names with different numbers, you cannot miss numbers else the code will break.
for (int c = 0; c < NumberOfPlanets; c++)
{
int randomPlanet = Random.Range(1,5);
Object planetClone = Resources.Load("Planet"+randomPlanet) as GameObject;
GameObject planet = (GameObject)Instantiate(planetClone);
planet.transform.position = new Vector3(Random.Range(-500, 500),0,Random.Range(-500, 500));
if ((float)Vector3.Distance(planet.transform.position,player.transform.position) < 100f )
{
planet.transform.position = new Vector3(Random.Range(-500, 500),0,Random.Range(-500, 500));
}
}
Thursday, 26 March 2015
Unity 5: Follow the player
1 Hour Code/Assets
By applying this simple script to an enemy GameObject they will follow any tag named player. I have not created a system that allows for more then one player. This also allows for variable speed, for each GameObject but it is easy to remove.
public float SpeedMax = 10f;
public float SpeedMin = 7f;
public int rotationSpeed = 5;
public Vector3 direction = new Vector3(0,0,0);
public static float moveSpeed;
Transform target; //the enemy's target var moveSpeed = 3; //move speed var rotationSpeed = 3; //speed of turning
Transform myTransform; //current transform data of this enemy
void Awake()
{
myTransform = transform;//cache transform data for easy access/preformance
}
void Start()
{
target = GameObject.FindWithTag("Player").transform; //target the player
moveSpeed = Random.Range(SpeedMin, SpeedMax);
}
void Update ()
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
By applying this simple script to an enemy GameObject they will follow any tag named player. I have not created a system that allows for more then one player. This also allows for variable speed, for each GameObject but it is easy to remove.
public float SpeedMax = 10f;
public float SpeedMin = 7f;
public int rotationSpeed = 5;
public Vector3 direction = new Vector3(0,0,0);
public static float moveSpeed;
Transform target; //the enemy's target var moveSpeed = 3; //move speed var rotationSpeed = 3; //speed of turning
Transform myTransform; //current transform data of this enemy
void Awake()
{
myTransform = transform;//cache transform data for easy access/preformance
}
void Start()
{
target = GameObject.FindWithTag("Player").transform; //target the player
moveSpeed = Random.Range(SpeedMin, SpeedMax);
}
void Update ()
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
Unity 5: Infinitely Omni Directional Scrolling Background
2 Hours Research
After much research, trial and error, I have found the code that allows for this. For some reason SetTextureOffset will not work, nor is any other method I tried efficient enough to be effective.
For this method you need a background with a seamless texture that covers the whole camera view, then a controller that allows for 2d movement. Drop the Player GameObject onto the public GameObject and the backgrounds material onto the Material section. You need to include the /100, realistically anything greater then /10 will work. Each tile is worth 1 unity unit. So if your player GameObject were to move 1 unit the background would go to a new tile.
public Material material;
public GameObject player;
void Start()
{
material = renderer.material;
}
void FixedUpdate()
{
renderer.material.mainTextureOffset = new Vector2(player.transform.position.x / 100, player.transform.position.y / 100);
}
After much research, trial and error, I have found the code that allows for this. For some reason SetTextureOffset will not work, nor is any other method I tried efficient enough to be effective.
For this method you need a background with a seamless texture that covers the whole camera view, then a controller that allows for 2d movement. Drop the Player GameObject onto the public GameObject and the backgrounds material onto the Material section. You need to include the /100, realistically anything greater then /10 will work. Each tile is worth 1 unity unit. So if your player GameObject were to move 1 unit the background would go to a new tile.
public Material material;
public GameObject player;
void Start()
{
material = renderer.material;
}
void FixedUpdate()
{
renderer.material.mainTextureOffset = new Vector2(player.transform.position.x / 100, player.transform.position.y / 100);
}
Unity 5: Creating New Movement System
2 Hours Research
2 Hours Code/Assets
After several hours of playing with codes and figuring out how rays work I created a new movement system for the spaceship. It now turns to where ever the mouse is pointing, all I need now is a way to make it slow down. I know of one method Quaternion.Slerp but I cannot get it to work. The movement part of the system uses a force multiplier system, if you use drag and angular drag on the ridged body it accounts for a autoslow and max speed system. Its not the best but it will do for now.
Add a new layer, call it "Floor" change the background to the layer Floor.
Add to top variables
//Movement Variables
Rigidbody playerRigidbody; // Reference to the player's rigidbody.
int floorMask; // A layer mask so that a ray can be cast just at gameobjects on the floor layer.
float camRayLength = 1000f; // The length of the ray from the camera into the scene.
Vector3 rotationFix = new Vector3(0, 0, 0);
public float movementSpeed = 5.0f;
Add Awake to the top Clear out Fixed update and add
void Awake ()
{
// Create a layer mask for the floor layer.
floorMask = LayerMask.GetMask ("Floor");
// Set up references.
playerRigidbody = GetComponent <Rigidbody> ();
}
// Transform direction is dependant on what angle you are using.
void FixedUpdate () // FixedUpdate runs with physics
{
if (Input.GetKey(KeyCode.W))
{
playerRigidbody.AddForce(transform.up * movementSpeed);
}
else if (Input.GetKey(KeyCode.S))
{
playerRigidbody.AddForce(transform.up * movementSpeed);
}
else if (Input.GetKey(KeyCode.A))
{
playerRigidbody.AddForce(-transform.forward * movementSpeed);
}
else if (Input.GetKey(KeyCode.D))
{
playerRigidbody.AddForce(transform.forward * movementSpeed);
}
// Turn the player to face the mouse cursor.
Turning();
// Animate the player.
}
void Turning()
{
// Create a ray from the mouse cursor on screen in the direction of the camera.
Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);
// Create a RaycastHit variable to store information about what was hit by the ray.
RaycastHit floorHit;
// Perform the raycast and if it hits something on the floor layer...
if (Physics.Raycast(camRay, out floorHit, camRayLength, floorMask))
{
// Create a vector from the player to the point on the floor the raycast from the mouse hit.
Vector3 playerToMouse = floorHit.point - transform.position;
// Ensure the vector is entirely along the floor plane. Axis must be the only one not being used by the player to move in.
playerToMouse.z = 0f;
// Create a quaternion (rotation) based on looking down the vector from the player to the mouse.
Quaternion newRotatation = Quaternion.LookRotation(playerToMouse);
//Quaternion.Euler is to correct for the 2d angle.
newRotatation *= Quaternion.Euler(90, 0, 0);
// Set the player's rotation to this new rotation.
playerRigidbody.MoveRotation(newRotatation);
}
}
2 Hours Code/Assets
After several hours of playing with codes and figuring out how rays work I created a new movement system for the spaceship. It now turns to where ever the mouse is pointing, all I need now is a way to make it slow down. I know of one method Quaternion.Slerp but I cannot get it to work. The movement part of the system uses a force multiplier system, if you use drag and angular drag on the ridged body it accounts for a autoslow and max speed system. Its not the best but it will do for now.
Add a new layer, call it "Floor" change the background to the layer Floor.
Add to top variables
//Movement Variables
Rigidbody playerRigidbody; // Reference to the player's rigidbody.
int floorMask; // A layer mask so that a ray can be cast just at gameobjects on the floor layer.
float camRayLength = 1000f; // The length of the ray from the camera into the scene.
Vector3 rotationFix = new Vector3(0, 0, 0);
public float movementSpeed = 5.0f;
Add Awake to the top Clear out Fixed update and add
void Awake ()
{
// Create a layer mask for the floor layer.
floorMask = LayerMask.GetMask ("Floor");
// Set up references.
playerRigidbody = GetComponent <Rigidbody> ();
}
// Transform direction is dependant on what angle you are using.
void FixedUpdate () // FixedUpdate runs with physics
{
if (Input.GetKey(KeyCode.W))
{
playerRigidbody.AddForce(transform.up * movementSpeed);
}
else if (Input.GetKey(KeyCode.S))
{
playerRigidbody.AddForce(transform.up * movementSpeed);
}
else if (Input.GetKey(KeyCode.A))
{
playerRigidbody.AddForce(-transform.forward * movementSpeed);
}
else if (Input.GetKey(KeyCode.D))
{
playerRigidbody.AddForce(transform.forward * movementSpeed);
}
// Turn the player to face the mouse cursor.
Turning();
// Animate the player.
}
void Turning()
{
// Create a ray from the mouse cursor on screen in the direction of the camera.
Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);
// Create a RaycastHit variable to store information about what was hit by the ray.
RaycastHit floorHit;
// Perform the raycast and if it hits something on the floor layer...
if (Physics.Raycast(camRay, out floorHit, camRayLength, floorMask))
{
// Create a vector from the player to the point on the floor the raycast from the mouse hit.
Vector3 playerToMouse = floorHit.point - transform.position;
// Ensure the vector is entirely along the floor plane. Axis must be the only one not being used by the player to move in.
playerToMouse.z = 0f;
// Create a quaternion (rotation) based on looking down the vector from the player to the mouse.
Quaternion newRotatation = Quaternion.LookRotation(playerToMouse);
//Quaternion.Euler is to correct for the 2d angle.
newRotatation *= Quaternion.Euler(90, 0, 0);
// Set the player's rotation to this new rotation.
playerRigidbody.MoveRotation(newRotatation);
}
}
Subscribe to:
Posts (Atom)