Esempio n. 1
0
    public override void Initialize(Vector3 surfacePosition)
    {
        base.Initialize(surfacePosition);

        sampler.SampleMesh(false);

        meshBounds = sampler.Bounds;

        boids        = new Boid[numBoids];
        surfaceBoids = new SurfaceBoid[numBoids];
        boidMatrices = new Matrix4x4[numBoids];
        for (int i = 0; i < numBoids; i++)
        {
            Boid       b = new Boid();
            MeshSample s = sampler.Samples[Random.Range(0, sampler.Samples.Length)];
            b.Position = s.UV;
            b.Rotation = Random.Range(0, 360);
            boids[i]   = b;

            SurfaceBoid sb = new SurfaceBoid();
            sb.Offset       = Random.value;
            surfaceBoids[i] = sb;
        }

        forces = new Force[fingers.Length];
    }
Esempio n. 2
0
    private void DrawSurfaceBoids()
    {
        Vector3 scale = Vector3.one * boidScale;

        for (int i = 0; i < numBoids; i++)
        {
            SurfaceBoid b      = surfaceBoids[i];
            float       bounce = bounceCurve.Evaluate(Mathf.Repeat((b.Offset + Time.time) * (surfaceBounceSpeed * b.Agitation), 1f)) * surfaceBounce;
            boidMatrices[i] = Matrix4x4.TRS(b.Position + (b.Normal * bounce), b.Rotation, scale);
        }

        Graphics.DrawMeshInstanced(boidMesh, 0, boidMat, boidMatrices);
    }
Esempio n. 3
0
    private void UpdateBoids(float time, float deltaTime)
    {
        Vector2 sumPositions      = Vector2.zero;
        Vector2 sumVelocities     = Vector2.zero;
        Vector2 averagePosition   = Vector2.zero;
        Vector2 averageVelocity   = Vector2.zero;
        int     newNumBoidFleeing = 0;

        for (int i = 0; i < numBoids; i++)
        {
            Boid b = boids[i];
            sumPositions  += b.Position;
            sumVelocities += b.Velocity;
        }
        averagePosition = sumPositions / numBoids;
        averageVelocity = sumVelocities / numBoids;

        for (int b1i = 0; b1i < numBoids; b1i++)
        {
            Boid b1 = boids[b1i];

            Vector2 desiredAverageDirection = (averagePosition - b1.Position).normalized;
            Vector2 separationDirection     = Vector2.zero;
            Vector2 fleeDirection           = Vector2.zero;
            Vector2 forceAveragePosition    = Vector2.zero;
            Vector2 difference = Vector2.zero;

            int numBoidsInRange = 0;
            for (int b2i = 0; b2i < numBoids; b2i++)
            {
                if (b1i == b2i)
                {
                    continue;
                }

                Boid b2 = boids[b2i];

                float dist = DistanceBetween(b1.Position, b2.Position, ref difference);
                if (dist < minDistance)
                {
                    separationDirection += (difference.normalized / dist);
                    numBoidsInRange++;
                }
            }

            int numForcesInRange = 0;
            for (int fi = 0; fi < forces.Length; fi++)
            {
                Force f = forces[fi];
                if (!f.Enabled || !f.Active)
                {
                    continue;
                }

                float dist = DistanceBetween(b1.Position, f.Position, ref difference);
                if (dist < f.Radius)
                {
                    fleeDirection        += (difference.normalized / dist);
                    forceAveragePosition += f.Position;
                    numForcesInRange++;
                    newNumBoidFleeing++;
                }
            }

            // Alignment and coherence happen regardless of proximity
            Vector2 alignment   = Steer(b1.Velocity, averageVelocity);
            Vector2 coherence   = Steer(b1.Velocity, desiredAverageDirection);
            Vector2 newVelocity = (alignmentAmount * alignment) + (coherenceAmount * coherence);

            if (numBoidsInRange > 0)
            {
                // Separation happens if any boids were in range
                separationDirection = (separationDirection / numBoidsInRange).normalized;
                Vector2 separation = Steer(b1.Velocity, separationDirection * maxSpeed);
                newVelocity += (separationAmount * separation);
            }

            // Do a smooth lerp for alignment, coherence and separation
            b1.Velocity = Vector2.Lerp(b1.Velocity, LimitMagnitude(newVelocity, maxSpeed), deltaTime);

            if (numForcesInRange > 0)
            {
                // Flee is more disruptive
                // Use disance to force center to determine flee amount
                forceAveragePosition = (forceAveragePosition / numForcesInRange);
                fleeDirection        = (fleeDirection / numForcesInRange).normalized;
                float   distToForceCenter   = DistanceBetween(b1.Position, forceAveragePosition, ref difference);
                float   normalizedFleeForce = Mathf.Clamp01(distToForceCenter / forceRadius.y);
                Vector2 flee = Steer(b1.Velocity, fleeDirection * fleeAmount * normalizedFleeForce);
                // Don't limit flee velocity
                b1.Velocity = b1.Velocity + flee;
            }

            // Make sure boids don't go out of range
            Vector2 position = b1.Position + (b1.Velocity * deltaTime);
            position.x = Mathf.Repeat(position.x, 1);
            position.y = Mathf.Repeat(position.y, 1);

            b1.Position = position;
            b1.Rotation = Mathf.Lerp(b1.Rotation, Mathf.Atan2(b1.Velocity.y, b1.Velocity.x) * Mathf.Rad2Deg, deltaTime);

            boids[b1i] = b1;
        }

        numBoidsFleeing = newNumBoidFleeing;
        Vector3 origin = surfaceTransform.position;

        for (int i = 0; i < numBoids; i++)
        {
            Boid        b  = boids[i];
            SurfaceBoid sb = surfaceBoids[i];
            sb.Agitation = 1f + (b.Velocity.magnitude * agitationMultiplier);
            sb.Position  = SampleSurface(b.Position);
            sb.Normal    = (sb.Position - origin).normalized;
            Vector3 up = Quaternion.AngleAxis(b.Rotation, Vector3.forward) * Vector3.right;
            sb.Rotation = Quaternion.LookRotation(sb.Normal, up);

            surfaceBoids[i] = sb;
        }
    }