Пример #1
0
    public BoidNode[] GetUnitNeighbours(BoidNode boid, bool radialNeighbourhood = false, float radius = 1)
    {
        List <BoidNode> neighbours = new List <BoidNode>();
        int             radiusInt  = (int)Mathf.Ceil(radius);

        for (int x = -radiusInt; x <= radiusInt; x++)
        {
            for (int y = -radiusInt; y <= radiusInt; y++)
            {
                if ((!radialNeighbourhood && new Vector2(x, y).magnitude > radius))
                {
                    continue;
                }

                Node node   = NodeFromWorldPoint(boid.position);
                int  checkX = node.gridX + x;
                int  checkY = node.gridY + y;
                if (checkX >= 0 && checkX < gridSizeX && checkY >= 0 && checkY < gridSizeY)
                {
                    HashSet <BoidNode> neighboursXY = units[checkX, checkY];
                    foreach (BoidNode neighbour in neighboursXY)
                    {
                        if (boid.id != neighbour.id)
                        {
                            neighbours.Add(neighbour);
                        }
                    }
                }
            }
        }

        return(neighbours.ToArray());
    }
Пример #2
0
    void MoveTo(BoidNode currentWaypoint)
    {
        node = boid.node;

        // Influence of next checkpoint
        Vector3 steeringFromTarget = boid.VelocityTowards(currentWaypoint.position, 0, 0.5f);

        neighbourUnits = Grid.instance.GetUnitNeighbours(boid, false, 3);
        Vector3 steeringFromUnits = Flocker.ComputeSeparationForce(boid, neighbourUnits, radius, 1);

        Vector3 steeringFromSurroundings = ComputeSteeringFromObstacles(node, 1, 10);
        // Compose
        Vector3 steering = Vector3.ClampMagnitude(steeringFromTarget + steeringFromUnits + steeringFromSurroundings, steeringFromTarget.magnitude);

        steering = steering / boid.mass;

        // Floor influence
        float movementRatio = 1 - node.boidNode.penalty;

        boid.velocity = Vector3.ClampMagnitude(boid.velocity + steering, boid.maxSpeed * movementRatio);

        Grid.instance.RemoveUnit(boid);
        boid.position = boid.predictPosition(Time.deltaTime);
        Grid.instance.RegisterUnit(boid);
        transform.position = boid.position;
    }
Пример #3
0
    public static Vector3 ComputeAlignmentForce(BoidNode boid, BoidNode[] neighbourUnits, float maxRadius, float maxForce)
    {
        Vector3 force         = new Vector3();
        Vector3 velocity      = new Vector3();
        int     neighborCount = 0;

        foreach (BoidNode b in neighbourUnits)
        {
            if (b == boid)
            {
                continue;
            }
            float distance = boid.DistanceBetweenBorders(b);
            if (b != boid && distance < maxRadius)
            {
                velocity += b.velocity * (1 - distance / maxRadius) * boid.mass;
                neighborCount++;
            }
        }

        if (neighborCount != 0)
        {
            velocity = velocity / neighborCount;
            force.Normalize();
            force *= maxForce;
        }

        return(velocity);
    }
Пример #4
0
    public static Vector3 ComputeSeparationForce(BoidNode boid, BoidNode[] neighbourUnits, float maxRadius, float maxForce)
    {
        Vector3 force         = new Vector3();
        int     neighborCount = 0;

        foreach (BoidNode b in neighbourUnits)
        {
            if (b == boid)
            {
                continue;
            }
            float distance = boid.DistanceBetweenBorders(b);
            if (b != boid && distance < maxRadius)
            {
                force += (boid.position - b.position) * (1 - distance / maxRadius) * boid.mass;
                neighborCount++;
            }
        }

        if (neighborCount != 0)
        {
            force = force / (neighborCount);
            force.Normalize();
            force *= maxForce;
        }
        // Assume all the neigbours will make an equivalent effort
        return(force);
    }
Пример #5
0
    public static Vector3 ComputeCohesionForce(BoidNode boid, BoidNode[] neighbourUnits, float maxRadius, float maxForce)
    {
        Vector3 force         = new Vector3();
        Vector3 centroid      = new Vector3();
        int     neighborCount = 0;

        foreach (BoidNode b in neighbourUnits)
        {
            if (b == boid)
            {
                continue;
            }
            float distance = boid.DistanceBetweenBorders(b);
            if (b != boid && distance < maxRadius)
            {
                centroid += b.position * boid.mass;
                neighborCount++;
            }
        }

        if (neighborCount != 0)
        {
            centroid = centroid / neighborCount;
            float distance = boid.DistanceFromBorder(centroid);
            force = (boid.position - centroid) * Mathf.Max(1, distance / maxRadius);
            force.Normalize();
            force *= maxRadius;
        }
        return(force);
    }
Пример #6
0
 public bool WillCollide(BoidNode other, out Vector3 avoidanceSpeed, out Vector3 collisionPoint, int subSamples = 3)
 {
     if (this != other)
     {
         aheadVector = velocity.normalized * maxSeeAhead * velocity.magnitude / maxSpeed * Time.deltaTime;
         float distance = float.MaxValue;
         for (int sample = 0; sample <= subSamples; sample++)
         {
             Vector3 aheadPosition   = position + aheadVector * ((float)sample) / subSamples;
             float   currentDistance = other.DistanceFromBorder(aheadPosition) - this.hardRadius;
             if (currentDistance <= 0)
             {
                 distance       = currentDistance;
                 collisionPoint = aheadPosition;
                 avoidanceSpeed = collisionPoint - other.position;
                 avoidanceSpeed = -avoidanceSpeed.normalized * maxAvoidForce;
                 return(true);
             }
             else if (currentDistance < distance)
             {
                 distance = currentDistance;
             }
         }
     }
     avoidanceSpeed = Vector3.zero;
     collisionPoint = Vector3.zero;
     return(false);
 }
Пример #7
0
    public Node(bool _walkable, Vector3 _worldPos, int _gridX, int _gridY, int _penalty)
    {
        walkable        = _walkable;
        worldPosition   = _worldPos;
        gridX           = _gridX;
        gridY           = _gridY;
        movementPenalty = _penalty;


        pathfindingNode = new PathfindingNode(this);

        float normalizedPenalty = ((float)movementPenalty) / MaxMovementPenalty;

        if (walkable)
        {
            boidNode = new BoidNode(this, normalizedPenalty);
        }
        else
        {
            float radius = 0.5f;
            boidNode = new BoidNode(this, radius, normalizedPenalty, true);
            //boidNode.softRadius = radius;
            //boidNode.visibilityRadius = radius;
        }
    }
Пример #8
0
    public Vector3 VelocityAwayFrom(BoidNode other)
    {
        float   distance;
        Vector3 otherPosition   = InterceptPosition(other, out distance);
        Vector3 desiredVelocity = MaxSpeed(-(otherPosition - this.position));

        return(desiredVelocity);
    }
Пример #9
0
    public void RegisterUnit(BoidNode boid)
    {
        Node node = NodeFromWorldPoint(boid.position);

        boid.node = node;
        units[node.gridX, node.gridY].Add(boid);
        //print ("Added Boid  at ["+ node.gridX +"," + node.gridY+"] total:"+units[node.gridX,node.gridY].Count);
    }
Пример #10
0
    public Vector3 ComputeInfluence(BoidNode boid, BoidNode[] neighbourUnits, float separationFactor, float cohesionFactor, float alignmentFactor)
    {
        Vector3 separation = ComputeSeparationForce(boid, neighbourUnits, separationRadius, maxSeparationForce);
        Vector3 cohesion   = ComputeCohesionForce(boid, neighbourUnits, cohesionRadius, maxCohesionForce);
        Vector3 alignment  = ComputeAlignmentForce(boid, neighbourUnits, AlignmentRadius, maxAlignmentForce);
        Vector3 unitForce  = separation * separationFactor + cohesion * cohesionFactor + alignment * alignmentFactor;

        return(unitForce);
    }
Пример #11
0
    public void RemoveUnit(BoidNode boid)
    {
        Node node = NodeFromWorldPoint(boid.position);

        boid.node = null;
        units[node.gridX, node.gridY].Remove(boid);

        //print ("Removed Boid  at ["+ node.gridX +"," + node.gridY+"] total:"+units[node.gridX,node.gridY].Count);
    }
Пример #12
0
    Vector3 InterceptPosition(BoidNode other, out float distance)
    {
        Vector3 otherPosition = other.position;

        distance = DistanceFromBorder(other);
        float currentSpeed = velocity.magnitude;

        if (other.IsMoving() && currentSpeed > 0)
        {
            //  See where the other will be when this one arrives to that point)
            otherPosition = other.predictPosition(distance / currentSpeed);
            //  from now on, the target position is that one, so we need to update the distance
            distance = DistanceFromBorder(otherPosition);
        }
        return(otherPosition);
    }
Пример #13
0
    public Vector3 VelocityTowards(BoidNode other)
    {
        float   distance;
        Vector3 otherPosition   = InterceptPosition(other, out distance);
        Vector3 desiredVelocity = MaxSpeed(otherPosition - this.position);

        //Arrival
        if (distance < other.softRadius && distance >= other.hardRadius)
        {
            desiredVelocity *= ((distance - other.hardRadius) / (other.softRadius - other.hardRadius));
        }
        if (distance < other.hardRadius)
        {
            desiredVelocity = -velocity;
        }
        return(desiredVelocity);
    }
Пример #14
0
    public override bool Equals(System.Object obj)
    {
        // If parameter is null return false.
        if (obj == null)
        {
            return(false);
        }

        // If parameter cannot be cast to Point return false.
        BoidNode b = obj as BoidNode;

        if ((System.Object)b == null)
        {
            return(false);
        }

        // Return true if the fields match:
        return(b.id == this.id);
    }
Пример #15
0
 protected override void Initialize()
 {
     boid = new BoidNode(transform.position, radius);
     transform.localScale = Vector3.one * radius * 2;
     flock = new Flocker();
 }
Пример #16
0
 public void chase(BoidNode targetBoid)
 {
     PathRequestManager.RequestPath(boid.position, targetBoid.position, OnPathFound);
 }
Пример #17
0
 public int GetHashCode(BoidNode n)
 {
     return(n.id);
 }
Пример #18
0
    public float DistanceBetweenBorders(BoidNode other)
    {
        float distance = Vector3.Distance(other.position, this.position);

        return(distance - this.hardRadius - other.hardRadius);
    }
Пример #19
0
 void Start()
 {
     Grid.instance.RegisterUnit(boid);
     targetBoid = target.GetComponent <Unit>().boid;
 }
Пример #20
0
 protected override void Initialize()
 {
     boid = new BoidNode(transform.position, radius);
 }