void GetNearBoid() { float m = Mathf.Infinity; nearBoid = null; foreach (Boid b in boidGroup.boids) { float sm = (b.position - position).sqrMagnitude; if (sm != 0 && sm < m) { m = sm; nearBoid = b; } } m = Mathf.Infinity; target = null; foreach (BoidTarget bt in boidGroup.targets) { float sm = (bt.transform.position - position).sqrMagnitude / bt.strength; if (sm < m) { m = sm; target = bt; } } }
// Use this for initialization void Start () { firstTarget = CreateTarget(0); BoidTarget prevTarget = firstTarget; for (int i = 1; i < count; i++) { BoidTarget t = CreateTarget(i); t.nextTarget = prevTarget; prevTarget = t; } firstTarget.nextTarget = prevTarget; }
public void CreateBoid(Vector3 position, Vector3 launchDirection, BoidTarget target = null) { BoidBehaviour boid = (BoidBehaviour)Instantiate(boidPrefab, position, Quaternion.identity); boid.transform.parent = transform; boid.SoundManager = soundManager; boid.Launch(launchDirection); boid.target = target; activeBoids.Add(boid); }
private BoidTarget SelectGroupTarget(ref Dictionary<BoidTarget, int> counts, BoidTarget curTarget, BoidTarget newTarget) { int curTargetCount; if (curTarget != null && counts.ContainsKey(curTarget)) { curTargetCount = counts[curTarget]; } else { curTargetCount = 0; } int newTargetCount; if (counts.ContainsKey(newTarget)) { newTargetCount = counts[newTarget] + 1; counts[newTarget] = newTargetCount; } else { newTargetCount = 1; counts.Add(newTarget, newTargetCount); } if (newTargetCount > curTargetCount) { return newTarget; } else { return curTarget; } }
private void FlyUpdate(Vector3 playerPosition, Vector3 playerVelocity) { Vector3 toPlayer = playerPosition - transform.position; float toPlayerDist = toPlayer.magnitude; // modifications based on proximity to player float noise = Mathf.PerlinNoise(Time.time, noiseOffset) * 2f - 1f; float frameSpeed = maxSpeed * (1f + noise * speedVariance); bool targetPlayer = false; // find flock Collider[] colliders = Physics.OverlapSphere(transform.position, sensorRadius, sensorLayerMask, QueryTriggerInteraction.Ignore); // get flock center and velocity Vector3 flockCenter = Vector3.zero; Vector3 flockVelocity = Vector3.zero; Vector3 avoidance = Vector3.zero; int count = 0; scratch.Clear(); if (target != null) { target = SelectGroupTarget(ref scratch, target, target); } for (int i = 0; i < colliders.Length; i++) { BoidBehaviour boid = GetComponentCache.Instance.GetComponent<BoidBehaviour>(colliders[i]); if (boid != null && boid != this && boid.type == type) { flockCenter += boid.transform.position; flockVelocity += boid.velocity; count++; Vector3 toBoid = boid.transform.position - transform.position; float toBoidDist = toBoid.magnitude; if (toBoidDist < avoidanceDist) { avoidance -= (toBoid / toBoidDist) * (avoidanceDist - toBoidDist); } if (boid.target != null) { target = SelectGroupTarget(ref scratch, target, boid.target); } // also avoid segments if (type == BoidType.Giant) { SegmentBehaviour[] boidSegments = boid.Segments; for (int j = 0; j < boidSegments.Length; j++) { Vector3 toSegment = boidSegments[j].transform.position - transform.position; float toSegmentDist = toSegment.magnitude; if (toSegmentDist < avoidanceDist) { avoidance -= (toSegment / toSegmentDist) * (avoidanceDist - toSegmentDist); } } } continue; } } // special case: consider player a boid if (flockWithPlayer && toPlayerDist < playerSensorRadius) { if (!flockedWithPlayerLastFrame) { PlaySound(true); flockedWithPlayerLastFrame = true; } flockCenter += playerPosition; flockVelocity += playerVelocity; count++; if (toPlayerDist < avoidanceDist) { avoidance -= (toPlayer / toPlayerDist) * (avoidanceDist - toPlayerDist); } // new max speed float playerSpeed = playerVelocity.magnitude * (1f + noise * speedVariance); frameSpeed = Mathf.Max(frameSpeed, Mathf.Lerp(playerSpeed, playerSpeed * playerSpeedMult, Mathf.Clamp01(Mathf.InverseLerp(playerSensorRadius, avoidanceDist, toPlayerDist)))); targetPlayer = targetPlayerWhenClose; } else { flockedWithPlayerLastFrame = false; } // avoid phys collisions RaycastHit hit; if (Physics.SphereCast(transform.position, boidRadius, transform.forward, out hit, rayCastDist, collisionLayerMask)) { Vector3 avoidDir = Vector3.ProjectOnPlane(hit.normal, transform.forward).normalized; Vector3 avoidForce = Mathf.InverseLerp(rayCastDist, 0f, hit.distance) * avoidDir * physAvoidanceMultiplier; avoidance += avoidForce; Debug.DrawLine(hit.point, hit.point + avoidForce, Color.magenta); } // calc new velocity Vector3 newVelocity = Vector3.zero; // avoid other boids and obstacles newVelocity += avoidance * avoidanceWeight; if (count > 0) { flockCenter /= count; flockVelocity /= count; // move toward center of flock newVelocity += (flockCenter - transform.position) * centeringWeight; // match velocity newVelocity += flockVelocity * steeringWeight; } if (targetPlayer) { newVelocity += (playerPosition - transform.position) * targettingWeight; } else if (target != null) { if (target.InRange(transform.position)) { target = target.nextTarget; } newVelocity += (target.transform.position - transform.position) * targettingWeight; } // rotate towards new direction newVelocity = newVelocity.normalized * frameSpeed; float maxAngle = rotSpeed * Time.deltaTime; float goalAngle = Vector3.Angle(velocity, newVelocity); Quaternion newRotation; if (goalAngle > maxAngle) { newRotation = Quaternion.RotateTowards(Quaternion.LookRotation(velocity), Quaternion.LookRotation(newVelocity), maxAngle); } else { newRotation = Quaternion.LookRotation(newVelocity); } // find y rotation for roll calc float yRot = transform.rotation.eulerAngles.y - newRotation.eulerAngles.y; if (yRot < -180f) { yRot += 360f; } else if (yRot > 180f) { yRot -= 360f; } float rollGoal = Mathf.Clamp((yRot / Time.deltaTime) * rollCoef, -maxRoll, maxRoll); roll = Mathf.SmoothDampAngle(roll, rollGoal, ref rollVelocity, rollTime, rotSpeed); transform.rotation = newRotation; velocity = transform.forward * frameSpeed; transform.position += velocity * Time.deltaTime; // add roll Debug.DrawLine(transform.position, transform.position + transform.up * 2f, Color.green); transform.Rotate(0f, 0f, roll, Space.Self); Debug.DrawLine(transform.position, transform.position + transform.up * 2f, Color.green); }
void GetNearBoid() { float m = Mathf.Infinity; nearBoid = null; foreach(Boid b in boidGroup.boids){ float sm = (b.position - position).sqrMagnitude; if(sm != 0 && sm < m){ m = sm; nearBoid = b; } } m = Mathf.Infinity; target = null; foreach(BoidTarget bt in boidGroup.targets){ float sm = (bt.transform.position - position).sqrMagnitude/bt.strength; if(sm < m){ m = sm; target = bt; } } }