FishBehaviour CreateAgent(List <Transform> transforms, int i)
        {
            Transform agentTransform = Instantiate(prefab).transform;
            float     scale          = Random.Range(minScale, maxScale);

            agentTransform.localScale = new Vector3(scale, scale, scale);
            transforms.Add(agentTransform);
            agentTransform.position = groupAnchor;
            agentTransform.SetParent(flockingParent);

            FishBehaviour ab = new FishBehaviour();

            ab.acceleration         = Random.Range(minAcceleration, maxAcceleration);
            ab.speed                = Random.Range(minSpeed, maxSpeed);
            ab.force                = Random.Range(minForce, maxForce);
            ab.turnSpeed            = Random.Range(minTurnSpeed, maxTurnSpeed);
            ab.radius               = fishSize;
            ab.scaredTime           = 0.0f;
            ab.distFromNeighbour    = neighbourDistance;
            ab.currentPos           = agentTransform.position;
            ab.destination          = followTarget ? target.position : agentTransform.position;
            agentTransform.position = ab.currentPos;
            ab.velocity             = new Vector3(0, 0, 0);
            ab.distFromPredator     = 18;
            ab.id        = fishIdEnum++;
            ab.transform = agentTransform;

            return(ab);
        }
Beispiel #2
0
        static Vector3 Cohesion(FishBehaviour agent, List <FishBehaviour> otherAgents, int agentsCount, int index)
        {
            Vector3 sum = vzero;
            float   desiredSeparation = agent.radius * agent.distFromNeighbour;
            int     count             = 0;

            for (int i = 0; i < agentsCount; i++)
            {
                FishBehaviour otherAgent = otherAgents[i];

                if (i != index)
                {
                    Vector3 dist    = agent.currentPos - otherAgent.currentPos;
                    float   distmag = MagnitudeVector(dist);

                    if (distmag > 0 && distmag < desiredSeparation)
                    {
                        sum += otherAgent.currentPos;
                        count++;
                    }
                }
            }

            if (count > 0 && sum != vzero)
            {
                sum /= count;
                return(Seek(sum, agent.currentPos, agent.velocity, agent.speed, agent.force));
            }

            return(vzero);
        }
Beispiel #3
0
        static Vector3 Separate(FishBehaviour agent, List <FishBehaviour> otherAgents, int agentsCount, int index, Predator[] predators)
        {
            Vector3 sum               = vzero;
            int     count             = 0;
            float   desiredSeparation = agent.radius * agent.distFromNeighbour;

            for (int i = 0; i < agentsCount; i++)
            {
                if (i != index)
                {
                    FishBehaviour otherAgent = otherAgents[i];

                    Vector3 dist    = agent.currentPos - otherAgent.currentPos;
                    float   distmag = MagnitudeVector(dist);

                    System.Random r = new System.Random();

                    if (distmag <= 0)
                    {
                        tempVec.x = otherAgent.currentPos.x + (r.Next((int)(-desiredSeparation + (desiredSeparation / 2)), (int)(desiredSeparation - (desiredSeparation / 2))));
                        tempVec.y = otherAgent.currentPos.y + (r.Next((int)(-desiredSeparation + (desiredSeparation / 2)), (int)(desiredSeparation - (desiredSeparation / 2))));
                        tempVec.z = otherAgent.currentPos.z + (r.Next((int)(-desiredSeparation + (desiredSeparation / 2)), (int)(desiredSeparation - (desiredSeparation / 2))));

                        dist    = agent.currentPos - tempVec;
                        distmag = MagnitudeVector(dist);
                    }

                    if (distmag > 0 && distmag < desiredSeparation)
                    {
                        Vector3 diff = dist;
                        diff  = NormalizeVector(diff);
                        diff /= distmag;

                        sum += diff;
                        count++;
                    }
                }
            }

            desiredSeparation = agent.radius * agent.distFromPredator;

            if (count > 0 && sum != vzero)
            {
                sum /= count;

                sum  = NormalizeVector(sum);
                sum *= agent.speed;

                return(Steer(sum, agent.velocity, agent.force));
            }

            return(vzero);
        }
Beispiel #4
0
        void Update()
        {
            float minX = controller.groupAnchor.x - (controller.groupAreaWidth / 2);
            float maxX = controller.groupAnchor.x + (controller.groupAreaWidth / 2);
            float minY = controller.groupAnchor.y - (controller.groupAreaHeight / 2);
            float maxY = controller.groupAnchor.y + (controller.groupAreaHeight / 2);
            float minZ = controller.groupAnchor.z - (controller.groupAreaDepth / 2);
            float maxZ = controller.groupAnchor.z + (controller.groupAreaDepth / 2);

            if (currChangePositionRate < Time.time)
            {
                lastTargetPos.x = Random.Range(minX, maxX);
                lastTargetPos.y = Random.Range(minY, maxY);
                lastTargetPos.z = Random.Range(minZ, maxZ);
                vecToFollow     = lastTargetPos - myTransform.position;

                currChangePositionRate = Time.time + changePositionRate;
            }

            myTransform.position += myTransform.forward * Time.deltaTime * speed;

            Quaternion futureRotation = Quaternion.LookRotation(vecToFollow);

            if (futureRotation.eulerAngles.magnitude > 0.1f)
            {
                myTransform.rotation = Quaternion.Slerp(myTransform.rotation, futureRotation, Time.smoothDeltaTime * turnSpeed);
            }

            currentPosition = myTransform.position;

            for (int i = 0; i < controller.behaviours.Count; i++)
            {
                FishBehaviour b = controller.behaviours[i];

                if ((b.currentPos - mouth.position).magnitude < b.radius)
                {
                    controller.KillFish(i, b.id);
                    GameObject bloodInstance = Instantiate(blood, mouth.position, blood.transform.rotation);
                    Destroy(bloodInstance, 2f);
                }
            }
        }
        FishBehaviour CreatePureAgent(int i)
        {
            //float scale = Random.Range(minScale, maxScale);

            FishBehaviour ab = new FishBehaviour();

            ab.acceleration      = Random.Range(minAcceleration, maxAcceleration);
            ab.speed             = Random.Range(minSpeed, maxSpeed);
            ab.force             = Random.Range(minForce, maxForce);
            ab.turnSpeed         = Random.Range(minTurnSpeed, maxTurnSpeed);
            ab.radius            = fishSize;
            ab.scaredTime        = 0.0f;
            ab.distFromNeighbour = neighbourDistance;
            ab.currentPos        = groupAnchor;
            ab.destination       = followTarget ? target.position : groupAnchor;
            ab.velocity          = new Vector3(0, 0, 0);
            ab.distFromPredator  = 18;
            ab.id        = fishIdEnum++;
            ab.transform = null;

            return(ab);
        }
        void CheckForObstacles(FishBehaviour ab, ref Vector3 targetDirection, Vector3 tposition, Vector3 tforward)
        {
            RaycastHit hit;
            Vector3    forward = tforward;
            Vector3    pos     = tposition;

            //if (frameSkipAmountCount == 0)

            //forward cast
            CheckObstacle(pos, forward, out hit, lookAheadDistance, collisionAvoidLayer, ref targetDirection, 0);

            //left raycast
            Vector3 left = pos;

            left.x -= .5f;
            CheckObstacle(left, forward, out hit, lookSideDistance, collisionAvoidLayer, ref targetDirection, 1);

            //right raycast
            Vector3 right = pos;

            right.x += .5f;
            CheckObstacle(right, forward, out hit, lookSideDistance, collisionAvoidLayer, ref targetDirection, 2);
        }
        void Update()
        {
            if (swimOnLocalSpace)
            {
                flockingParent.position = groupAnchor;
            }

            if (frameSkipAmountCount >= frameSkipAmount)
            {
                frameSkipAmountCount = 0;
            }

            deltaTime = Time.deltaTime;
            UpdateTempVariables();

            if (requestedCalculation)
            {
                FlockMain.eventLock.Set();
            }

            UpdateParent();

            float minX = groupAnchor.x - (groupAreaWidth / 2);
            float maxX = groupAnchor.x + (groupAreaWidth / 2);
            float minY = groupAnchor.y - (groupAreaHeight / 2);
            float maxY = groupAnchor.y + (groupAreaHeight / 2);
            float minZ = groupAnchor.z - (groupAreaDepth / 2);
            float maxZ = groupAnchor.z + (groupAreaDepth / 2);

            for (int i = 0; i < lastAgentsAmount; i++)
            {
                FishBehaviour behaviour = behaviours[i];
                if (behaviour.transform == null)
                {
                    continue;
                }

                Transform  btransform         = agentsTransforms[i];
                Vector3    btransformPosition = btransform.position;
                Vector3    btransformForward  = btransform.rotation * Vec3Forward;
                Quaternion btransformRotation = btransform.rotation;

                Vector3 targetDirection = behaviour.targetDirection;

                CheckForObstacles(behaviour, ref targetDirection, btransformPosition, btransformForward);

                Quaternion rotation = behaviour.targetDirectionMagnitude < 0.2f ? btransformRotation : Quaternion.LookRotation(targetDirection);
                btransformRotation = Quaternion.Slerp(btransformRotation, rotation, behaviour.turnSpeed * deltaTime);

                btransformPosition  += btransformForward * deltaTime * behaviour.acceleration;
                behaviour.currentPos = btransformPosition;

                if (attackTarget)
                {
                    behaviour.seek        = true;
                    behaviour.destination = targetToAttackTransform.position;
                }
                else
                {
                    bool lookForRandomPos = true;
                    if (forceGroupAreaDestination)
                    {
                        lookForRandomPos = !behaviour.outOfBounds;
                    }

                    if (lookForRandomPos)
                    {
                        behaviour.seek = true;

                        Vector3 newDestination = behaviour.destination;
                        if ((newDestination - behaviour.currentPos).magnitude < 2f)
                        {
                            float xr = Random.Range(minX, maxX);
                            float yr = Random.Range(minY, maxY);
                            float zr = Random.Range(minZ, maxZ);

                            newDestination.x      = xr;
                            newDestination.y      = yr;
                            newDestination.z      = zr;
                            behaviour.destination = newDestination;
                        }
                    }
                }

                behaviour.outOfBounds = false;
                if (btransformPosition.x > maxX || btransformPosition.x < minX ||
                    btransformPosition.y > maxY || btransformPosition.y < minY ||
                    btransformPosition.z > maxZ || btransformPosition.z < minZ)
                {
                    behaviour.destination = groupAnchor;
                    behaviour.outOfBounds = true;
                    behaviour.seek        = true;

                    if (forceGroupAreaDestination)
                    {
                        rotation           = Quaternion.LookRotation(groupAnchor - btransformPosition);
                        btransformRotation = Quaternion.Slerp(btransformRotation, rotation, behaviour.turnSpeed * deltaTime);
                    }
                }

                if (refreshVariables)
                {
                    behaviour.acceleration = Random.Range(minAcceleration, maxAcceleration);
                    behaviour.speed        = Random.Range(minSpeed, maxSpeed);
                    behaviour.force        = Random.Range(minForce, maxForce);
                    behaviour.turnSpeed    = Random.Range(minTurnSpeed, maxTurnSpeed);
                }

                {
                    btransform.rotation = btransformRotation;
                    btransform.position = btransformPosition;
                }

                if (OnUpdateFishEvent != null)
                {
                    behaviour = OnUpdateFishEvent(behaviour);
                }
                behaviours[i] = behaviour;
            }

            refreshVariables = false;

            if (frameSkipAmountCount == 0)
            {
                if (!requestedCalculation && FlockMain.can_request)
                {
                    if (my_id == last_controller_to_request)
                    {
                        for (int i = 0; i < queueToClear.Count; i++)
                        {
                            int behaviourIndex = behaviours.FindIndex(it => it.id == queueToClear[i]);

                            FishBehaviour behaviour = behaviours[behaviourIndex];

                            Transform t = behaviour.transform;
                            agentsTransforms.Remove(t);

                            behaviours.RemoveAt(behaviourIndex);
                            Destroy(t.gameObject, 2f);

                            fishAmount--;
                            lastAgentsAmount = fishAmount;
                        }

                        queueToClear.Clear();

                        request.behaviours                = new List <FishBehaviour>(behaviours);
                        request.predators                 = predators;
                        request.separationScale           = separationScale;
                        request.alignmentScale            = alignmentScale;
                        request.cohesionScale             = cohesionScale;
                        request.forceGroupAreaDestination = forceGroupAreaDestination;

                        FlockMain.Request(request);
                        requestedCalculation = true;

                        Debug.Log(gameObject.name + " requesting calculation");

                        last_controller_to_request++;
                        if (last_controller_to_request >= controllers.Count)
                        {
                            last_controller_to_request = 0;
                        }
                    }
                }
            }
            else
            {
                RefreshAgents();
            }

            frameSkipAmountCount++;
        }
Beispiel #8
0
        static void CalculateBehaviours()
        {
            if (!has_request)
            {
                return;
            }

            List <FishBehaviour> behaviours = the_request.behaviours;

            Predator[] predators                 = the_request.predators;
            float      separationScale           = the_request.separationScale;
            float      alignmentScale            = the_request.alignmentScale;
            float      cohesionScale             = the_request.cohesionScale;
            bool       forceGroupAreaDestination = the_request.forceGroupAreaDestination;

            for (int i = 0; i < behaviours.Count; i++)
            {
                behavioursLimitC++;

                if (behavioursLimitC >= behavioursLimitCount)
                {
                    //Thread.Sleep(1);
                    behavioursLimitC = 0;
                }

                FishBehaviour agentBehaviour = behaviours[i];

                agentBehaviour.velocity = Vector3.zero;

                if (agentBehaviour.seek)
                {
                    Vector3 seekDestination = Seek(agentBehaviour.destination, agentBehaviour.currentPos, agentBehaviour.velocity, agentBehaviour.speed, agentBehaviour.force);

                    if (forceGroupAreaDestination)
                    {
                        agentBehaviour.velocity += seekDestination * (agentBehaviour.outOfBounds ? 3 : 1);
                    }
                    else
                    {
                        agentBehaviour.velocity += seekDestination;
                    }
                }

                if (!agentBehaviour.outOfBounds)
                {
                    for (int p = 0; p < predators.Length; p++)
                    {
                        Predator predator = predators[p];

                        float mag = MagnitudeVector(agentBehaviour.currentPos - predator.currentPosition);
                        if (mag <= predator.radius)
                        {
                            Evade(predator.currentPosition, agentBehaviour.currentPos, agentBehaviour.velocity, agentBehaviour.speed, agentBehaviour.force);
                        }
                    }
                }

                {
                    int     behavioursCount = behaviours.Count;
                    Vector3 sep             = Separate(agentBehaviour, behaviours, behavioursCount, i, predators);
                    Vector3 ali             = Align(agentBehaviour, behaviours, behavioursCount, i);
                    Vector3 coh             = Cohesion(agentBehaviour, behaviours, behavioursCount, i);

                    if (forceGroupAreaDestination)
                    {
                        if (!agentBehaviour.outOfBounds)
                        {
                            sep *= separationScale;
                            ali *= alignmentScale;
                            coh *= cohesionScale;
                        }
                        else
                        {
                            sep *= 0.5f;
                            ali *= 0.5f;
                            coh *= 0.5f;
                        }
                    }
                    else
                    {
                        sep *= separationScale;
                        ali *= alignmentScale;
                        coh *= cohesionScale;
                    }

                    agentBehaviour.velocity += sep;
                    agentBehaviour.velocity += ali;
                    agentBehaviour.velocity += coh;
                }

                agentBehaviour.targetDirection          = (((agentBehaviour.currentPos + agentBehaviour.velocity * 1.4f) - agentBehaviour.currentPos)).normalized;
                agentBehaviour.targetDirectionMagnitude = agentBehaviour.targetDirection.magnitude;

                behaviours[i] = agentBehaviour;
            }

            has_request = false;
            the_request.callback(behaviours);

            can_request = true;
        }