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); }
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); }
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); }
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++; }
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; }