Permalink
Browse files

Enemies Now Flee Player

I tried to move a bunch of utility methods into a separate classfile,
LibRevel.cs. I apparently broke that though, and now enemies flee away
from the player at superspeed.

The TriggerEnter wasn't detecting the player ramming against the enemy.
Instead, I'll work around it for now by giving a distance check for a
very small amount of distance.

Also, it's likely that the raycasting is being projected from the center
of gameobjects instead of the bounds. In which ase, we should probably
factor in the radius from the center of enemies to its surface as an
additional factor of the length it needs to travel to reach a target.
  • Loading branch information...
Retl committed Apr 6, 2014
1 parent 9d6b9a1 commit d21cdaa8c4d87f8c4a2665a3a7d391aa337314e3
Showing with 166 additions and 103 deletions.
  1. +1 −0 Unity Project/Assembly-CSharp-vs.csproj
  2. +1 −0 Unity Project/Assembly-CSharp.csproj
  3. BIN Unity Project/Assets/TSHE_Scenes/defaultTestScene.unity
  4. +13 −32 Unity Project/Assets/TSHE_Scripts/EnemyBehavior/EnemyBoogerBehavior.cs
  5. +7 −3 Unity Project/Assets/TSHE_Scripts/EnemyBehavior/EnemyGenericBehavior.cs
  6. +2 −27 Unity Project/Assets/TSHE_Scripts/EnemyBehavior/EnemySlabBehavior.cs
  7. +13 −39 Unity Project/Assets/TSHE_Scripts/EnemyBehavior/EnemyStalkBehavior.cs
  8. +115 −0 Unity Project/Assets/TSHE_Scripts/LibRevel.cs
  9. +8 −0 Unity Project/Assets/TSHE_Scripts/LibRevel.cs.meta
  10. BIN Unity Project/Assets/TSHE_Textures/Materials/BoogerTexture.mat
  11. +4 −0 Unity Project/Assets/TSHE_Textures/Materials/BoogerTexture.mat.meta
  12. BIN Unity Project/Library/CurrentLayout.dwlt
  13. BIN Unity Project/Library/CurrentMaximizeLayout.dwlt
  14. BIN Unity Project/Library/InspectorExpandedItems.asset
  15. BIN Unity Project/Library/ScriptAssemblies/Assembly-CSharp-firstpass.dll
  16. BIN Unity Project/Library/ScriptAssemblies/Assembly-CSharp-firstpass.dll.mdb
  17. BIN Unity Project/Library/ScriptAssemblies/Assembly-CSharp.dll
  18. BIN Unity Project/Library/ScriptAssemblies/Assembly-CSharp.dll.mdb
  19. BIN Unity Project/Library/ScriptAssemblies/Assembly-UnityScript-firstpass.dll
  20. BIN Unity Project/Library/ScriptAssemblies/Assembly-UnityScript-firstpass.dll.mdb
  21. BIN Unity Project/Library/ScriptAssemblies/Assembly-UnityScript.dll
  22. BIN Unity Project/Library/ScriptAssemblies/Assembly-UnityScript.dll.mdb
  23. BIN Unity Project/Library/assetDatabase3
  24. BIN Unity Project/Library/guidmapper
  25. BIN Unity Project/Library/metadata/26/26ebd1f47951f4434892c20bcd5e3861
  26. BIN Unity Project/Library/metadata/32/326c2fd653b29c440b538d61b85d3423
  27. BIN Unity Project/Library/metadata/44/449b48f7eb5d87a4baaa5fb73f875a59
  28. BIN Unity Project/Library/metadata/46/46a3a5e7775298242a3313681369755a
  29. BIN Unity Project/Library/metadata/52/52e6313d7dae6b14bb9487a349bd28cd
  30. BIN Unity Project/Library/metadata/53/5317f3e76581f4165b16ede5caa5f14b
  31. BIN Unity Project/Library/metadata/5b/5b46d15a3262ca249954269444d32350
  32. BIN Unity Project/Library/metadata/95/95ed56a3a61301c458ebc55ebc6a608a
  33. BIN Unity Project/Library/metadata/af/af4d766417e9a9743a1936fa4ef3a354
  34. BIN Unity Project/Library/metadata/e5/e594ff7358075cc499aa20f5ef8cae51
  35. BIN Unity Project/Library/metadata/ed/ede9a2f73b7c7994b8355d00fba8c2f8
  36. BIN Unity Project/ProjectSettings/InputManager.asset
  37. +1 −1 Unity Project/Unity Project-csharp.sln
  38. +1 −1 Unity Project/Unity Project.sln
@@ -51,6 +51,7 @@
<Compile Include="Assets\TSHE_Scripts\EnemyBehavior\EnemySlabBehavior.cs" />
<Compile Include="Assets\TSHE_Scripts\EnemyBehavior\EnemyStalkBehavior.cs" />
<Compile Include="Assets\TSHE_Scripts\GameController.cs" />
<Compile Include="Assets\TSHE_Scripts\LibRevel.cs" />
<Compile Include="Assets\TSHE_Scripts\PickupBubble.cs" />
<Compile Include="Assets\TSHE_Scripts\PlayerController.cs" />
<None Include="Assets\Standard Assets\Projectors\Guidelines.txt" />
@@ -51,6 +51,7 @@
<Compile Include="Assets\TSHE_Scripts\EnemyBehavior\EnemySlabBehavior.cs" />
<Compile Include="Assets\TSHE_Scripts\EnemyBehavior\EnemyStalkBehavior.cs" />
<Compile Include="Assets\TSHE_Scripts\GameController.cs" />
<Compile Include="Assets\TSHE_Scripts\LibRevel.cs" />
<Compile Include="Assets\TSHE_Scripts\PickupBubble.cs" />
<Compile Include="Assets\TSHE_Scripts\PlayerController.cs" />
<None Include="Assets\Standard Assets\Projectors\Guidelines.txt" />
Binary file not shown.
@@ -11,6 +11,7 @@ public class EnemyBoogerBehavior : MonoBehaviour {
const float DAMAGE = 5f;
const float attackRange = 5f;
const float attackRate = 1.0f;
const float moveSpeed = 1.0f;

protected EnemyGenericBehavior genericEnemy;

@@ -24,9 +25,13 @@ void Start()
void FixedUpdate()
{
if (genericEnemy != null)
{
//Do stuff unique to Slabs.
}
{
GameObject thePlayer = LibRevel.FindClosestGameObjectWithTag(gameObject, "Player");
if (LibRevel.IsWithinDistanceThreshold(gameObject, thePlayer, attackRange))
{
LibRevel.FlyTowardsGameObject(gameObject, thePlayer, moveSpeed);
}
}
}

void OnTriggerEnter(Collider other)
@@ -51,25 +56,24 @@ void OnTriggerStay(Collider other)

//If the parent of the object we're colliding with is the player, Check to see if we are looking at eachother before dealing damage.
playerController = other.transform.parent.GetComponent<PlayerController>();
if (playerController != null && genericEnemy.attackCooldownTime <= 0)
if (playerController != null && genericEnemy.AttackCooldownTime <= 0)
{
genericEnemy.SmoothLookAt(playerController.transform.position);
if (genericEnemy.IsFacingPlayer(attackRange))
{
playerController.TakeDamage(DAMAGE);
genericEnemy.attackCooldownTime = attackRate; //Wait one second before able to attack again.
genericEnemy.AttackCooldownTime = attackRate; //Wait one second before able to attack again.
}
}

//If the object we're colliding with is the player, immediately attempt to deal damage.
playerController = other.GetComponent<PlayerController>();
if (playerController != null && genericEnemy.attackCooldownTime <= 0)
if (playerController != null && genericEnemy.AttackCooldownTime <= 0)
{
genericEnemy.SmoothLookAt(playerController.transform.position);
playerController.TakeDamage(DAMAGE);
genericEnemy.attackCooldownTime = attackRate; //Wait one second before able to attack again.
genericEnemy.AttackCooldownTime = attackRate; //Wait a bit before able to attack again.
}

}
}

@@ -83,30 +87,7 @@ void OnTriggerExit(Collider other)

#region Utility Methods

//I should move this into its own utility script class. - Moore
protected GameObject FindClosestGameObjectWithTag(string tagToFind)
{
GameObject result = null;
GameObject[] allObjects = GameObject.FindGameObjectsWithTag(tagToFind);

foreach (GameObject current in allObjects)
{
if (current != this.gameObject)
{
if (result == null)
{
result = current;
} else
{
if (Vector3.Distance(transform.position, result.transform.position) > Vector3.Distance(transform.position, current.transform.position))
{
result = current;
}
}
}
}
return result;
}


#endregion Utility Methods
}
@@ -8,8 +8,11 @@

public class EnemyGenericBehavior : MonoBehaviour
{
//Properties that should not change during runtime.
public float ContactDistance = 2f;

public float attackCooldownTime = 0.0f;
//Properties that will change frequently.
public float AttackCooldownTime = 0.0f;

// Use this for initialization
void Start()
@@ -20,9 +23,9 @@ void Start()
// Update is called once per frame
void FixedUpdate()
{
if (attackCooldownTime > 0)
if (AttackCooldownTime > 0)
{
attackCooldownTime -= Time.fixedDeltaTime;
AttackCooldownTime -= Time.fixedDeltaTime;
}
}

@@ -76,6 +79,7 @@ public void SmoothLookAt(Vector3 target)
Quaternion rotation = Quaternion.LookRotation((new Vector3(target.x, target.y, target.z) - transform.position));
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * GameController.DAMPING);
}


#endregion Utility Methods

@@ -46,13 +46,13 @@ void OnTriggerStay(Collider other)
print("Trigger Stay by: " + other.ToString());
}
PlayerController playerController = other.transform.parent.GetComponent<PlayerController>();
if (playerController != null && genericEnemy.attackCooldownTime <= 0)
if (playerController != null && genericEnemy.AttackCooldownTime <= 0)
{
genericEnemy.SmoothLookAt(playerController.transform.position);
if (genericEnemy.IsFacingPlayer(attackRange))
{
playerController.TakeDamage(DAMAGE);
genericEnemy.attackCooldownTime = attackRate; //Wait one second before able to attack again.
genericEnemy.AttackCooldownTime = attackRate; //Wait one second before able to attack again.
}
}
}
@@ -67,31 +67,6 @@ void OnTriggerExit(Collider other)
}

#region Utility Methods

//I should move this into its own utility script class. - Moore
protected GameObject FindClosestGameObjectWithTag(string tagToFind)
{
GameObject result = null;
GameObject[] allObjects = GameObject.FindGameObjectsWithTag(tagToFind);

foreach (GameObject current in allObjects)
{
if (current != this.gameObject)
{
if (result == null)
{
result = current;
} else
{
if (Vector3.Distance(transform.position, result.transform.position) > Vector3.Distance(transform.position, current.transform.position))
{
result = current;
}
}
}
}
return result;
}

#endregion Utility Methods
}
@@ -12,6 +12,9 @@ public class EnemyStalkBehavior : MonoBehaviour {
const float DAMAGE = 7f;
const float attackRange = 20f;
const float attackRate = 2.0f;
const float moveSpeed = 3.0f;



protected EnemyGenericBehavior genericEnemy;

@@ -26,7 +29,11 @@ void FixedUpdate()
{
if (genericEnemy != null)
{
//Do stuff unique to Slabs.
GameObject thePlayer = LibRevel.FindClosestGameObjectWithTag(gameObject, "Player");
if (LibRevel.IsWithinDistanceThreshold(gameObject, thePlayer, attackRange))
{
LibRevel.FlyTowardsGameObject(gameObject, thePlayer, moveSpeed);
}
}
}

@@ -45,31 +52,22 @@ void OnTriggerStay(Collider other)

if (GameController.Testing)
{
print("Trigger Stay by: " + other.ToString());
//print("Trigger Stay by: " + other.ToString());
}

PlayerController playerController;

//If the parent of the object we're colliding with is the player, Check to see if we are looking at eachother before dealing damage.
playerController = other.transform.parent.GetComponent<PlayerController>();
if (playerController != null && genericEnemy.attackCooldownTime <= 0)
if (playerController != null && genericEnemy.AttackCooldownTime <= 0)
{
genericEnemy.SmoothLookAt(playerController.transform.position);
if (genericEnemy.IsFacingPlayer(attackRange))
if (genericEnemy.IsFacingPlayer(attackRange) || LibRevel.IsWithinDistanceThreshold(gameObject, playerController.gameObject, genericEnemy.ContactDistance))
{
playerController.TakeDamage(DAMAGE);
genericEnemy.attackCooldownTime = attackRate; //Wait one second before able to attack again.
genericEnemy.AttackCooldownTime = attackRate; //Wait one second before able to attack again.
}
}

//If the object we're colliding with is the player, immediately attempt to deal damage.
playerController = other.GetComponent<PlayerController>();
if (playerController != null && genericEnemy.attackCooldownTime <= 0)
{
genericEnemy.SmoothLookAt(playerController.transform.position);
playerController.TakeDamage(DAMAGE);
genericEnemy.attackCooldownTime = attackRate; //Wait one second before able to attack again.
}
}
}

@@ -82,31 +80,7 @@ void OnTriggerExit(Collider other)
}

#region Utility Methods

//I should move this into its own utility script class. - Moore
protected GameObject FindClosestGameObjectWithTag(string tagToFind)
{
GameObject result = null;
GameObject[] allObjects = GameObject.FindGameObjectsWithTag(tagToFind);

foreach (GameObject current in allObjects)
{
if (current != this.gameObject)
{
if (result == null)
{
result = current;
} else
{
if (Vector3.Distance(transform.position, result.transform.position) > Vector3.Distance(transform.position, current.transform.position))
{
result = current;
}
}
}
}
return result;
}


#endregion Utility Methods
}
@@ -0,0 +1,115 @@
//Author Name: Carlis Moore
//Class Name: LibRevel.cs
//Class Purpose: A variety of utility and convenience methods I've found useful in multiple game development projects compiled together so that I don't have to perform copypasta surgery ever week.
using UnityEngine;
using System.Collections;

public static class LibRevel
{

const float DAMPING = 7f;

// User calls this method and passes the tag (as a string) they've applied to objects they wish to find. This will linearly search through all of them and pick the closest one with that tag. O(n).
public static GameObject FindClosestGameObjectWithTagWhileAvoiding(GameObject performer, string tagToFind, GameObject ignoreThisGameObject)
{
GameObject result = null;
GameObject[] allObjects = GameObject.FindGameObjectsWithTag(tagToFind);

foreach (GameObject current in allObjects)
{
if (current != ignoreThisGameObject && current != performer)
{
if (result == null)
{
result = current;
}

else
{
//Only change if the newest object we're looking at is the closest.
if (Vector3.Distance(performer.transform.position, result.transform.position) > Vector3.Distance(performer.transform.position, current.transform.position))
{
result = current;

}

}

}
}
return result;
}

public static GameObject FindClosestGameObjectWithTag(GameObject performer, string tagToFind)
{
return FindClosestGameObjectWithTagWhileAvoiding(performer, tagToFind, null);
}

public static GameObject FindClosestGameObjectWithTag(string tagToFind)
{
return FindClosestGameObjectWithTag(null, tagToFind);
}

//This takes three pairs of min and max values and picks a random Vector3 of floats that are constrainted to those passed values.
public static Vector3 RandomVector3InRange(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax)
{
float tempX = Random.Range(xMin, xMax);
float tempY = Random.Range(yMin, yMax);
float tempZ = Random.Range(zMin, zMax);

return new Vector3(tempX, tempY, tempZ);
}


public static void FlyTowardsGameObject(GameObject performer, GameObject destination, float movementSpeed)
{
//Precondition: You should only be calling this once per caller per FixedUpdate. - Moore
if (destination != null)
{
//Make sure to check that the target is within a desirable distance. So there should be a maximum distance variable. - Moore

/*
//Smooth turning position tracking... Maybe consider a version of this follow script that doesn't enforce headturning.
Quaternion rotation = Quaternion.LookRotation((new Vector3(destination.transform.position.x, destination.transform.position.y, destination.transform.position.z) - transform.position));
performer.transform.rotation = Quaternion.Slerp(performer.transform.rotation, rotation, Time.deltaTime * DAMPING);
*/

if (IsNotWithinDistanceThreshold(performer, destination, movementSpeed)) //WARNING: This movement speed is an assumption instead of a given threshold. Might be bad to have these two interconnected like this.
{
if (performer.rigidbody == null)
{
performer.transform.position += (Vector3.MoveTowards(performer.transform.position, destination.transform.position, movementSpeed));
}

else
{
performer.rigidbody.freezeRotation = true;
performer.rigidbody.AddForce(-performer.rigidbody.velocity);
performer.rigidbody.AddForce(Vector3.MoveTowards(performer.transform.position, destination.transform.position, movementSpeed * Time.fixedDeltaTime));
}
}
}
}

//Given two gameObjects and a float distance threshold, will check to see if the distance between the objects is within the threshold.
public static bool IsWithinDistanceThreshold(GameObject performer, GameObject destination, float threshold)
{
bool result = false;

if (Vector3.Distance(performer.transform.position, destination.transform.position) > threshold)
{ //If it is outside of the threshold...
result = false; //Return false. - Moore
} else
{ // Otherwise, return true. - Moore
return true;
}

return result;
}

//Convenience Negation Wrapper Method for the above:
public static bool IsNotWithinDistanceThreshold(GameObject performer, GameObject destination, float threshold)
{
return !IsWithinDistanceThreshold(performer, destination, threshold);
}
}
Oops, something went wrong.

0 comments on commit d21cdaa

Please sign in to comment.