Sample Code
flock.cs | |
File Size: | 5 kb |
File Type: | cs |
Flocking
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class flock : MonoBehaviour
{
private float c_attration = 5f;
private float c_repulsion = 10f;
//ignoring the 'ground' layer to avoid collisions with ground
public int collisionMask = 8;
//private
float m_fMoveSpeed;
float m_fRepelRange;
float m_fDetectRange;
Color m_repelColor = Color.cyan;
Color m_detectColor = Color.cyan;
public List m_detectionList = new List();
// in case of game objects with multiple components, counts number of objets at start
int numObjects = 1;
// Use this for initialization
void Start()
{
m_fMoveSpeed = 5.0f;
m_fRepelRange = 5f;
m_fDetectRange = 10f; //10
numObjects += transform.childCount;
}
void FixedUpdate()
{
Overlap();
Move( transform.InverseTransformDirection( sumOfForces() ) + MoveToEnemy() );
RotateToEnemy();
}
Vector3 MoveToEnemy()
{
Vector3 direction = Player.GetThisPlayer().gameObject.transform.position - transform.position;
return direction.normalized * 1000 ;
}
/*
* Does range detection and creates a list of transforms that are within specified ranges
* collision mask is included to ignore the ground, for loops added to ignore self-collisions
*/
void Overlap()
{
Collider[] detects = Physics.OverlapSphere(transform.position, m_fDetectRange, ~(1 << collisionMask));
m_detectionList.Clear();
//in detection range, ignore number of overlaps equal to number of gameobjects
//print (detects.Length);
//if (detects.Length > numObjects)
{
//adding to detection list
for (int i = 0; i < detects.Length; ++i)
{
if (!detects[i].transform.IsChildOf(gameObject.transform))// && detects[i].tag != "neutral" )
{
m_detectionList.Add(detects[i].transform);
Vector3 direction = detects[i].transform.position - transform.position;
float distance = direction.magnitude;
if (distance <= m_fRepelRange)
m_repelColor = Color.red;
else
m_repelColor = Color.cyan;
}
}
}
if (m_detectionList.Count > 0)
{
m_detectColor = Color.red;
}
else
{
m_detectColor = Color.cyan;
}
}
Vector3 sumOfForces()
{
Vector3 sumForce = Vector3.zero;
Vector3 sumAttract = Vector3.zero;
Vector3 sumRepolst = Vector3.zero;
int attractionCounter = 1;
for (int i = 0; i < m_detectionList.Count; ++i)
{
Vector3 direction = m_detectionList[i].position - transform.position;
float distance = direction.magnitude;
direction.Normalize();
if (distance <= m_fRepelRange)
{
direction *= -1;
sumRepolst += (direction * c_repulsion) / (distance * distance); //REPEL FORCE
}
else if (gameObject.CompareTag(m_detectionList[i].tag))
{
float neutralZone = .3f * (m_fDetectRange - m_fRepelRange) + m_fRepelRange;
if (distance > neutralZone)
{ // if your outside of the nretural range
sumAttract += (direction * c_attration) / (distance * distance); //Atraction FORCE
attractionCounter++;
}
}
else
{
direction *= -1;
sumRepolst += (direction * c_repulsion) / (distance * distance); //runaway
}
}
sumForce = (sumAttract / attractionCounter) + sumRepolst;
sumForce.y = 0;
return sumForce;
}
public void Move(Vector3 dir)
{
float s = dir.magnitude < m_fMoveSpeed ? dir.magnitude : m_fMoveSpeed;
dir.Normalize();
transform.Translate(dir * s * Time.deltaTime);
}
void OnDrawGizmos()
{
//visualize detection and repel range
Gizmos.color = m_repelColor;
Gizmos.DrawWireSphere(transform.position, m_fRepelRange);
Gizmos.color = m_detectColor;
Gizmos.DrawWireSphere(transform.position, m_fDetectRange);
}
void RotateToEnemy()
{
if(m_detectionList.Count<=0)
return;
float bestDist = 1e30f;
Vector3 bestPos = Vector3.zero;
for (int i = 0; i < m_detectionList.Count; ++i)
{
if ( m_detectionList[i].gameObject.tag == "Player")
{
Vector3 currentEnemy = m_detectionList[i].position - transform.position;
float dist = currentEnemy.magnitude;
if (dist <= bestDist)
{
bestPos = m_detectionList[i].position;
bestDist = dist;
}
}
}
bestPos.y = 0;
transform.LookAt(bestPos);
}
}